3.3 2c Run-Time System
(require cpsc411/2c-run-time) | package: cpsc411-lib |
This library provides the run-time system for supporting the CPSC 411 languages that can only produce two’s complement integers.
procedure
(wrap-x64-run-time v) → string?
v : string?
This run-time system prints a two’s complement integer to the standard output port, as an ASCII string.
Implementation detail: currently, does nothing, as wrap-x64-boilerplate actually installs the run-time system, so this function cannot be used on its own; wrap-x64-boilerplate must be called immediately after.
Currently only supports Linux and macOS.
> (wrap-x64-run-time "mov rax, 5") "mov rax, 5"
procedure
(wrap-x64-boilerplate e) → string?
e : string?
Implementation detail: currently, installs the run-time system as well.
Currently only supports Linux and macOS.
> (require racket/pretty) > (pretty-display (wrap-x64-boilerplate "mov rax, 5"))
global start
section .text
start:
mov rbp, rsp
mov r15, done
mov rax, 5
; The result should be a number in RAX
jmp done
; Convert RAX to a string, left in buffer msg
; The result should be a number in RAX
; build the string backwards, then reverse
done:
number_to_string:
mov rdi, 0 ; index into msg, starting at beginning
mov r12, 10 ; divide by 10; idiv requires register arg
mov rsi, msg
mov r15, 0 ; clear r15 to store negative flag
cmp rax, 0 ; if negative
js neg
loop:
mov rdx, 0 ; extend rax to rdx
idiv r12 ; signed divide RDX:RAX by r12, with result
; stored in RAX ← Quotient, RDX ← Remainder.
add rdx, 48 ; convert digit to ASCII char
mov BYTE [rsi + rdi], dl ; mov char into msg
inc rdi
cmp rax, 0
jne loop
cmp r15, 0 ; if number if negative, add - as final character
jl add_minus
; rdi contains the length of the msg
; msg is in rsi
reverse_msg:
mov rdx, rdi ; preserve the length for printing
dec rdi ; length -> final index
mov r9, 0 ; first character
rev_loop:
cmp rdi, r9
jle print_msg
; Until rdi <= r9, swap [rsi + rdi] and [rsi + r9]
; Save last character into register, move first character
mov r8b, BYTE [rsi + rdi]
mov r10b, BYTE [rsi + r9]
mov BYTE [rsi + rdi], r10b
mov BYTE [rsi + r9], r8b
inc r9
dec rdi
jmp rev_loop
print_msg:
mov rax, 1
mov rdi, 1 ; And I want it to write to stdout
; The message pointer is in rsi
; length in rdx
syscall
mov rax, 60 ; I'm about to call the OS sys_exit function
mov rdi, 0 ; The exit code is 0
syscall
neg:
mov r15, -1
imul rax, -1
jmp loop
add_minus:
mov BYTE [rsi + rdi], 45
inc rdi
jmp reverse_msg
section .bss
section .data
dummy: db 0 ; Mac isn't happy with an empty .data
len: equ 19
msg: times len db '0'