Setup
-
Install NASM (Assembler) :
-
Execute :
-
nasm -f win64 main.asm -o main.obj -
clang main.obj -o main.exe -L../raylib/lib -lraylib -lopengl32 -lgdi32 -lwinmm -
.\main.exe
-
Moving Ball
; nasm -f win64 main.asm -o main.obj
; clang main.obj -o main.exe -L../raylib/lib -lraylib -lopengl32 -lgdi32 -lwinmm
; .\main.exe
; or call everything in one line:
; nasm -f win64 main.asm -o main.obj&&clang main.obj -o main.exe -L../raylib/lib -lraylib -lopengl32 -lgdi32 -lwinmm&&.\main.exe
; nasm -f win64 main.asm -o main.obj&&clang main.obj -o main.exe -L../raylib/lib -lraylib -lopengl32 -lgdi32 -lwinmm -lmsvcrt&&.\main.exe
; nasm -f win64 main.asm -o main.obj&&clang main.obj -o main.exe -L../raylib/lib -lraylibdll -lopengl32 -lgdi32 -lwinmm&© ..\raylib\lib\raylib.dll . && .\main.exe
default rel ; Enables RIP-relative addressing by default (important for 64-bit position-independent code).
; Declares functions from raylib. These will be resolved during linking.
extern InitWindow
extern SetTargetFPS
extern WindowShouldClose
extern IsKeyDown
extern BeginDrawing
extern ClearBackground
extern DrawText
extern DrawCircleV
extern EndDrawing
extern CloseWindow
section .data
SCREEN_WIDTH dd 800
SCREEN_HEIGHT dd 450
half dd 0.5
speed dd 2.0
radius dd 50.0
; Null-terminated C strings.
msg db "move the ball_pos with arrow keys",0
title db "Raylib ASM",0
; key codes (raylib)
KEY_RIGHT equ 262
KEY_LEFT equ 263
KEY_UP equ 265
KEY_DOWN equ 264
RAYWHITE db 245,245,245, 255
DARKGRAY db 80, 80, 80, 255
MAROON db 190, 33, 55, 255
section .bss
ball_pos resq 1 ; Reserves 8 bytes (64 bits). Vector2 {x, y}
section .text
global main ; Entry point exported as main.
main:
sub rsp, 56 ; Allocates stack space. Required for: Windows ABI shadow space (32 bytes) + Stack alignment (16-byte aligned) + scratch space (8 bytes)
; InitWindow(int width, int height, const char *title)
mov ecx, [SCREEN_WIDTH]
mov edx, [SCREEN_HEIGHT]
lea r8, [title]
call InitWindow
; SetTargetFPS(60)
mov ecx, 60
call SetTargetFPS
; ball_pos.x = width * 0.5
cvtsi2ss xmm0, [SCREEN_WIDTH]
mulss xmm0, [half]
movss [ball_pos], xmm0
; ball_pos.y = height * 0.5
cvtsi2ss xmm0, [SCREEN_HEIGHT]
mulss xmm0, [half]
movss [ball_pos+4], xmm0
.loop:
call WindowShouldClose
test eax, eax
jnz .end
; RIGHT
mov ecx, KEY_RIGHT
call IsKeyDown
test al, 1 ; (2026-04-02) Fixed: returns a C bool which is only guaranteed to have a meaningful value in bit 0, and the upper bits of EAX were apparently garbage, making test eax, eax always nonzero (always "true")
jz .not_key_right_down
movss xmm0, [ball_pos]
addss xmm0, [speed]
movss [ball_pos], xmm0
.not_key_right_down:
; LEFT
mov ecx, KEY_LEFT
call IsKeyDown
test al, 1
jz .not_key_left_down
movss xmm0, [ball_pos]
subss xmm0, [speed]
movss [ball_pos], xmm0
.not_key_left_down:
; UP
mov ecx, KEY_UP
call IsKeyDown
test al, 1
jz .not_key_up_down
movss xmm0, [ball_pos+4]
subss xmm0, [speed]
movss [ball_pos+4], xmm0
.not_key_up_down:
; DOWN
mov ecx, KEY_DOWN
call IsKeyDown
test al, 1
jz .not_key_down_down
movss xmm0, [ball_pos+4]
addss xmm0, [speed]
movss [ball_pos+4], xmm0
.not_key_down_down:
; Draw
call BeginDrawing
mov eax, [RAYWHITE]
mov ecx, eax
call ClearBackground
; DrawText(msg, 10, 10, 20, color)
lea rcx, [msg]
mov edx, 10
mov r8d, 10
mov r9d, 20
mov eax, [DARKGRAY]
mov [rsp+32], eax
call DrawText
; DrawCircleV(Vector2 pos, float radius, Color color)
mov rcx, [ball_pos]
movss xmm1, [radius]
mov r8d, [MAROON]
call DrawCircleV
call EndDrawing
jmp .loop
.end:
call CloseWindow
xor eax, eax
add rsp, 56 ; Restore stack
ret ; return