home projects random project
Goal: 61 / 1000

R100P0610A04 - assembly/04

Static Badge copy

« back 0610A04 next »

This is a part of R100P0917A00 .

This is where it got real. I actually finished this (according to file modified timestamps) two days after the last one, on September 9th, 2023. I don’t know what I was doing those two days, but it certainly had to have been brutal.

Anyways, after getting distracted with C, I went back to pure assembly. I was now going to try and render a full triangle. On the window, of course. Now it wouldn’t be that hard to pull off the actual code side of things – I’ve made a Hello Triangle project more times than I can count. It was just the assembly side of things that made it hard. I remember, while I was making it, consistently having on my second screen a table of the x86_64 call structure. I also constantly had to look at glfw.h to get values of constants that I needed for the functions.

But it works, and it’s in pure assembly! On my Linux machine, it compiles with: gcc -lglfw -lOpenGL -o program main.s. If the triangle doesn’t render on your machine, it could be that, since there is no shader rendering the triangle, the triangle just isn’t put on screen at all.

	.global main

	.section .rodata
.title: .string "HELLO, WORLD"

.F0: .string "GLFW error (0x%.08x): %s\n"

.ONE: .float 1.0
.TRI: .float -0.5, -0.5, 0.0
      .float  0.5, -0.5, 0.0
      .float  0.0,  0.5, 0.0
TRI_SIZE = . - .TRI

	.text

; glfw_error(int, char *)
glfw_error:
	push	%rbp
	mov	%rsp, %rbp

	mov 	%rsi, %rdx
	mov 	%edi, %esi
	lea 	.F0(%rip), %rdi
	xor	%al, %al
	call 	printf

	leave
	ret

glfw_resize:
	push 	%rbp
	mov	%rsp, %rbp

	mov	%edx, %ecx
	mov	%esi, %edx
	xor	%esi, %esi
	xor	%edi, %edi
	call	glViewport

	leave
	ret

main:
	push	%rbx
	sub	$16, %rsp
	
	lea	glfw_error(%rip), %rdi
	call	glfwSetErrorCallback

	call 	glfwInit
	cmp	$1, %eax
	jne 	exit

	; glfwCreateWindow(int, int, char *, void *, void *)
	mov	$640, %edi          ; 1st argument (width)
	mov	$480, %esi          ; 2nd argument (height)
	lea	.title(%rip), %rdx  ; 3rd argument
	xor	%ecx, %ecx          ; 4th
	xor	%r8d, %r8d          ; 5th
	call	glfwCreateWindow
	mov	%rax, %rbx

	mov	%rbx, %rdi
	call	glfwMakeContextCurrent
	mov	%rbx, %rdi
	lea	glfw_resize(%rip), %rsi
	call	glfwSetFramebufferSizeCallback

	; glViewport(0, 0, 640, 480)
	xor	%edi, %edi
	xor	%esi, %esi
	mov	$640, %edx
	mov	$480, %ecx
	call	glViewport

	; glClearColor(1.0, 0.0, 0.0, 1.0)
	movss	.ONE(%rip), %xmm0
	pxor	%xmm1, %xmm1
	pxor	%xmm2, %xmm2
	movss	.ONE(%rip), %xmm3
	call	glClearColor

	; glGenVertexArrays(1, &VAO)
	mov	$1, %edi
	lea	4(%rsp), %rsi
	call	glGenVertexArrays

	; glGenBuffers(1, &VBO_POS)
	mov	$1, %edi
	lea	8(%rsp), %rsi
	call	glGenBuffers

	; glBindVertexArray(VAO)
	mov	4(%rsp), %esi
	call	glBindVertexArray

	; glBindBuffer(GL_ARRAY_BUFFER, VBO_POS)
	mov	$0x8892, %edi
	mov	8(%rsp), %esi
	call	glBindBuffer

	; glBufferData(GL_ARRAY_BUFFER, sizeof(.TRI), .TRI, GL_STATIC_DRAW)
	mov	$0x8892, %edi
	mov	$TRI_SIZE, %esi
	lea	.TRI(%rip), %rdx
	mov	$0x88E4, %ecx
	call	glBufferData

	; glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 12, 0)
	xor	%edi, %edi
	mov	$3, %esi
	mov	$0x1406, %edx
	xor	%ecx, %ecx
	mov	$12, %r8d
	xor	%r9d, %r9d
	call	glVertexAttribPointer

	; glEnableVertexAttribArray(0)
	xor	%edi, %edi
	call	glEnableVertexAttribArray
	
	; glBindBuffer(GL_ARRAY_BUFFER, 0)
	mov	$0x8892, %edi
	xor	%esi, %esi
	call	glBindBuffer

loop:
	; glClear(GL_COLOR_BUFFER_BIT)
	mov	$0x4000, %edi
	call	glClear

	; glDrawArrays(GL_TRIANGLES, 0, 3)
	mov	$0x0004, %edi
	xor	%esi, %esi
	mov	$3, %edx
	call	glDrawArrays

	mov	%rbx, %rdi
	call	glfwSwapBuffers
	call	glfwPollEvents
	mov	%rbx, %rdi
	call	glfwWindowShouldClose
	test	%al, %al
	je	loop

	xor 	%al, %al
exit:
	add	$16, %rsp
	pop	%rbx
	ret

Raw file