diff options
Diffstat (limited to '04/guessing_game')
-rw-r--r-- | 04/guessing_game | 242 |
1 files changed, 242 insertions, 0 deletions
diff --git a/04/guessing_game b/04/guessing_game new file mode 100644 index 0000000..449ded8 --- /dev/null +++ b/04/guessing_game @@ -0,0 +1,242 @@ +global 0x1000 exit_code +global y +y = 4 +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) + puts(.str_intro) + + :guess_loop + 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 + puts(.str_got_it) + return 0 + :too_low + puts(.str_too_low) + goto guess_loop + :too_high + 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 + 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 + +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 |