Skip to content

Rework third chapter #41

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 24 commits into from
Apr 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,4 @@ dkms.conf
# Our binaries
hello/hello
sum/sum
stack/stack
1 change: 1 addition & 0 deletions CONTRIBUTORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ Special thanks to all the people who helped to develop this project:
- [knoxknox](https://github.com/knoxknox)
- [tirkarthi](https://github.com/tirkarthi)
- [maldron0309](https://github.com/maldron0309)
- [Yimura](https://github.com/Yimura)
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Here are links to each post:

* [Part 1. Introduction](https://github.com/0xAX/asm/blob/master/content/asm_1.md)
* [Part 2. The `x86_64` concepts](https://github.com/0xAX/asm/blob/master/content/asm_2.md)
* [Say hello to x86_64 Assembly part 3](https://github.com/0xAX/asm/blob/master/content/asm_3.md)
* [Part 3. Journey through the stack](https://github.com/0xAX/asm/blob/master/content/asm_3.md)
* [Say hello to x86_64 Assembly part 4](https://github.com/0xAX/asm/blob/master/content/asm_4.md)
* [Say hello to x86_64 Assembly part 5](https://github.com/0xAX/asm/blob/master/content/asm_5.md)
* [Say hello to x86_64 Assembly part 6](https://github.com/0xAX/asm/blob/master/content/asm_6.md)
Expand Down
706 changes: 545 additions & 161 deletions content/asm_3.md

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions content/assets/asm-3-args-on-stack.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions content/assets/asm-3-stack-of__double-1.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions content/assets/asm-3-stack-of__double-2.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 3 additions & 1 deletion lychee.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ glob_ignore_case = false

# Exclude URLs from checking (supports regex).
exclude = [
"https://www.gnu.org/software/emacs"
"https://www.gnu.org/software/emacs",
"https://makeapullrequest.com",
"https://x.com/0xAX"
]

# Exclude these filesystem paths from getting checked.
Expand Down
2 changes: 1 addition & 1 deletion stack/Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
all:
nasm -f elf64 -o stack.o stack.asm
ld -o stack stack.o
ld -o stack stack.o

clean:
rm stack stack.o
11 changes: 7 additions & 4 deletions stack/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
This is simple application which gets two command line arguments, sums it and prints result.
# Stack

Build it with: `make`
This is a simple application that takes two command line arguments, sums them, and prints the result.

More details at - [Say hello to x64 Assembly [part 3]](https://github.com/0xAX/asm/blob/master/content/asm_3.md)
To build the program, run:

[@0xAX](https://x.com/0xAX)
```bash
make
```

For more details, read [Part 3. Journey through the stack](https://github.com/0xAX/asm/blob/master/content/asm_3.md).
296 changes: 145 additions & 151 deletions stack/stack.asm
Original file line number Diff line number Diff line change
@@ -1,168 +1,162 @@
;; Definition of the .data section
section .data
SYS_WRITE equ 1
STD_IN equ 1
SYS_EXIT equ 60
EXIT_CODE equ 0

NEW_LINE db 0xa
WRONG_ARGC db "Must be two command line argument", 0xa

;; Number of the `sys_write` system call
SYS_WRITE equ 1
;; Number of the `sys_exit` system call
SYS_EXIT equ 60
;; Number of the standard output file descriptor
STD_OUT equ 1
;; Exit code from the program. The 0 status code is a success.
EXIT_CODE equ 0
;; ASCII code of the new line symbol ('\n')
NEW_LINE db 0xa
;; Error message that is printed in a case of not enough command-line arguments
WRONG_ARGC_MSG db "Error: expected two command-line arguments", 0xa
;; Length of the WRONG_ARGC_MSG message
WRONG_ARGC_MSG_LEN equ 42

;; Definition of the .text section
section .text
;; Reference to the entry point of our program
global _start

;; Entry point
_start:
;; rcx - argc
pop rcx

;;
;; Check argc
;;
cmp rcx, 3
jne argcError

;;
;; start to sum arguments
;;

;; skip argv[0] - program name
add rsp, 8

;; get argv[1]
pop rsi
;; convert argv[1] str to int
call str_to_int
;; put first num to r10
mov r10, rax
;; get argv[2]
pop rsi
;; convert argv[2] str to int
call str_to_int
;; put second num to r11
mov r11, rax
;; sum it
add r10, r11

;;
;; Convert to string
;;
mov rax, r10
;; number counter
xor r12, r12
;; convert to string
jmp int_to_str

;;
;; Print argc error
;;
;; Fetch the number of arguments from the stack and store it in the rcx register.
pop rcx
;; Check the number of the given command-line arguments.
cmp rcx, 3
;; If not enough, jump to the error subroutine.
jne argcError

;; Skip the first command-line argument which is usually the program name.
add rsp, 8

;; Fetch the first command-line argument from the stack and store it in the rsi register.
pop rsi
;; Convert the first command-line argument to an integer number.
call str_to_int
;; Store the result in the r10 register.
mov r10, rax

;; Fetch the second command-line argument from the stack and store it in the rsi register.
pop rsi
;; Convert the second command-line argument to an integer number.
call str_to_int
;; Store the result in the r11 register.
mov r11, rax

;; Calculate the sum of the arguments. The result will be stored in the r10 register.
add r10, r11

;; Move the sum value to the rax register.
mov rax, r10
;; Initialize counter by resetting it to 0. It will store the length of the result string.
xor rcx, rcx
;; Convert the sum from a number to a string to print the result to the standard output.
jmp int_to_str

;; Print the error message if not enough command-line arguments.
argcError:
;; sys_write syscall
mov rax, 1
;; file descritor, standard output
mov rdi, 1
;; message address
mov rsi, WRONG_ARGC
;; length of message
mov rdx, 34
;; call write syscall
;; Specify the system call number (1 is `sys_write`).
mov rax, SYS_WRITE
;; Set the first argument of `sys_write` to 1 (`stdout`).
mov rdi, STD_OUT
;; Set the second argument of `sys_write` to the reference of the `WRONG_ARGC_MSG` variable.
mov rsi, WRONG_ARGC_MSG
;; Set the third argument to the length of the `WRONG_ARGC_MSG` variable's value.
mov rdx, WRONG_ARGC_MSG_LEN
;; Call the `sys_write` system call.
syscall
;; exit from program
jmp exit
;; Go to the exit of the program.
jmp exit


;;
;; Convert int to string
;;
int_to_str:
;; reminder from division
mov rdx, 0
;; base
mov rbx, 10
;; rax = rax / 10
div rbx
;; add \0
add rdx, 48
;; push reminder to stack
push rdx
;; go next
inc r12
;; check factor with 0
cmp rax, 0x0
;; loop again
jne int_to_str
;; print result
jmp print

;;
;; Convert string to int
;;
;; Convert the command-line argument to the integer number.
str_to_int:
;; accumulator
xor rax, rax
;; base for multiplication
mov rcx, 10
next:
;; check that it is end of string
cmp [rsi], byte 0
;; return int
je return_str
;; mov current char to bl
mov bl, [rsi]
;; get number
sub bl, 48
;; rax = rax * 10
mul rcx
;; ax = ax + digit
add rax, rbx
;; get next number
inc rsi
;; again
jmp next

return_str:
;; Set the value of the rax register to 0. It will store the result.
xor rax, rax
;; Base for multiplication
mov rcx, 10
__repeat:
;; Compare the first element in the given string with the NUL terminator (end of the string).
cmp [rsi], byte 0
;; If we reached the end of the string, return from the procedure. The result is stored in the rax register.
je __return
;; Move the current character from the command-line argument to the bl register.
mov bl, [rsi]
;; Subtract the value 48 from the ASCII code of the current character.
;; This will give us the numeric value of the character.
sub bl, 48
;; Multiple our result number by 10 to get the place for the next digit.
mul rcx
;; Add the next digit to our result number.
add rax, rbx
;; Move to the next character in the command-line argument string.
inc rsi
;; Repeat until we reach the end of the string.
jmp __repeat
__return:
;; Return from the str_to_int procedure.
ret


;;
;; Print number
;;
print:
;;;; calculate number length
mov rax, 1
mul r12
mov r12, 8
mul r12
mov rdx, rax
;;;;

;;;; print sum
mov rax, SYS_WRITE
mov rdi, STD_IN
mov rsi, rsp
;; call sys_write
;; Convert the sum to a string and print it to the standard output.
int_to_str:
;; High part of the dividend. The low part is in the rax register.
mov rdx, 0
;; Set the divisor to 10.
mov rbx, 10
;; Divide the sum stored in `rax. The resulting quotient will be stored in `rax`,
;; and the remainder will be stored in the `rdx` register.
div rbx
;; Add 48 to the remainder to get a string ASCII representation of the number value.
add rdx, 48
;; Store the remainder on the stack.
push rdx
;; Increase the counter.
inc rcx
;; Compare the rest of the sum with zero.
cmp rax, 0x0
;; If it is not zero, continue to convert it to string.
jne int_to_str
;; Otherwise, print the result.
jmp printResult

;; Print the result to the standard output.
printResult:
;; Put the number of string characters to the rax register.
mov rax, rcx
;; Put the value 8 to the rcx register.
mov rcx, 8
;; Calculate the number of bytes in the given string by multiplying rax by 8.
;; The result will be stored in the rax register.
mul rcx

;; Set the third argument to the length of the result string to print.
mov rdx, rax
;; Specify the system call number (1 is `sys_write`).
mov rax, SYS_WRITE
;; Set the first argument of `sys_write` to 1 (`stdout`).
mov rdi, STD_OUT
;; Set the second argument of `sys_write` to the reference of the result string to print.
mov rsi, rsp
;; Call the `sys_write` system call.
syscall
;;

;; newline
jmp printNewline

;;
;; Print number
;;
printNewline:
mov rax, SYS_WRITE
mov rdi, STD_IN
mov rsi, NEW_LINE
mov rdx, 1
;; Specify the system call number (1 is `sys_write`).
mov rax, SYS_WRITE
;; Set the first argument of `sys_write` to 1 (`stdout`).
mov rdi, STD_OUT
;; Set the second argument of `sys_write` to the reference of the `NWE_LINE` variable.
mov rsi, NEW_LINE
;; Set the third argument to the length of the `NEW_LINE` variable's value (1 byte).
mov rdx, 1
;; Call the `sys_write` system call.
syscall
jmp exit

;;
;; Exit from program
;;
exit:
;; syscall number
mov rax, SYS_EXIT
;; exit code
mov rdi, EXIT_CODE
;; call sys_exit
;; Specify the number of the system call (60 is `sys_exit`).
mov rax, SYS_EXIT
;; Set the first argument of `sys_exit` to 0. The 0 status code is a success.
mov rdi, EXIT_CODE
;; Call the `sys_exit` system call.
syscall