Printing Integers in x86_64 Assembly
I finally got the assembly for printing numbers working. It was somewhat tricky as each individual digit needs to be extracted, converted to ASCII, and then printed. Here's how it works:
- Suppose we want to print the number 123.
We need to divide that number by 10 and put the remainder in the stack. We do this until our result equals 0:
123 / 10 = 12 with a remainder or 3 12 / 10 = 1 with a remainder of 2 1 / 10 = 0 with a remainder of 1
- We need to add 48 to the digit because 48 is the ASCII value for 0. So we're offsetting the ASCII character for 0 by the value of the digit.
- Now we can iterate through each value and print it.
Here's the final code with some comments to help make whats happening clearer:
section .text global _start _start: ;; Move the number we want to print into rax mov rax, 123 call _printInt ;; Exit mov rax, 60 mov rdi, 0 syscall _printInt: ;; r8 will keep a count of how many bytes to print mov r8, 0 call _pushDigitsOnStack ret _pushDigitsOnStack: ;; Divide rax by 10 and add 48. ;; This extracts the digit and converts it to ascii. ;; 48 is the ascii value for 0. xor rdx, rdx mov rbx, 10 div rbx add dl, 48 ;; Allocate 1 byte on the stack for the digit ;; and place it in the stack. ;; Then increment the count sub rsp, 1 mov byte [rsp], dl inc r8 ;; If rax is equal to 0 then we're done cmp rax, 0 jne _pushDigitsOnStack _printDigitsOnStack: ;; Add the newline character to the stack ;; and increment the number of bytes we need to print ;; to take into account this newline character mov byte [rsp+r8], 10 inc r8 ;; Print all the bytes in the stack mov rax, 1 mov rdi, 1 mov rsi, rsp mov rdx, r8 syscall ;; Move the stack pointer back to the location ;; of the return instruction dec r8 add rsp, r8 ret