Lab 5 - 64-Bit Assembly Language - Aarch64
64-Bit Assembly Language
In this lab, I will be conducting experiments with assemblers on both the x86_64 and Aarch64 platforms.
Get code example
The first step is to retrieve the code example from the server. The example is located in /public/spo600-assembler-lab-examples.tgz
, which is a compressed file. To extract the file and store it in the desired location, navigate to that location. For me, it's the home directory:
cd ~ tar xvf /public/spo600-assembler-lab-examples.tgz
After running the command, the files will be extracted to your current location. You will see a folder named spo600.
Investigating C version code
We can use the above command to extract the same code example on both platform servers. Now, let's check if there are any differences between the x86_64 and Aarch64 platforms.
First, navigate to the folder containing the C version of the program and run the make
command to compile it. Then, use the following command to disassemble the binary and view the assembly instructions:
objdump -d hello
#include <stdio.h>
int main() {
printf("Hello World!\n");
}
Aarch64 platform
cat hello.s
Disassemble the binary and view the assembly instructions by:
objdump -d hello
We can see that the instructions are the same, but the value has changed from decimal value to hexadecimal value.
Fixing a loop in Aarch64
.text .globl _start min = 0 /* starting value for the loop index; **note that this is a symbol (constant)**, not a variable */ max = 6 /* loop exits when the index hits this number (loop condition is i<max) */ _start: mov x19, min loop: /* ... body of the loop ... do something useful here ... */ add x19, x19, 1 /* increment the loop counter */ cmp x19, max /* see if we've hit the max */ b.ne loop /* if not, then continue the loop */ mov x0, 0 /* set exit status to 0 */ mov x8, 93 /* exit is syscall #93 */ svc 0 /* invoke syscall */
Print out the word "Loop" each time it loops:
.text
.globl _start
min = 0 /* starting value for the loop index; **note that this is a symbol (constant)**, not a variable */
max = 6 /* loop exits when the index hits this number (loop condition is i<max) */
_start:
mov x19, min
loop:
/* ... body of the loop ... do something useful here ... */
/* ============== Start ============== */
mov x0, 1 // File descriptor: 1 is stdout
adr x1, msg // message location (memory address)
mov x2, len // message length (bytes)
mov x8, 64 // write is syscall #64
svc 0 // invoke syscall
/* =============== End =============== */
add x19, x19, 1 /* increment the loop counter */
cmp x19, max /* see if we've hit the max */
b.ne loop /* if not, then continue the loop */
mov x0, 0 /* set exit status to 0 */
mov x8, 93 /* exit is syscall #93 */
svc 0 /* invoke syscall */
.data
msg: .ascii "Loop\n"
len= . - msg
Result:
.text .globl _start min = 0 /* starting value for the loop index; **note that this is a symbol (constant)**, not a variable */ max = 6 /* loop exits when the index hits this number (loop condition is i<max) */ _start: mov x19, min loop: /* ... body of the loop ... do something useful here ... */ /* ============== Start ============== */ mov x0, 1 // File descriptor: 1 is stdout adr x1, msg // message location (memory address) mov x2, len // message length (bytes) mov x8, 64 // write is syscall #64 svc 0 // invoke syscall adr x5, buffer // Load buffer into x5 register mov x3, x19 // copy loop count x19 to x3 add x3, x3, 48 // Convert number to character strb w3, [x5] // Store number character in buffer add x5, x5, 1 // move to next byte in buffer mov x3, 10 // 10 is newline character in ASCII strb w3, [x5] // store newline character in buffer mov x0, 1 // File descriptor: 1 is stdout adr x1, buffer // buffer loaction (memory address) mov x2, 2 // buffer length mov x8, 64 // write is syscall #64 svc 0 // invoke syscall /* =============== End =============== */ add x19, x19, 1 /* increment the loop counter */ cmp x19, max /* see if we've hit the max */ b.ne loop /* if not, then continue the loop */ mov x0, 0 /* set exit status to 0 */ mov x8, 93 /* exit is syscall #93 */ svc 0 /* invoke syscall */ .data msg: .ascii "Loop: " len= . - msg buffer: .space 2
Result:
Print out the loop number with 2 digits until 32. For example, 0 is 00.
.text .globl _start min = 0 /* starting value for the loop index; **note that this is a symbol (constant)**, not a variable */ max = 33 /* loop exits when the index hits this number (loop condition is i<max) */ _start: mov x19, min loop: /* ... body of the loop ... do something useful here ... */ /* ============== Start ============== */ mov x0, 1 // File descriptor: 1 is stdout adr x1, msg // message location (memory address) mov x2, len // message length (bytes) mov x8, 64 // write is syscall #64 svc 0 // invoke syscall adr x5, buffer // Load buffer into x5 register mov x3, x19 // copy loop count x19 to x3 mov x4, 10 // store #10 in x4 udiv x6, x3, x4 // x6 = x3(loop count) / x4(16) msub x7, x6, x4, x3 // x7 = x3(loop count) - (x6 * x4) add x6, x6, 48 // Convert number to character strb w6, [x5] // Store to buffer add x5, x5, 1 // Move to next byte in buffer add x7, x7, 48 // Convert number to character strb w7, [x5] // Store to buffer add x5, x5, 1 // Move to next byte in buffer mov x3, 10 // 10 is newline character in ASCII strb w3, [x5] // Store newline character in buffer mov x0, 1 // File descriptor: 1 is stdout adr x1, buffer // buffer loaction (memory address) mov x2, 3 // buffer length mov x8, 64 // write is syscall #64 svc 0 // invoke syscall /* =============== End =============== */ add x19, x19, 1 /* increment the loop counter */ cmp x19, max /* see if we've hit the max */ b.ne loop /* if not, then continue the loop */ mov x0, 0 /* set exit status to 0 */ mov x8, 93 /* exit is syscall #93 */ svc 0 /* invoke syscall */ .data msg: .ascii "Loop: " len= . - msg buffer: .space 3
Result:
Print out the loop number with 1 digit when the number is less than 10.
.text .globl _start min = 0 /* starting value for the loop index; **note that this is a symbol (constant)**, not a variable */ max = 33 /* loop exits when the index hits this number (loop condition is i<max) */ _start: mov x19, min loop: /* ... body of the loop ... do something useful here ... */ /* ============== Start ============== */ mov x0, 1 // File descriptor: 1 is stdout adr x1, msg // message location (memory address) mov x2, len // message length (bytes) mov x8, 64 // write is syscall #64 svc 0 // invoke syscall adr x5, buffer // Load buffer into x5 register mov x3, x19 // copy loop count x19 to x3 mov x4, 10 // store #10 in x4 udiv x6, x3, x4 // x6 = x3(loop count) / x4(16) msub x7, x6, x4, x3 // x7 = x3(loop count) - (x6 * x4) cmp x6, 0 // Check if ten digit is 0 b.eq units_digit // Skip ten digit if it is 0 add x6, x6, 48 // Convert number to character strb w6, [x5] // Store to buffer add x5, x5, 1 // Move to next byte in buffer units_digit: add x7, x7, 48 // Convert number to character strb w7, [x5] // Store to buffer add x5, x5, 1 // Move to next byte in buffer mov x3, 10 // 10 is newline character in ASCII strb w3, [x5] // Store newline character in buffer mov x0, 1 // File descriptor: 1 is stdout adr x1, buffer // buffer loaction (memory address) mov x2, 3 // buffer length mov x8, 64 // write is syscall #64 svc 0 // invoke syscall /* =============== End =============== */ add x19, x19, 1 /* increment the loop counter */ cmp x19, max /* see if we've hit the max */ b.ne loop /* if not, then continue the loop */ mov x0, 0 /* set exit status to 0 */ mov x8, 93 /* exit is syscall #93 */ svc 0 /* invoke syscall */ .data msg: .ascii "Loop: " len= . - msg buffer: .space 3
Result:
Print out the loop number in hexadecimal instead of decimal number.
.text .globl _start min = 0 /* starting value for the loop index; **note that this is a symbol (constant)**, not a variable */ max = 33 /* loop exits when the index hits this number (loop condition is i<max) */ _start: mov x19, min loop: /* ... body of the loop ... do something useful here ... */ /* ============== Start ============== */ mov x0, 1 // File descriptor: 1 is stdout adr x1, msg // message location (memory address) mov x2, len // message length (bytes) mov x8, 64 // write is syscall #64 svc 0 // invoke syscall adr x5, buffer // Load buffer into x5 register mov x3, x19 // copy loop count x19 to x3 mov x4, 16 // store #16 in x4 udiv x6, x3, x4 // x6 = x3(loop count) / x4(16) msub x7, x6, x4, x3 // x7 = x3(loop count) - (x6 * x4) cmp x6, 0 // Check if ten digit is 0 b.eq units_digit // Skip ten digit if it is 0 add x6, x6, 48 // Convert number to character strb w6, [x5] // Store to buffer add x5, x5, 1 // Move to next byte in buffer units_digit: add x7, x7, 48 // Convert number to character cmp x7, 58 // Compare if the character code is greater than 59. 0-9 is ASCII value 48-57 b.lt st_unit // Go to store unit st_unit if it is less than 58. add x7, x7, 7 // If it is greater than 58, add 7 to convert to A-E st_unit: strb w7, [x5] // Store to buffer add x5, x5, 1 // Move to next byte in buffer mov x3, 10 // 10 is newline character in ASCII strb w3, [x5] // Store newline character in buffer mov x0, 1 // File descriptor: 1 is stdout adr x1, buffer // buffer loaction (memory address) mov x2, 3 // buffer length mov x8, 64 // write is syscall #64 svc 0 // invoke syscall /* =============== End =============== */ add x19, x19, 1 /* increment the loop counter */ cmp x19, max /* see if we've hit the max */ b.ne loop /* if not, then continue the loop */ mov x0, 0 /* set exit status to 0 */ mov x8, 93 /* exit is syscall #93 */ svc 0 /* invoke syscall */ .data msg: .ascii "Loop: " len= . - msg buffer: .space 3
Comments
Post a Comment