Skip to content

Instantly share code, notes, and snippets.

@davawen
Created August 1, 2024 18:07
Show Gist options
  • Save davawen/4852d7af032b585b845d767d2e1def6f to your computer and use it in GitHub Desktop.
Save davawen/4852d7af032b585b845d767d2e1def6f to your computer and use it in GitHub Desktop.
; 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