lang-bootstrap/04/guessing_game

241 lines
3.2 KiB
Text
Raw Normal View History

global exit_code
exit_code = main()
exit(exit_code)
function main
local secret_number
local guess
global 32 input_line
local p_line
p_line = &input_line
secret_number = getrand(100)
2022-01-07 11:07:06 -05:00
puts(.str_intro)
:guess_loop
2022-01-07 11:07:06 -05:00
puts(.str_guess)
syscall(0, 0, p_line, 30)
guess = stoi(p_line)
if guess < secret_number goto too_low
if guess > secret_number goto too_high
2022-01-07 11:07:06 -05:00
puts(.str_got_it)
return 0
:too_low
2022-01-07 11:07:06 -05:00
puts(.str_too_low)
goto guess_loop
:too_high
2022-01-07 11:07:06 -05:00
puts(.str_too_high)
goto guess_loop
:str_intro
string I'm thinking of a number.
byte 10
byte 0
:str_guess
string Guess what it is:
byte 32
byte 0
:str_got_it
string You got it!
byte 10
byte 0
:str_too_low
string Too low!
byte 10
byte 0
:str_too_high
string Too high!
byte 10
byte 0
; get a "random" number from 0 to x using the system clock
function getrand
argument x
global 16 getrand_time
local ptime
local n
ptime = &getrand_time
2022-01-07 11:07:06 -05:00
syscall(228, 0, ptime) ; clock_gettime(CLOCK_REALTIME, ptime)
ptime += 8 ; nanoseconds at offset 8 in struct timespec
n = *4ptime
n %= x
return n
; returns a pointer to a null-terminated string containing the number given
function itos
global 32 itos_string
argument x
local c
local p
p = &itos_string
p += 30
:itos_loop
c = x % 10
c += '0
*1p = c
x /= 10
if x == 0 goto itos_loop_end
p -= 1
goto itos_loop
:itos_loop_end
return p
; returns the number at the start of the given string
function stoi
argument s
local p
local n
local c
n = 0
p = s
:stoi_loop
c = *1p
if c < '0 goto stoi_loop_end
if c > '9 goto stoi_loop_end
n *= 10
n += c - '0
p += 1
goto stoi_loop
:stoi_loop_end
return n
function strlen
argument s
local c
local p
p = s
:strlen_loop
c = *1p
if c == 0 goto strlen_loop_end
p += 1
goto strlen_loop
:strlen_loop_end
return p - s
function fputs
argument fd
argument s
local length
length = strlen(s)
syscall(1, fd, s, length)
return
2022-01-07 11:07:06 -05:00
function puts
argument s
fputs(1, s)
return
function fputn
argument fd
argument n
local s
s = itos(n)
fputs(fd, s)
return
function exit
argument status_code
syscall(0x3c, status_code)
function syscall
; I've done some testing, and this should be okay even if
; rbp-56 goes beyond the end of the stack.
; mov rax, [rbp-16]
byte 0x48
byte 0x8b
byte 0x85
byte 0xf0
byte 0xff
byte 0xff
byte 0xff
; mov rdi, rax
byte 0x48
byte 0x89
byte 0xc7
; mov rax, [rbp-24]
byte 0x48
byte 0x8b
byte 0x85
byte 0xe8
byte 0xff
byte 0xff
byte 0xff
; mov rsi, rax
byte 0x48
byte 0x89
byte 0xc6
; mov rax, [rbp-32]
byte 0x48
byte 0x8b
byte 0x85
byte 0xe0
byte 0xff
byte 0xff
byte 0xff
; mov rdx, rax
byte 0x48
byte 0x89
byte 0xc2
; mov rax, [rbp-40]
byte 0x48
byte 0x8b
byte 0x85
byte 0xd8
byte 0xff
byte 0xff
byte 0xff
; mov r10, rax
byte 0x49
byte 0x89
byte 0xc2
; mov rax, [rbp-48]
byte 0x48
byte 0x8b
byte 0x85
byte 0xd0
byte 0xff
byte 0xff
byte 0xff
; mov r8, rax
byte 0x49
byte 0x89
byte 0xc0
; mov rax, [rbp-56]
byte 0x48
byte 0x8b
byte 0x85
byte 0xc8
byte 0xff
byte 0xff
byte 0xff
; mov r9, rax
byte 0x49
byte 0x89
byte 0xc1
; mov rax, [rbp-8]
byte 0x48
byte 0x8b
byte 0x85
byte 0xf8
byte 0xff
byte 0xff
byte 0xff
; syscall
byte 0x0f
byte 0x05
return