Lab4
Introduction
This project demonstrates the implementation of loops in AArch64 and x86_64 assembly languages. The objective is to print numbers from 0–10
and 0–30
in specific formats, leveraging both single and double-digit handling mechanisms. The implementation showcases system calls, ASCII conversion, and data handling techniques.
AArch64 Assembly: Loop from 0 to 10
This code outputs numbers from 0
to 10
, appending them to a predefined string "Loop: "
. The loop index is converted to ASCII before being displayed.
.text
.globl _start
// Define constants
min = 0 // Starting value for the loop index
max = 10 // Maximum value for the loop index
_start:
mov x19, min // Initialize the loop counter to 0
loop:
mov x0, 1 // File descriptor: 1 (stdout)
adr x1, msg // Address of the message template
mov x2, len // Message length
mov x4, x19 // Copy loop index to x4
add x4, x4, 48 // Convert the loop index to ASCII
strb w4, [x1, 6] // Insert ASCII value into the message
mov x8, 64 // Syscall number for write
svc 0 // Perform the syscall
add x19, x19, 1 // Increment the loop counter
cmp x19, max // Compare loop counter with max value
b.ne loop // Repeat the loop if the counter is not max
mov x0, 0 // Exit status
mov x8, 93 // Syscall number for exit
svc 0 // Perform the syscall
.data
msg: .ascii "Loop: 0\n" // Message template with a placeholder
len = . - msg // Length of the message
AArch64 Assembly: Loop from 0 to 30
This implementation extends the logic to handle two-digit numbers. It uses division to calculate the tens and ones places of the numbers.
.text
.globl _start
// Define constants
min = 0 // Starting value for the loop index
max = 31 // Maximum value for the loop index
ten = 10 // Divisor for two-digit conversion
_start:
mov x19, min // Initialize loop counter
mov x20, ten // Load divisor into register x20
loop:
mov x0, x19 // Copy loop index into x0
udiv x2, x0, x20 // Calculate quotient (tens place)
msub x3, x2, x20, x0 // Calculate remainder (ones place)
add x2, x2, 48 // Convert quotient to ASCII
add x3, x3, 48 // Convert remainder to ASCII
adr x1, msg // Address of the message template
strb w2, [x1, 6] // Insert tens place ASCII
strb w3, [x1, 7] // Insert ones place ASCII
mov x0, 1 // File descriptor: 1 (stdout)
mov x2, len // Message length
mov x8, 64 // Syscall number for write
svc 0 // Perform the syscall
add x19, x19, 1 // Increment loop counter
cmp x19, max // Compare loop counter with max value
b.ne loop // Repeat the loop if not equal
mov x0, 0 // Exit status
mov x8, 93 // Syscall number for exit
svc 0 // Perform the syscall
.data
msg: .ascii "Loop: 00\n" // Message template with placeholders
len = . - msg // Length of the message
x86_64 Assembly: Loop from 0 to 10
This implementation uses NASM syntax to print numbers from 0
to 10
, appending them to the string "Loop: "
.
section .data
prefix: db "Loop: ", 0 ; The string "Loop: "
newline: db 10 ; Newline character (ASCII 10)
counter: db 0 ; Placeholder for ASCII character
section .text
global _start
_start:
mov r15, 0 ; Initialize loop counter to 0
loop:
mov rax, 1 ; Syscall for write
mov rdi, 1 ; File descriptor: stdout
mov rsi, prefix ; Address of "Loop: "
mov rdx, 6 ; Length of "Loop: "
syscall ; Perform the syscall
mov rax, r15 ; Move loop counter into rax
add rax, 48 ; Convert to ASCII
mov [counter], al ; Store ASCII character in memory
mov rax, 1 ; Syscall for write
mov rdi, 1 ; File descriptor: stdout
mov rsi, counter ; Address of the ASCII character
mov rdx, 1 ; Length of 1 character
syscall ; Perform the syscall
mov rax, 1 ; Syscall for write
mov rdi, 1 ; File descriptor: stdout
mov rsi, newline ; Address of newline character
mov rdx, 1 ; Length of 1 character
syscall ; Perform the syscall
inc r15 ; Increment loop counter
cmp r15, 10 ; Compare with max value
jl loop ; Repeat if less than 10
mov rax, 60 ; Syscall for exit
xor rdi, rdi ; Exit status: 0
syscall ; Perform the syscall
x86_64 Assembly: Loop from 0 to 30
This implementation extends the logic for handling two-digit numbers using division.
section .data
prefix: db "Loop: ", 0 ; The string "Loop: "
newline: db 10 ; Newline character (ASCII 10)
counter: db "00", 0 ; Placeholder for two-digit ASCII number
section .text
global _start
_start:
mov r15, 0 ; Initialize loop counter to 0
loop:
mov rax, 1 ; Syscall for write
mov rdi, 1 ; File descriptor: stdout
mov rsi, prefix ; Address of "Loop: "
mov rdx, 6 ; Length of "Loop: "
syscall ; Perform the syscall
mov rax, r15 ; Move loop counter into rax
mov rbx, 10 ; Divisor for two-digit conversion
xor rdx, rdx ; Clear rdx for division
div rbx ; Divide rax by 10
add rax, 48 ; Convert quotient to ASCII
mov [counter], al ; Store tens place ASCII
add rdx, 48 ; Convert remainder to ASCII
mov [counter+1], dl ; Store ones place ASCII
mov rax, 1 ; Syscall for write
mov rdi, 1 ; File descriptor: stdout
mov rsi, counter ; Address of the ASCII characters
mov rdx, 2 ; Length of 2 characters
syscall ; Perform the syscall
mov rax, 1 ; Syscall for write
mov rdi, 1 ; File descriptor: stdout
mov rsi, newline ; Address of newline character
mov rdx, 1 ; Length of 1 character
syscall ; Perform the syscall
inc r15 ; Increment loop counter
cmp r15, 31 ; Compare with max value
jl loop ; Repeat if less than 31
mov rax, 60 ; Syscall for exit
xor rdi, rdi ; Exit status: 0
syscall ; Perform the syscall
Conclusion
This lab required careful attention to detail, as it involved implementing loops in AArch64 and x86_64 assembly languages. Debugging system calls, ASCII conversion, and handling two-digit numbers presented some difficulties, particularly when working with low-level operations. On AArch64, using division and modular arithmetic required precision, while x86_64’s div
instruction and memory manipulation showcased its flexibility. Overall, the lab deepened my understanding of computer architecture and improved my skills in debugging and low-level programming.
Comments
Post a Comment