Created
August 1, 2024 18:07
-
-
Save davawen/4852d7af032b585b845d767d2e1def6f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; nasm main.s -felf64 -o main.o | |
; gcc main.o -no-pie -lraylib -lm -o main | |
section .rodata | |
; read-only data: | |
; title is a list of bytes (`db`), ending with a null terminator | |
title: db "Raylib from Assembly :)", 0x0 | |
; SYSTEM-V calling convention: | |
; https://web.archive.org/web/20160801075139/http://www.x86-64.org/documentation/abi.pdf | |
; (see page 18-27) | |
; struct Color { u8 r; u8 g; u8 b; u8 a; }; | |
section .text | |
; declare entry point (that will be called by libc, since we are linking with gcc) | |
global main | |
; declare external symbols | |
extern InitWindow ; void(int width, int height, const char *title); | |
extern WindowShouldClose ; bool(); | |
extern CloseWindow ; void(); | |
extern BeginDrawing ; void(); | |
extern EndDrawing ; void(); | |
extern ClearBackground ; void(Color c); | |
extern DrawCircle ; void(int centerX, int centerY, float radius, Color color); | |
extern GetMouseX ; int(); | |
extern GetMouseY ; int(); | |
main: | |
; push stack frame (align stack pointer to 64 bit boundary) | |
push rbp | |
mov rbp, rsp | |
; load arguments for InitWindow | |
; integer arguments are loaded in this order: | |
; rdi, rsi, rdx, rcx, r8, r9 (see page 20) | |
mov rdi, 800 | |
mov rsi, 800 | |
lea rdx, [title] ; this instruction is "load effective address": we're getting the address of the title string | |
call InitWindow | |
; basically a while loop: | |
; the condition will be checked at the end of each loop, but we're jumping to it first so that it's also checked at the beginning | |
jmp close_test | |
loop: | |
call BeginDrawing | |
; for some reason, the `Color` struct is stored in a single register like this: | |
; AA BB GG RR | |
mov rdi, 0xffcfcfcf | |
call ClearBackground | |
; no input argument | |
call GetMouseX | |
push rax ; the return value is placed in the `rax` register (see page 21) | |
call GetMouseY | |
push rax | |
; right now, the stack looks like: | |
; TOP | |
; | Y value | | |
; | X value | | |
; | stack frame | | |
; | ... | | |
; we want to place the Y value in the second argument register (rsi) | |
; and the X value in the first argument register (rdi) | |
pop rsi | |
pop rdi | |
; "convert 32 bit signed integer into 32 bit float" | |
; so store 10.0 in floating point register | |
mov rax, 10 | |
cvtsi2ss xmm0, rax | |
; red color | |
mov rdx, 0xff0000ff | |
call DrawCircle ; <- draw red circle at the current mouse position | |
call EndDrawing | |
close_test: | |
; WindowShouldClose returns 0 if the window should stay open, and 1 if it should close | |
call WindowShouldClose | |
; return value is placed in rax | |
test rax, rax | |
; jump to the start of the loop if `rax` is zero, otherwise continue | |
jz loop | |
call CloseWindow | |
; leave main function | |
pop rbp | |
ret |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment