Skip to content
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

Rework third chapter #41

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
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
687 changes: 526 additions & 161 deletions content/asm_3.md

Large diffs are not rendered by default.

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.
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).
294 changes: 144 additions & 150 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 `sys_write` system call
SYS_WRITE equ 1
;; Number of `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 argument", 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 number to string to print the result on the screen.
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
;; Set the value of the rax register to 0. It will store the result.
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:
mov rcx, 10
__repeat:
;; Compare the first element in the given string with the NUL terminator (end of 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 do not 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 string and print it on the screen.
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`, resulting quotient will be stored in `rax`,
;; and the remainder will be stored in `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 yet, 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 symbols within the string 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
Loading