Skip to content

Instantly share code, notes, and snippets.

@TabulateJarl8
Created December 20, 2023 07:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TabulateJarl8/70ffe4cca20fcea5ab589292eb01ca3e to your computer and use it in GitHub Desktop.
Save TabulateJarl8/70ffe4cca20fcea5ab589292eb01ca3e to your computer and use it in GitHub Desktop.
I printed an integer in assembly
section .data
str_buffer db 0
section .text
global _start
calculate_ten_power:
; calculate the power of 10 that corresponds to an integer
; for example, 100 for 543, 1000 for 8956, and 10000 for 15236
; returns the integer in rcx
; rsp is the return address, add 8 to get the argument
mov rcx, [rsp+8] ; rcx should be the integer to find the power of 10 for
mov rax, 1 ; we need to calculate the power of 10 that corresponds to rcx
; for example 100 for 543 and 1000 for 8753
mov rbx, 10
calculate_ten:
mul rbx
cmp rax, rcx
jg finish_power_ten ; if number is greater than target, divide by 10 and ret
jmp calculate_ten
finish_power_ten:
; divide ax by 10 to finish the calculation
xor rdx, rdx
div rbx
; now rax contains the power of 10
mov rcx, rax
ret
print_digit:
push rcx
mov rcx, [rsp+16]
add rcx, '0' ; convert digit to ASCII
mov byte [str_buffer], cl ; assign lower 8 bits of rcx to buffer
mov rsi, str_buffer ; buffer pointer
mov rax, 1 ; write
mov rdi, 1 ; stdout
mov rdx, 1 ; len
syscall ; call kernel
pop rcx ; restore rcx
ret
print_integer:
mov rax, [rsp+8] ; use a reg as an intermediary because i cant directly push from the stack
push rax ; rsp+8 should be the number to print. push it for the next function to consume
call calculate_ten_power ; power of 10 is now in rcx
pop rax ; mov the argument (number to print) that was pushed into rax
iter_number:
; num_to_print: rax
; base_10_place: rcx
; formula for accessing number: (num_to_print // base_10_place) % 10
; base_10_place is the power of 10 that corresponds to the place of number to print
; using 123 for example, 100 will get the 1, 10 will get the 2, and 1 will get the 3
; first, make sure we have a copy of rax
push rax
; 10 for use in modulo
mov rbx, 10
; next, floor divide rax by rcx
xor rdx, rdx
div rcx
; result is stored in rax, mod 10
; clear out rdx because thats where remainder is stored
xor rdx, rdx
div rbx
; rdx now contains our digit to print
push rdx
call print_digit
pop rax ; we can ignore this, its the rdx that never got popped from print_digit
; check if rcx is equal to 1. if so, we just did the last digit
mov rax, 1
cmp rax, rcx
je exit_print_integer
; divide out power of 10 by 10 to get the next digit
xor rdx, rdx
mov rbx, 10
mov rax, rcx
div rbx
mov rcx, rax
; restore our original number to print
pop rax
; loop to iter_number until rcx is 1 (we've done the last digit)
jmp iter_number
exit_print_integer:
pop rax ; pop off our original number so that we return to the correct address
ret
_start:
mov rax, 578
push rax
call print_integer
; exit
mov rax, 60
mov rdi, 0
syscall ; call kernel
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment