In the previous post, the code was able to loop and print from 0 to 9 onto the screen with both Aarch64 and x84_64.
In order to print numbers beyond that meaning two digit numbers, modifications to the code needs to be made.
Expected result:
Loop: 00
Loop: 01
Loop: 02
Loop: 03
Loop: 04
...
Loop: 30
etc.
The strategy is to store both the quotient and remainder of the number when it is divided by 10. This allows to also display the number that goes beyond 10 when we display the quotient and remainder side by side onto the screen.
partial code in x84_64
loop:
movq $0, %rdx /* clearing reminder for division */
movq %r15, %rax /* set rax to be divide */
movq $10, %r10 /* set divisor 10 */
div %r10 /* perform division */
movq %rax, %r14 /* store quotient to the register*/
movq %rdx, %r13 /* store remainder to the register*/
add $0x30, %r14 /* converting quotient to ASCII */
add $0x30, %r13 /* converting remainder to ASCII */
mov %r13b, msg+8 /* Extra byte in msg with remainder than quotient */
The code above takes care of performing the division of the number by 10. Stores the quotient and remainder to the register, converting both of them into ASCII code and later to be set to the position of msg.
Complete Source Code in x84_64:
.text
.globl _start
_start:
movq $0, %r15 /* Loop counter */
movq $0x30, %r12 /* value of 0 in Ascii */
loop:
movq $0, %rdx /* clearing reminder for division */
movq %r15, %rax /* set rax to be divide */
movq $10, %r10 /* set divisor 10 */
div %r10 /* perform division */
movq %rax, %r14 /* store quotient to the register*/
movq %rdx, %r13 /* store remainder to the register*/
add $0x30, %r14 /* converting quotient to ascii */
add $0x30, %r13 /* converting remainder to ascii */
mov %r13b, msg+8 /* Modify 1 byte inmsg with remainder */
cmp %r12, %r14
mov %r14b, msg+7 /* Modify 1 byte in msg with quotient */
movq $len, %rdx /* message length */
movq $msg, %rsi /* message location */
movq $1, %rdi /* file descriptor stdout */
movq $1, %rax /* syscall sys_write */
syscall
inc %r15 /* increment counter */
cmp $31, %r15 /* see if we're done */
jne loop /* if not, loop */
movq $0, %rdi /* exit status */
movq $60, %rax /* syscall sys_exit */
syscall
.section .data
msg: .ascii "Loop : \n"
len = . - msg
Complete Source Code in Aarch64:
.text
.globl _start
_start:
mov x19, 0
mov x17, 10
loop:
mov x0, 1 /* file descriptor: 1 is stdout */
adr x1, msg /* message location (memory address) */
mov x2, len /* message length (bytes) */
mov x18, x19
udiv x9, x18, x17
add x13, x9, 0x30
msub x10, x9, x17, x18
add x14, x10, 0x30
adr x15, msg
strb w13, [x15, 7]
strb w14, [x15, 8]
mov x8, 64 /* write is syscall #64 */
svc 0 /* invoke syscall */
add x19, x19, 1
cmp x19, 31
b.ne loop
.data
msg: .ascii "Loop : #\n"
len= . - msg
Conclusion:
Personally the biggest challenge I found in this lab was to figure out how to perform the division and store the values from the division into two registers and placing then into the msg.
Top comments (0)