add itoa and build "system"

This commit is contained in:
nora 2022-01-02 13:41:04 +01:00
parent 73c1ca8415
commit 19427394db
3 changed files with 153 additions and 0 deletions

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
target
.idea
*.iml

30
build.sh Normal file
View file

@ -0,0 +1,30 @@
build () {
FILE="$1"
PROGRAM_NAME=$(basename "$FILE" ".asm")
if [ ! -f "$FILE" ]; then
echo "$PROGRAM_NAME not found"
return
fi
echo "Building $PROGRAM_NAME"
nasm -g -F dwarf -f elf64 "$FILE" -o "./target/$PROGRAM_NAME.o" && ld.lld "./target/$PROGRAM_NAME.o" -o "./target/$PROGRAM_NAME"
}
if [ "$1" = "--clean" ]; then
rm -r target
exit
fi
if [ ! -d ./target ]; then
mkdir ./target
fi
if [ "$#" -eq 0 ]; then
for FILE in ./src/*.asm ; do
build "$FILE"
done
else
build "src/$1.asm"
fi

120
src/itoa.asm Normal file
View file

@ -0,0 +1,120 @@
global _start
NUMBER EQU 0
section .data
buffer: times 8 db 0
section .text
_start:
mov rax, NUMBER
mov rbx, buffer
call itoa
cmp rax, 0
jnz error
write_buffer:
mov rax, 1 ; write
mov rdi, 1 ; stdout
mov rsi, buffer
mov rdx, rbx ; the length
syscall
graceful_exit:
xor rdi, rdi
jmp exit
error:
mov rdi, 1
exit:
mov rax, 60
syscall
; itoa - converts an unsigned integer into its ascii representation
; inputs:
; rax - the number
; rbx - the pointer to the buffer
; outputs:
; rax - 0: success, 1: error
; rbx - the length
MAX_SIZE EQU 100000
START_DIVISOR EQU MAX_SIZE / 10
ASCII_NUM EQU 48
itoa:
; r12: whether we are in the leading zeroes (bool)
; r11: buffer start
; r10: number
; r9: divisor
; r8: current buffer pointer
mov r12, 1
mov r10, rax
cmp r10, MAX_SIZE
jge number_too_big
mov r9, START_DIVISOR
mov r11, rbx
mov r8, rbx
cmp rax, 0
jz write_zero_return
div_loop:
; first division for getting the mod of the number
xor rdx, rdx
mov rax, r10
mov rcx, r9
div rcx
; if rax is non-zero or we are not in the leading zeroes, write into the buffer
cmp rax, 0
jne write_ascii_into_buffer
cmp r12, 0
jz write_ascii_into_buffer
; else, skip the write
jmp take_remainder_of_number
write_ascii_into_buffer:
; write the ascii number into the buffer
add rax, ASCII_NUM
mov byte [r8], al
inc r8
xor r12, r12 ; we are past the leading zeroes, set it to false
take_remainder_of_number:
; if the divisor is one, we are done here
cmp r9, 1
je return_success
; now take the remainder of the number for the next loop
xor rdx, rdx
mov rax, r10
mov rcx, r9
div rcx
mov r10, rdx ; nom = num % div
; divide the divisor by ten
xor rdx, rdx
mov rax, r9
mov rcx, 10
div rcx
mov r9, rax
jmp div_loop
write_zero_return:
mov byte [r8], '0'
inc r8
return_success:
; calculate the length into r8
sub r8, r11
mov rax, 0 ; return the success code 0
mov rbx, r8 ; return the length
ret
number_too_big:
mov rax, 1 ; return error code 1
mov rbx, 0 ; we've written nothing
ret