Skip to content

Instantly share code, notes, and snippets.

@Liebranca
Last active October 31, 2024 15:33
Show Gist options
  • Save Liebranca/5e5e9678a17dd847618ec98ed4d41780 to your computer and use it in GitHub Desktop.
Save Liebranca/5e5e9678a17dd847618ec98ed4d41780 to your computer and use it in GitHub Desktop.
D&D dice set in flat assembler
; to compile: fasm dice.asm roll
; to run: ./roll 1d20 2d4 4d6 etc.
;
; --- * --- * ---
; info
format ELF64 executable 3;
entry _start;
define VERSION v0.00.6a;
define AUTHOR IBN-3DILA;
; --- * --- * ---
; utils
macro list_range dst,cnt {
local ok;
dst equ;
rept cnt idex \{
ok equ 1;
match any,dst \\{
dst equ dst,idex;
ok equ 0;
\\}
match =1,ok \\{
dst equ idex;
\\}
\};
};
macro _mkstrtab name,[elem] {
common name#_SRC:
forward match any , elem \{
.n\#any\#: db \`any,$0A,0;
.n\#any\#_len=$-.n\#any;
\};
common name#:
forward match any , elem \{
dw name#_SRC.n\#any-name#_SRC;
dw name#_SRC.n\#any\#_len;
\};
};
macro mkstrtab name,cnt {
local dst;
list_range dst,cnt;
match list,dst \{
_mkstrtab name,list;
\};
};
; --- * --- * ---
; ROM
segment readable;
DICETAB:
.d4 dq RPG.Dice_d4;
.d6 dq RPG.Dice_d6;
.d8 dq RPG.Dice_d8;
.d10 dq RPG.Dice_d10;
.d12 dq RPG.Dice_d12;
.d20 dq RPG.Dice_d20;
.d100 dq RPG.Dice_d100;
mkstrtab NUMTAB,100;
EOL db $0A;
errme db 'SNAFU',$0A;
errme.len=$-errme;
; --- * --- * ---
; GBL
segment readable writeable;
FOUT.sz=$100;
FOUT:
.ptr dw $00;
.buff db FOUT.sz dup $00
; --- * --- * ---
; EXE
segment readable executable;
align $10;
; --- * --- * ---
; generate random byte
RPG.Dice_xlamp:
mov rdx,rax
RPG.Dice_xlamp_anon@127:
rept 7 {
ror rdx,8
xor rax,rdx
}
xor rdx,rdx;
and rax,$FF
ret
RPG.Dice_prng:
rdtsc
shl rdx,32
or rax,rdx
call RPG.Dice_xlamp
ret
; --- * --- * ---
; ^map to diceroll!
RPG.Dice_d4:
call RPG.Dice_prng
and al,3
ret
RPG.Dice_d6:
call RPG.Dice_prng
mov rdi,rax
mov rax,683
imul rax,rdi
shr rax,12
lea rax,[rax*2]
lea rax,[rax+rax*2]
sub rdi,rax
mov rax,rdi
ret
RPG.Dice_d8:
call RPG.Dice_prng
and rax,7
ret
RPG.Dice_d10:
call RPG.Dice_prng
mov rdi,rax
mov rax,410
imul rax,rdi
shr rax,12
lea rax,[rax*2]
lea rax,[rax+rax*4]
sub rdi,rax
mov rax,rdi
ret
RPG.Dice_d12:
call RPG.Dice_prng
mov rdi,rax
mov rax,342
imul rax,rdi
shr rax,12
lea rax,[rax+rax*2]
lea rax,[rax*4]
sub rdi,rax
mov rax,rdi
ret
RPG.Dice_d20:
call RPG.Dice_prng
mov rdi,rax
mov rax,205
imul rax,rdi
shr rax,12
lea rax,[rax*4]
lea eax,[rax+rax*4]
sub rdi,rax
mov rax,rdi
ret
RPG.Dice_d100:
call RPG.Dice_prng
mov rdi,rax
mov rax,41
imul rax,rdi
shr rax,12
mov rdx,100
imul rax,rdx
sub rdi,rax
mov rax,rdi
ret
; --- * --- * ---
; entry point
_start:
; get argc
push rbp;
mov rbp,rsp;
sub rsp,$08;
; setup counter
define PENDING rbp+$08;
define NEXT rbp-$08;
mov rax,qword [rbp+$08];
dec rax;
mov qword [PENDING],rax;
mov qword [NEXT],$18;
; --- * --- * ---
; roll next dice!
.get_next:
; get counter
mov rax,qword [PENDING];
test rax,rax;
jz .skip;
dec qword [PENDING];
; get idex
mov rax,qword [NEXT];
add qword [NEXT],$08;
mov rax,qword [rbp+rax];
; read input string
mov r15b,byte [rax];
mov r14d,dword [rax+1];
; get number of copies to roll!
mov al,$30;
mov dl,$37;
cmp r15b,$39;
cmovg eax,edx;
sub r15b,al;
; ^match string to dice!
cmp r14w,word $3464;
cmovz r14,qword [DICETAB.d4];
cmp r14w,word $3664;
cmovz r14,qword [DICETAB.d6];
cmp r14w,word $3864;
cmovz r14,qword [DICETAB.d8];
cmp r14d,dword $303164;
cmovz r14,qword [DICETAB.d10];
cmp r14d,dword $323164;
cmovz r14,qword [DICETAB.d12];
cmp r14d,dword $00303264;
cmovz r14,qword [DICETAB.d20];
cmp r14w,word $2564;
cmovz r14,qword [DICETAB.d100];
; --- * --- * ---
; roll dice N times!
.reroll:
call r14;
cmp al,$64;
jge .error;
; ^load string repr from table
xor rdi,rdi;
xor rsi,rsi;
lea rax,[NUMTAB+rax*4];
mov di,word [rax];
mov si,word [rax+2];
add rdi,NUMTAB_SRC;
call FOUT.write;
; manage iter
dec r15b;
test r15b,r15b;
jnz .reroll;
jmp .get_next;
; --- * --- * ---
; cleanup and give
.skip:
call FOUT.flush;
leave;
mov rax,60;
syscall;
; --- * --- * ---
; d'oh!
.error:
; ^write repr to stdout
mov rdi,1;
mov rsi,errme;
mov rdx,errme.len;
mov rax,1;
syscall;
; exit
mov rdi,1;
mov rax,60;
syscall;
; --- * --- * ---
; writes to static mem
FOUT.write:
; point to buffer+offset
xor rax,rax;
mov ax,word [FOUT.ptr];
add rax,FOUT.buff;
; read str -> write at ptr
mov rdx,qword [rdi];
mov qword [rax],rdx;
; update ptr and give
add word [FOUT.ptr],si;
ret;
; --- * --- * ---
; ^outputs buffer to stdout
FOUT.flush:
; point to buffer
xor rdx,rdx;
lea rsi,[FOUT.buff];
mov dx,word [FOUT.ptr];
; flush and give
mov rdi,$01;
mov rax,$01;
syscall;
ret;
; --- * --- * ---
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment