summaryrefslogtreecommitdiff
path: root/PGU/CHAP10
diff options
context:
space:
mode:
authorCarlos Maiolino <[email protected]>2025-07-10 22:55:07 +0200
committerCarlos Maiolino <[email protected]>2025-07-10 22:56:55 +0200
commitd98f46ce647846b0aa30b2e16a30fd4e152a1bf5 (patch)
tree267474fcc77cf20b428f6f4c7f768ca09f4cfe0e /PGU/CHAP10
parent869e68986aa8f69af6e7842260a68d1e5c6f796f (diff)
Add new code
Signed-off-by: Carlos Maiolino <[email protected]>
Diffstat (limited to 'PGU/CHAP10')
-rw-r--r--PGU/CHAP10/convprog.s35
-rw-r--r--PGU/CHAP10/count-chars.s47
-rw-r--r--PGU/CHAP10/int2str.s86
-rw-r--r--PGU/CHAP10/linux.s16
-rw-r--r--PGU/CHAP10/write-newline.s29
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
+
+