Lab 4 - 64-bit Assembly Language Lab - Part 4
Welcome to part 3 of lab 4. This lab goes over some basics of 64-bit assembly languages, specifically in the AArch64 and x86_64 platforms. This specific part will be going over the second half of the lab in the AArch64 system. Links for the other parts are listed here:
Part 1 - First half in AArch64
Part 2 - First half in x86_64
Part 3 - Second half in AArch64
I'll be outlining the steps in detail as I go along but the full instructions for this lab can be found here.
Okay we're in the homestretch. Just like part 3 we're making our loop print from 00-30. I learned my lesson from part 3 and pre-labelled my code, and I was already planning on trying to reduce the overall amount of registers I use but x86_64 seems to have less safe registers anyways so I was somewhat forced to. Major difference here is the div function. The div function in x86_64 calculates the remainder too so that was pretty convenient. It's a bit less intuitive, it takes one argument, a register, and it divides rax by that register, changing it to the quotient and putting the remainder in rdx, (which has to be cleared before the div). Weird way to do it but it feels less cumbersome somehow. Anyways after that I'm just moving rax and rdx to registers 12 and 13 respectively, which are the first and second digit respectively. Then just as before I'm inserting them into the message. Easy peasy. Code provided below:
.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:
print:
mov $min,%r15 /* loop index */
mov $10,%rbx /* variable set to 10 for dividing */
loop:
mov $0,%rdx /* set rdx to zero for the div */
mov %r15,%rax /* move index value to rax for div */
div %rbx /* the division */
mov %rax,%r12 /* move quotient (first digit) to r12 */
mov %rdx,%r13 /* move remainder (second digit) to r13 */
firstDigit: /* inserting first digit into msg */
mov %r12,%r14
add $'0',%r14
movb %r14b,msg+6
secondDigit: /* inserting second digit into msg */
mov %r13,%r14
add $'0',%r14
movb %r14b,msg+7
//print 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 loop
inc %r15 /* increment index */
cmp $max,%r15 /* see if we're done */
jne loop /* loop if we're not */
mov $0,%rdi /* exit status */
mov $60,%rax /* syscall sys_exit */
syscall
.section .data
msg: .ascii "Loop: ##\n"
len = . - msg
And as always, the output:
Loop: 00
Loop: 01
Loop: 02
Loop: 03
Loop: 04
Loop: 05
Loop: 06
Loop: 07
Loop: 08
Loop: 09
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
Loop: 30
Now, just as part 3, I suppress the lead zero. There's not much to say here. It gave me no problem cuz it worked just the same as AArch64. I used the same logic, if the first digit is zero, jump to the suppressLeadZero to make the first digit a space, and if not, insert the first digit as usual and then jump over suppressLeadZero to secondDigit.
.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:
print:
mov $min,%r15 /* loop index */
mov $10,%rbx /* variable set to 10 for dividing */
loop:
mov $0,%rdx /* set rdx to zero for the div */
mov %r15,%rax /* move index value to rax for div */
div %rbx /* the division */
mov %rax,%r12 /* move quotient (first digit) to r12 */
mov %rdx,%r13 /* move remainder (second digit) to r13 */
cmp $0,%r12 /* check if first digit is zero */
je suppressLeadZero /* suppress lead zero */
firstDigit: /* inserting first digit into msg */
mov %r12,%r14
add $'0',%r14
movb %r14b,msg+6
jmp secondDigit
suppressLeadZero: /* insert space in first digit slot, only called if first digit is zero */
mov $' ',%r14
movb %r14b,msg+6
secondDigit: /* insertng second digit into msg */
mov %r13,%r14
add $'0',%r14
movb %r14b,msg+7
//print 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 loop
inc %r15 /* increment index */
cmp $max,%r15 /* see if we're done */
jne loop /* loop if we're not */
mov $0,%rdi /* exit status */
mov $60,%rax /* syscall sys_exit */
syscall
.section .data
msg: .ascii "Loop: ##\n"
len = . - msg
Here's the output once again:
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
Loop: 30
Final Summary
Honestly thought I'd have more to say but my thoughts remain very similar to the first half summary, I oddly find x86_64 a bit nicer. It's math systems seem a bit odd but I prefer them, and I really did not like msub in AArch64. But despite that the differences still aren't huge for making me prefer one over the other. I still do feel AArch64 feels more intuitive, even if msub exists, and overall this lab was pretty fun and I did end up enjoying both systems.
Comments
Post a Comment