Lab-3
Exploring Assembly Language on x86_64 and AArch64
Introduction
In this lab, we dive into the intricacies of assembler on both x86_64 and AArch64 architectures. We'll explore code examples, disassemble object files, and write simple assembly programs to understand the core differences and functionalities between these architectures.
Setting Up
First, we unpacked the provided code examples:
cd ~
tar xvf /public/spo600-assembler-lab-examples.tgz
This created a directory structure under ~/spo600/examples/
, containing various examples in C and assembly for both architectures.
Building and Running C Programs
We started with the C programs to establish a baseline:
- Building the C programs:
cd ~/spo600/examples/c make
- Running the C programs:
./hello ./hello2 ./hello3
- Observing the differences:
hello.c
usesprintf()
.hello2.c
useswrite()
.hello3.c
usessyscall()
directly.
Disassembling C Binaries
Using objdump
, we disassembled the binaries to view their assembly code:
objdump -d hello > hello_disassembly.txt objdump -d hello2 > hello2_disassembly.txt objdump -d hello3 > hello3_disassembly.txt
Examining the <main>
sections revealed differences in how each function call is translated into machine code. The C binaries included additional setup and teardown code, which was absent in pure assembly programs.
x86_64 Assembly Programs
Next, we turned to the x86_64 assembly programs:
- Building the assembly programs:
cd ~/spo600/examples/hello/assembler/x86_64 make
- Disassembling and comparing:
objdump -d hello-gas > hello_gas_disassembly.txt objdump -d hello-nasm > hello_nasm_disassembly.txt
The assembly code generated was leaner compared to the C binaries, as it didn't include the extra overhead required for C runtime support.
AArch64 Assembly Programs
We followed similar steps for the AArch64 assembly programs:
- Building the assembly programs:
cd ~/spo600/examples/hello/assembler/aarch64 make
- Disassembling and verifying:
objdump -d hello > hello_aarch64_disassembly.txt
Writing Assembly Programs
AArch64 Loop Example
We modified the provided loop example to print a message along with the loop index:
.text .globl _start min = 0 max = 10 _start: mov x19, min loop: // Print "Loop: " mov x0, 1 ldr x1, =msg mov x2, 6 mov x8, 64 svc 0 // Convert index to character and print add x21, x19, 0x30 mov x0, 1 mov x1, x21 mov x2, 1 mov x8, 64 svc 0 // Print newline ldr x1, =newline mov x2, 1 mov x8, 64 svc 0 // Increment and loop add x19, x19, 1 cmp x19, max b.ne loop // Exit mov x0, 0 mov x8, 93 svc 0 .data msg: .ascii "Loop: " newline: .ascii "\n"
Loop from 00 to 30
We extended the loop to print two-digit numbers:
.text .globl _start min = 0 max = 31 _start: mov x19, min loop: // Print "Loop: " mov x0, 1 ldr x1, =msg mov x2, 6 mov x8, 64 svc 0 // Convert tens place udiv x20, x19, 10 add x20, x20, 0x30 mov x0, 1 mov x1, x20 mov x2, 1 mov x8, 64 svc 0 // Convert units place msub x21, x19, x20, 10 add x21, x21, 0x30 mov x0, 1 mov x1, x21 mov x2, 1 mov x8, 64 svc 0 // Print newline ldr x1, =newline mov x2, 1 mov x8, 64 svc 0 // Increment and loop add x19, x19, 1 cmp x19, max b.ne loop // Exit mov x0, 0 mov x8, 93 svc 0 .data msg: .ascii "Loop: " newline: .ascii "\n"
Experience and Reflection
Writing and debugging in assembly language is an enlightening experience. It offers a granular level of control over the hardware, allowing us to see how high-level constructs translate into machine operations. However, it also demands meticulous attention to detail and a deep understanding of the hardware architecture.
Comparison: 6502, x86_64, and AArch64
- 6502 Assembly:
- Simpler and more constrained environment.
- Ideal for understanding the fundamentals of assembly language.
- x86_64 Assembly:
- More complex and powerful.
- Provides extensive instruction sets, but can be overwhelming due to its CISC nature.
- AArch64 Assembly:
- Balances between simplicity and power.
- RISC architecture makes it more intuitive after grasping the basics.
Overall, this lab provided invaluable insights into different assembly languages and architectures. The experience underscored the importance of understanding lower-level programming to appreciate the efficiency and performance of high-level applications.
Comments
Post a Comment