1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
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
|