diff options
| author | Carlos Maiolino <[email protected]> | 2025-07-10 22:55:07 +0200 |
|---|---|---|
| committer | Carlos Maiolino <[email protected]> | 2025-07-10 22:56:55 +0200 |
| commit | d98f46ce647846b0aa30b2e16a30fd4e152a1bf5 (patch) | |
| tree | 267474fcc77cf20b428f6f4c7f768ca09f4cfe0e /PGU/CHAP10 | |
| parent | 869e68986aa8f69af6e7842260a68d1e5c6f796f (diff) | |
Add new code
Signed-off-by: Carlos Maiolino <[email protected]>
Diffstat (limited to 'PGU/CHAP10')
| -rw-r--r-- | PGU/CHAP10/convprog.s | 35 | ||||
| -rw-r--r-- | PGU/CHAP10/count-chars.s | 47 | ||||
| -rw-r--r-- | PGU/CHAP10/int2str.s | 86 | ||||
| -rw-r--r-- | PGU/CHAP10/linux.s | 16 | ||||
| -rw-r--r-- | PGU/CHAP10/write-newline.s | 29 |
5 files changed, 213 insertions, 0 deletions
diff --git a/PGU/CHAP10/convprog.s b/PGU/CHAP10/convprog.s new file mode 100644 index 0000000..49ac6fb --- /dev/null +++ b/PGU/CHAP10/convprog.s @@ -0,0 +1,35 @@ +.include "linux.s" + +.section .data + +tmp_buffer: + .ascii "\0\0\0\0\0\0\0\0\0\0\0" + +.section .text + +.globl _start + +_start: + movq %rsp, %rbp + + pushq $tmp_buffer + pushq $824 + call integer2string + addq $16, %rsp + + pushq $tmp_buffer + call count_chars + addq $8, %rsp + + movq %rax, %rdx + movq $STDOUT, %rdi + movq $tmp_buffer, %rsi + movq $SYS_WRITE, %rax + syscall + + pushq $STDOUT + call write_newline + + movq $SYS_EXIT, %rax + movq $0, %rdi + syscall diff --git a/PGU/CHAP10/count-chars.s b/PGU/CHAP10/count-chars.s new file mode 100644 index 0000000..7e12791 --- /dev/null +++ b/PGU/CHAP10/count-chars.s @@ -0,0 +1,47 @@ +# Count the characters in a string (until a null byte is reached) +# It's supposed to behave similarly with strlen() +# +# Returns the count in %rax +# +# - %rcx: Char count +# - %rdx: current Char address +# - %al: current char +# + +.type count_chars, @function +.globl count_chars + +# We receive the string addr in the stack. +# Remember %rsp + 8 contains the return value +.equ ST_STRING_ADDRESS, 16 + +count_chars: + pushq %rbp + movq %rsp, %rbp + + #initialize counter + movq $0, %rcx + + # Start address of string: + movq ST_STRING_ADDRESS(%rbp), %rdx + +count_loop_begin: + + # Grab char + movb (%rdx), %al + + cmpb $0, %al + je count_loop_end + + # We are not done yet... + incq %rcx + incq %rdx + jmp count_loop_begin + +count_loop_end: + + movq %rcx, %rax + + movq %rbp, %rsp + popq %rbp + ret diff --git a/PGU/CHAP10/int2str.s b/PGU/CHAP10/int2str.s new file mode 100644 index 0000000..6ea5178 --- /dev/null +++ b/PGU/CHAP10/int2str.s @@ -0,0 +1,86 @@ +# integer2string +# +# Convert an int number to a decima string for display +# +# Receives a buffer large enough to hold the largest possible numberr +# and an integer to convert +# +# %rcx hold the count of characters processed +# %rax holds the current value +# %rdi hold the base (10) + +.equ ST_VALUE, 16 +.equ ST_BUFFER, 24 + +.globl integer2string +.type integer2string, @function + +integer2string: + + # Default function setup + pushq %rbp + movq %rsp, %rbp + + movq $0, %rcx # Init char count + movq ST_VALUE(%rbp), %rax # Retrieve value from stack + + # The divisor must be in a register or memory location + movq $10, %rdi + + conversion_loop: + # Division is actually performed on the combined + # %rdx:%rax register, so first, clear out %rdx + movq $0, %rdx + + # Divide %rdx:%rax (which are implied) by 10 + # Store the quotient in %rax and the remainder in + # %rdx (both which are implied) + divq %rdi + + # Quotient is in the right place. %rdx has the remainder + # which now needs to be converted into a number. So, %rdx has a + # number that is 0 through 9. We'll use it as an 'index' on the + # ASCII table starting from char '0'. + addq $'0', %rdx # Get our number's index from ASCII + # table, starting from '0'. + + # Push this value into the stack. When we are done, we can just + # pop them off one-by-one, and they will be in the right order. + # NOTE: We are pushing the whole register, but we only need the + # byte in %dl (The last byte of the %rdx register) for the + # character. + pushq %rdx + + incq %rcx # Increment digit count + + cmpq $0, %rax # Have we reached the end of the calculation? + je end_conversion_loop + + # %rax has its new value + jmp conversion_loop + + end_conversion_loop: + # The string is now on the stack, if we pop it off a char at a + # time, we can copy it into the buffer and we are done. + + movq ST_BUFFER(%rbp), %rdx # Move buffer address to %rdx + + copy_reversing_loop: + popq %rax + movb %al, (%rdx) + decq %rcx # Once we reach 0 we are finished + incq %rdx # Point to the next byte + + cmpq $0, %rcx # Check if we are finished + je end_copy_reversing_loop + + jmp copy_reversing_loop + + end_copy_reversing_loop: + movb $0, (%rdx) + + movq %rbp, %rsp + popq %rbp + ret + +# end of integer2string diff --git a/PGU/CHAP10/linux.s b/PGU/CHAP10/linux.s new file mode 100644 index 0000000..9ab8243 --- /dev/null +++ b/PGU/CHAP10/linux.s @@ -0,0 +1,16 @@ +# Syscall numbers (x86_64) + +.equ SYS_EXIT, 60 +.equ SYS_READ, 0 +.equ SYS_WRITE, 1 +.equ SYS_OPEN, 2 +.equ SYS_CLOSE, 3 +.equ SYS_BRK, 12 + +# Default File Descriptors +.equ STDIN, 0 +.equ STDOUT, 1 +.equ STDERR, 2 + +# Common Status Codes +.equ END_OF_FILE, 0 diff --git a/PGU/CHAP10/write-newline.s b/PGU/CHAP10/write-newline.s new file mode 100644 index 0000000..e916379 --- /dev/null +++ b/PGU/CHAP10/write-newline.s @@ -0,0 +1,29 @@ +# Just write a newline (\n) to STDOUT + +.include "linux.s" +.type write_newline, @function +.globl write_newline + +.section .data + +newline: + .ascii "\n" + +.section .text + .equ ST_FILEDES, 16 + +write_newline: + pushq %rbp + movq %rsp, %rbp + + movq $SYS_WRITE, %rax + movq ST_FILEDES(%rbp), %rdi + movq $newline, %rsi + movq $1, %rdx + syscall + + movq %rbp, %rsp + popq %rbp + ret + + |
