In this lab our instructions were to:
- Build and run three C versions of the hello.c program for x86_64 and aarch64.
- Modify the code so it prints the loop index values like so:
Loop: 0 Loop: 1 Loop: 2 Loop: 3 Loop: 4 Loop: 5 Loop: 6 Loop: 7 Loop: 8 Loop: 9
- Extend the code to loop from 00 – 30, printing each value as a 2-digit decimal number.
This lab was completed with my classmates Josue and Miguel. Writing in assembly was no easy task for us as it took us the entire lab to write the loop which repeated 10 times. We added comments in the assembly code explaining what operation that was happening on each line.
This was the x86_64 assembly code that we wrote for the in-class lab:
.text
.globl _start
start = 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) */
divisor = 10
zero = 48
_start:
mov $start,%r15 /* loop index */
loopmd:
cmp $divisor,%r15 /* see if loop index is less than 10 */
jl loopsg
mov $divisor,%r13 /* moved 10 to r13 */
mov %r15,%rax /* moved r15 to rax */
mov $zero,%r14 /* moved 48 to r14*/
mov $0,%rdx /* moved 0 to rdx */
div %r13 /* divided rax by r13 (loop index by 10) */
add %r14,%rax /* added r14 to rax (48 to the quotient of the division */
mov %rax,%r13 /* moved rax to r13 so I can then move only one byte to msg */
mov %r13b,msg+6
add %r14,%rdx /* added r15 to r14 */
mov %rdx,%r13 /* moved rdx to r13 so I can then move only one byte to msg */
mov %r13b,msg+7 /* added number after 'Loop' */
mov $len,%rdx /* message length */
mov $msg,%rsi /* message location */
mov $1,%rdi /* file descriptor stdout */
mov $1,%rax /* syscall sys_write */
syscall
jmp check
loopsg:
mov $zero,%r14 /* moved 48 to r14*/
add %r15,%r14 /* added r15 to r14 */
mov %r14b,msg+7 /* added number after 'Loop' */
mov $len,%rdx /* message length */
mov $msg,%rsi /* message location */
mov $1,%rdi /* file descriptor stdout */
mov $1,%rax /* syscall sys_write */
syscall
check:
inc %r15 /* increment index */
cmp $max,%r15 /* see if we're done */
jne loopmd /* 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
A link to the assembly code above can be found here: https://github.com/naiuhz/spo600/blob/master/lab3/86_64/loop.s
And for the aarch64 assembly code:
.text
.globl _start
start = 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) */
divisor = 10
zero = 48
/* note: registers 19-28 are safe */
_start:
mov x20,start /* loop index */
loop:
mov x2,len /* message length syscall args*/
adr x1,msg /* message location syscall args*/
mov x28,divisor /* store 10 (divisor) in x28 */
udiv x23,x20,x28 /* divide index (x20) by 10 (x28), store quotient into x23; remainer discarded */
msub x24,x23,x28,x20 /* store remainder (x20 - (x23 * x28)) into x24 */
cmp x23,0 /* check if quotient is 0 (i.e. single digit index) */
b.eq sloop /* if so, branch to single digit loop */
/* tens digit */
add x23,x23,zero /* increase x23 (quotient) by 48 i.e. convert to ascii value */
strb w23,[x1,6] /* copy 1 byte of w23 to message 6 bytes offset */
/* ones digit */
sloop:
add x24,x24,zero /* increase x24 (remainder) by 48 i.e. convert to ascii value */
strb w24,[x1,7] /* copy 1 byte of w24 to message 7 bytes offset */
mov x0,1 /* file descriptor stdout syscall args*/
mov x8,64 /* syscall number is 8; write is 64 */
svc 0 /* perform a syscall */
/* increment & check for exit */
add x20,x20,1 /* increment index */
mov x22,max /* compare x22 and max value */
cmp x20,x22 /* see if we're done */
b.lt loop /* branch to loop if less than */
mov x0,0 /* exit status */
mov x8,93 /* syscall sys_exit */
svc 0
.section .data
msg: .ascii "Loop: \n"
len = . - msg
And that assembly code can be found here: https://github.com/naiuhz/spo600/blob/master/lab3/arm64/loop.s