Writing assembly code can be an enlightening experience, offering a deep dive into the inner workings of a computer's architecture. In this blog post on Lab 3, we'll explore the process of writing and debugging assembly code for two different architectures: AArch64 and x86_64. We'll contrast the two and share our experiences with each.
AArch64 Assembly Code
Here's a snippet of assembly code written for the AArch64 architecture:
.text
.globl _start
min_val = 0
max_val = 30
zero_char = 0x30
_start:
mov x19, min_val
mov w6, zero_char
mov w7, zero_char
loop:
mov x0, 1
adr x1, msg
mov x2, len
mov x8, 64
mov x23, 0xA
udiv x24, x19, x23
msub x25, x24, x23, x19
cmp x24, 0x0
b.eq setup_second_digit
mov w6, w24
mov w7, w25
mov w26, zero_char
add w6, w6, w26
add w7, w7, w26
add x3, x1, 6
strb w6, [x3]
setup_second_digit:
add x3, x1, 7
strb w7, [x3]
svc 0
add x19, x19, 1
add w7, w7, 1
cmp x19, max_val
b.ne loop
mov x0, 0
mov x8, 93
svc 0
.data
msg: .ascii "Loop: \n"
len= . - msg
Explanation:
- The code begins with `.text` directive, indicating the start of executable instructions.
- `_start` is declared as the entry point of the program.
- Constants such as `loop_index`, `loop_max`, and `zero_char` are defined.
- The loop iterates from `loop_index` to `loop_max`.
- Inside the loop, the current index is divided to obtain the first and second digits.
- ASCII characters for the digits are obtained and stored in the `msg` string.
- The message is printed to the standard output using the `syscall` instruction.
- The loop continues until `loop_index` reaches `loop_max`.
- Finally, the program exits with a system call.
- This is what the loop prints on screen:
[mwrajani@aarch64-001 lab3]$ ./loop
Loop: 0
Loop: 1
Loop: 2
Loop: 3
Loop: 4
Loop: 5
Loop: 6
Loop: 7
Loop: 8
Loop: 9
Loop: 10
Loop: 11
Loop: 12
Loop: 13
Loop: 14
Loop: 15
Loop: 16
Loop: 17
Loop: 18
Loop: 19
Loop: 20
Loop: 21
Loop: 22
Loop: 23
Loop: 24
Loop: 25
Loop: 26
Loop: 27
Loop: 28
Loop: 29
x86_64 Assembly Code
Here's a snippet of assembly code written for the x86_64 architecture:
.text
.globl _start
loop_index = 0
loop_max = 30
zero_char = 48
_start:
movq $loop_index, %rbx
loop:
movq %rbx, %rax
movq $10, %rcx
xor %rdx, %rdx
div %rcx
add $zero_char, %rdx
cmp $0, %rax
je setup_second_digit
add $zero_char, %rax
movq $msg, %rdi
add $6, %rdi
stosb
setup_second_digit:
movq $msg, %rdi
add $7, %rdi
movq %rdx, %rax
stosb
movq $1, %rdi
movq $msg, %rsi
movq $len, %rdx
movq $1, %rax
syscall
inc %rbx
cmp $loop_max, %rbx
jne loop
mov $0, %rdi
mov $60, %rax
syscall
.data
msg: .ascii "Loop: \n"
len= . - msg
Explanation:
- The code starts with `.text` directive and `_start` as the entry point.
- Constants such as `min_val`, `max_val`, and `zero_char` are defined.
- The loop iterates from `min_val` to `max_val`.
- Inside the loop, the current index is divided to obtain the first and second digits.
- ASCII characters for the digits are obtained and stored in the `msg` string.
- The message is printed to the standard output using the `svc` instruction.
- The loop continues until `min_val` reaches `max_val`.
- Finally, the program exits with a system call.
- This is what the loop prints on screen, although it is the same as aarch64, but it is expected as we are also doing the same thing:
[mwrajani@x86-001 lab3]$ ./loop
Loop: 0
Loop: 1
Loop: 2
Loop: 3
Loop: 4
Loop: 5
Loop: 6
Loop: 7
Loop: 8
Loop: 9
Loop: 10
Loop: 11
Loop: 12
Loop: 13
Loop: 14
Loop: 15
Loop: 16
Loop: 17
Loop: 18
Loop: 19
Loop: 20
Loop: 21
Loop: 22
Loop: 23
Loop: 24
Loop: 25
Loop: 26
Loop: 27
Loop: 28
Loop: 29
Writing and Debugging Experience
Writing assembly code for both architectures offers a unique insight into how the underlying hardware operates. AArch64 assembly, with its distinct syntax and register names, requires a thorough understanding of the architecture's instruction set. Debugging AArch64 code often involves meticulous examination of register values and memory accesses.
On the other hand, x86_64 assembly, being more ubiquitous, may feel more familiar to those accustomed to Intel-based systems. Debugging x86_64 code is aided by the availability of numerous tools and resources, making it relatively straightforward to identify and fix issues.
Conclusion
In conclusion, writing assembly code for AArch64 and x86_64 architectures provides valuable insights into low-level system operations. While each architecture has its own syntax and nuances, the fundamentals of assembly programming remain consistent. By understanding these differences, developers can gain a deeper appreciation for the inner workings of modern computing systems.
No comments:
Post a Comment