Commit c8ac898
Changed files (6)
assignments/3/Makefile
@@ -16,3 +16,8 @@ manual: max_min.s
as --64 -o max_min.o max_min.s
ld -o max_min.exe max_min.o
./max_min.exe
+
+manual_ai: max_min.asm
+ as --64 -o max_min.o max_min.asm
+ ld -o max_min.exe max_min.o
+ ./max_min.exe
assignments/3/max_min.asm
@@ -0,0 +1,158 @@
+.section .data
+largest_msg: .asciz "Max: "
+smallest_msg: .asciz "The smallest number is: "
+newline: .asciz "\n"
+temp_input: .space 32 # Buffer for input string
+largest: .quad 0
+smallest: .quad 0
+initialized: .byte 0 # Flag to check if smallest/largest are initialized
+
+.section .text
+.globl _start
+
+_start:
+ # Initialize the largest and smallest values
+ movq $0, largest
+ movq $0, smallest
+ movb $0, initialized # Mark as uninitialized
+
+read_input:
+ # Read a line of input from stdin
+ movq $0, %rax # syscall: read
+ movq $0, %rdi # file descriptor: stdin
+ lea temp_input(%rip), %rsi # buffer to store input
+ movq $32, %rdx # size of input buffer
+ syscall
+
+ # Check if input is empty (EOF)
+ cmpq $0, %rax
+ je print_results
+
+ # Null-terminate the input string
+ lea temp_input(%rip), %rdi # Load base address of temp_input
+ addq %rax, %rdi # Add offset to the base address
+ movb $0, (%rdi) # Null-terminate the string
+
+ # Convert the input string to an integer
+ lea temp_input(%rip), %rsi
+ call string_to_int
+ movq %rax, %rdi # Store integer in %rdi
+
+ # Check for termination (sentinel value -1)
+ cmpq $-1, %rdi
+ je print_results
+
+ # Check if largest/smallest are initialized
+ cmpb $0, initialized(%rip)
+ jne compare_values
+
+ # Initialize largest and smallest with the first input value
+ movq %rdi, largest(%rip)
+ movq %rdi, smallest(%rip)
+ movb $1, initialized(%rip) # Mark as initialized
+ jmp read_input
+
+compare_values:
+ # Update the largest value
+ movq largest(%rip), %rax
+ cmpq %rdi, %rax
+ jge check_smallest
+ movq %rdi, largest(%rip)
+
+check_smallest:
+ # Update the smallest value
+ movq smallest(%rip), %rax
+ cmpq %rdi, %rax
+ jle read_input
+ movq %rdi, smallest(%rip)
+ jmp read_input
+
+print_results:
+ # Print the largest value
+ movq $1, %rax # syscall: write
+ movq $1, %rdi # file descriptor: stdout
+ lea largest_msg(%rip), %rsi
+ movq $5, %rdx # length of message
+ syscall
+
+ movq largest(%rip), %rax # Load the largest value
+ call print_integer
+
+ # Print newline
+ movq $1, %rax
+ movq $1, %rdi
+ lea newline(%rip), %rsi
+ movq $1, %rdx
+ syscall
+
+ # Print the smallest value
+ movq $1, %rax
+ movq $1, %rdi
+ lea smallest_msg(%rip), %rsi
+ movq $25, %rdx
+ syscall
+
+ movq smallest(%rip), %rax # Load the smallest value
+ call print_integer
+
+ # Print newline
+ movq $1, %rax
+ movq $1, %rdi
+ lea newline(%rip), %rsi
+ movq $1, %rdx
+ syscall
+
+ # Exit program
+ movq $60, %rax # syscall: exit
+ xorq %rdi, %rdi
+ syscall
+
+string_to_int:
+ # Convert null-terminated string at %rsi to integer in %rax
+ xorq %rax, %rax # Clear %rax (result)
+ xorq %rbx, %rbx # Clear %rbx (temporary register)
+
+convert_loop:
+ movb (%rsi), %bl # Load next character
+ cmpb $0, %bl # Check for null terminator
+ je convert_done
+ subb $48, %bl # Convert ASCII to integer
+ imulq $10, %rax # Multiply result by 10
+ addq %rbx, %rax # Add the current digit
+ incq %rsi # Move to the next character
+ jmp convert_loop
+
+convert_done:
+ ret
+
+print_integer:
+ # Convert integer in %rax to string and print it
+ pushq %rbp
+ movq %rsp, %rbp
+ subq $16, %rsp
+
+ movq $10, %rbx # Base 10 divisor
+ xorq %rcx, %rcx # Counter for digits
+ movq %rax, %rdx # Copy number to %rdx
+
+ # Convert digits to string in reverse order
+convert_digit:
+ xorq %r8, %r8 # Clear temporary
+ divq %rbx # Divide %rdx by 10, remainder in %rax
+ addb $48, %al # Convert remainder to ASCII
+ movb %al, -1(%rbp,%rcx) # Store digit
+ incq %rcx # Increment digit count
+ testq %rdx, %rdx # Check if quotient is 0
+ jne convert_digit
+
+ # Print the digits
+ movq $1, %rax # syscall: write
+ movq $1, %rdi # file descriptor: stdout
+ lea -1(%rbp,%rcx), %rsi # Start of digits
+ movq %rcx, %rdx # Length of string
+ syscall
+
+ movq %rbp, %rsp
+ popq %rbp
+ ret
+
assignments/3/max_min.s
@@ -2,11 +2,11 @@
.text
_start:
- # write(1, message, 13)
+ # write(1, greeting, 16)
mov $1, %rax # system call 1 is write
mov $1, %rdi # file handle 1 is stdout
- mov $message, %rsi # address of string to output
- mov $13, %rdx # number of bytes
+ mov $greeting, %rsi # address of string to output
+ mov $16, %rdx # number of bytes
syscall # invoke operating system to do the write
# read(0, input, 3)
@@ -16,6 +16,27 @@ _start:
mov $4, %rdx # number of bytes
syscall # invoke operating system to do the write
+ # write(1, max_message, 4)
+ mov $1, %rax # system call 1 is write
+ mov $1, %rdi # file handle 1 is stdout
+ mov $max_message, %rsi # address of string to output
+ mov $5, %rdx # number of bytes
+ syscall # invoke operating system to do the write
+
+ # write(1, input, 4)
+ mov $1, %rax # system call 1 is write
+ mov $1, %rdi # file handle 1 is stdout
+ mov $input, %rsi # address of string to output
+ mov $4, %rdx # number of bytes
+ syscall # invoke operating system to do the write
+
+ # write(1, min_message, 4)
+ mov $1, %rax # system call 1 is write
+ mov $1, %rdi # file handle 1 is stdout
+ mov $min_message, %rsi # address of string to output
+ mov $5, %rdx # number of bytes
+ syscall # invoke operating system to do the write
+
# write(1, input, 4)
mov $1, %rax # system call 1 is write
mov $1, %rdi # file handle 1 is stdout
@@ -29,5 +50,9 @@ _start:
syscall # invoke operating system to exit
.data
-message: .ascii "Hello, world\n"
+greeting: .ascii "Enter numbers: \n"
+max_message: .ascii "Max: "
+min_message: .ascii "Min: "
input: .word 0
+max: .word 0
+min: .word 0
assignments/3-solution.md
@@ -6,8 +6,16 @@ Choose ONE exercise each from Chapters 6, 7, and 8
Chapter 6:
-> 13. Write a complete assembly language program (including all necessary pseudo-ops) that reads in a series of integers, one at a time, and outputs the largest and smallest values. The input will consist of a list of integer values
+> 13. Write a complete assembly language program (including all necessary
+> pseudo-ops) that reads in a series of integers, one at a time, and outputs
+> the largest and smallest values. The input will consist of a list of integer
+> values
+```assembly
+!include assignments/3/max_min.s
+```
+
+<!--
I wrote the following C code and then used the GNU C Compiler to convert the C
code into Assembly code for my machine. Below is the C code, compiler command,
and final assembly code.
@@ -26,6 +34,7 @@ main.s
```assembly
!include assignments/3/main.s
```
+-->
Chapter 7:
@@ -129,3 +138,9 @@ $ ruby caesar.rb
| Ciphertext | RTAJ TZY FY IFBS |
| Plaintext | MOVE OUT AT DAWN |
```
+
+References:
+
+* https://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/
+* https://ftp.gnu.org/old-gnu/Manuals/gas-2.9.1/html_chapter/as_7.html
+* https://cs.lmu.edu/~ray/notes/gasexamples/
3431709-assignment-3.pdf
Binary file
3431709-assignment-4.pdf
Binary file