RE-POST March: Lab 3
This post would be about the experiments that I have done with assembler using x86-64 and aarch64 platforms.
At the end of this lab, I found working with these two servers quite enjoyable. I like how I can practice Linux commands on the terminal which I didn't really have a lot of chance to do since my first semester in ULI101. Even though it took me more time to write in assembler using the vi command since I had forgotten how to navigate around with only the keyboard. However, I found that the debugger tool in the assembler is very convenient and tells me exactly which line is the problem.
Experiment on x86-64 and aarch64
In both the AArch64 and x86_64 machine:
ll /public/spo600-assemble-lab-examples.tgz
The extension .tgz file means that it is a tar file created with the tar archiving program and it has been compressed.
To expand the archive:
tar xvf /public/spo600-assemble-lab-examples.tgz
Afterward, I created the lab3 dictionary that has loop.s and Makefile files:
mkdir lab3
cd lab3
touch loop.s Makefile
The following links are references used to do this lab:
- https://toronto.tylers.info/dokuwiki-toronto/doku.php?id=spo600:x86_64_register_and_instruction_quick_start (updated 2024-04-17, due to the previous wiki no longer working)
- https://toronto.tylers.info/dokuwiki-toronto/doku.php?id=spo600:aarch64_register_and_instruction_quick_start (updated 2024-04-17, due to the previous wiki no longer working)
Optional Investigation
These steps were done in the previous post
Lab Tasks
Steps 1-3 were done in the previous post.
To extend the code from 00-30 and print each value as a 2-digit decimal number:
In AArch64
.text
.globl _start
min = 0 /* starting value for the loop index; **note that this is a symbol (constant)**, not a variable */
max = 31 /* loop exits when the index hits this number (loop condition is i<max) */
_start:
mov x19, min
loop:
/* Divide loop counter by 10 to separate the digits */
mov x10, x19
/* Copy loop counter to x10 for division */
mov x9, 10
udiv x0, x10, x9
msub x1, x0, x9, x10
/* Convert tens digit to char */
add x0, x0, 0x30
adr x14,msg+6
strb w0,[x14]
/* Convert loop counter to char for the ones digit */
add x1, x1, 0x30 /* add 48 to convert to char */
adr x14, msg+7 strb w1, [x14]
/* Print the message */
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 */
/* Continue the loop */
add x19, x19, 1
cmp x19, max
b.ne loop
/* Exit the program */
mov x0, 0 /* status -> 0 */
mov x8, 93 /* exit is syscall #93 */
svc 0 /* invoke syscall */
.data
msg: .ascii "Loop: ##\n"
len= . - msg
.text
.globl _start
min = 0 /* starting value for the loop index; **note that this is a symbol (constant)**, not a variable */
max = 31 /* loop exits when the index hits this number (loop condition is i<max) */
_start:
mov x19, min
loop:
/* Divide loop counter by 10 to separate the digits */
mov x10, x19
/* Copy loop counter to x10 for division */
mov x9, 10
udiv x0, x10, x9
msub x1, x0, x9, x10
/* For numbers < 10, check for divsion == 0 */
cmp x0, 0
b.eq skipDoubleDigit
/* Convert tens digit to char */
add x0, x0, 0x30
adr x14,msg+6
strb w0,[x14]
b storeSingleDigit
skipDoubleDigit:
mov x0, 0x20 /* Space */
adr x14, msg+6 strb w0,[x14]
storeSingleDigit:
/* Convert loop counter to char for the ones digit */
add x1, x1, 0x30 /* add 48 to convert to char */
adr x14, msg+7
strb w1, [x14]
/* Print the message */
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 */
/* Continue the loop */
add x19, x19, 1
cmp x19, max
b.ne loop
/* Exit the program */
mov x0, 0 /* status -> 0 */
mov x8, 93 /* exit is syscall #93 */
svc 0 /* invoke syscall */
.data
msg: .ascii "Loop: ##\n"
len= . - msg
.text
.globl _start
min = 0 /* starting value for the loop index; **note that this is a symbol (constant)**, not a variable */
max = 31 /* loop exits when the index hits this number (loop condition is i<max) */ _start:
mov $min,%r15 /* loop index */
loop:
/* Convert loop counter to 2-digit */
mov %r15, %rax
mov $10, %rbx
xor %rdx, %rdx
div %rbx
/* Convert the double digits to char */
add $'0', %al
mov %al, msg+6
/* Convert single digit to char */
add $'0', %dl
mov %dl, msg+7
/* Print the message */
movq $len,%rdx /* message length */
movq $msg,%rsi /* message location */
movq $1,%rdi /* file descriptor stdout */
movq $1,%rax /* syscall sys_write */
syscall
/* Continue the loop */
inc %r15 /* increment index */
cmp $max,%r15 /* see if we're done */
jne loop /* loop if we're not */
/* Exit the program */
mov $0,%rdi /* exit status */
mov $60,%rax /* syscall sys_exit */
syscall
.section .data
msg: .ascii "Loop: ##\n"
len = . - msg
.text
.globl _start
min = 0 /* starting value for the loop index; **note that this is a symbol (constant)**, not a variable */
max = 31 /* loop exits when the index hits this number (loop condition is i<max) */
_start:
mov $min,%r15 /* loop index */
loop:
/* Convert loop counter to 2-digit */
mov %r15, %rax
mov $10, %rbx
xor %rdx, %rdx
div %rbx
/* Check if division=0 for double digit */
cmp $0, %al
je singleDigit
/* Convert the double digits to char */
add $'0', %al
mov %al, msg+6
jmp storeSingleDigit
singleDigit:
/* Update double digit to Space */
mov $' ', %al
mov %al, msg+6
storeSingleDigit:
/* Convert single digit to char */
add $'0', %dl
mov %dl, msg+7
/* Print the message */
movq $len,%rdx /* message length */
movq $msg,%rsi /* message location */
movq $1,%rdi /* file descriptor stdout */
movq $1,%rax /* syscall sys_write */
syscall
/* Continue the loop */
inc %r15 /* increment index */
cmp $max,%r15 /* see if we're done */
jne loop /* loop if we're not */
/* Exit the program */
mov $0,%rdi /* exit status */
mov $60,%rax /* syscall sys_exit */
syscall
.section .data
msg: .ascii "Loop: ##\n"
len = . - msg
At the end of this lab, I found working with these two servers quite enjoyable. I like how I can practice Linux commands on the terminal which I didn't really have a lot of chance to do since my first semester in ULI101. Even though it took me more time to write in assembler using the vi command since I had forgotten how to navigate around with only the keyboard. However, I found that the debugger tool in the assembler is very convenient and tells me exactly which line is the problem.
When working with the AArch64 machine and then switching to the x86 machine, I got a bit confused when I was writing the code, since in AArch64 you state the memory location first and then the value you want to store in it, while x86 is the opposite ways.
Learning 6502 first and then going to the more modern system, actually helped me a lot in understanding the instructions and how to write them properly in a bigger system.
Comments
Post a Comment