- Get link
- X
- Other Apps
This blog post is for my SPO600 class I am participating at Seneca College, this is related to Lab 4 detailed here.
In this lab we are tasked with modifying some simple loop programs, one made with AArch64 assembly language and another made with x86_64 assembly language.
The programs are as follows:
AArch64 version:
.text
.globl _start
min = 0
max = 30
_start:
mov x19, min
loop:
add x19, x19, 1
cmp x19, max
b.ne loop
mov x0, 0 /* status -> 0 */
mov x8, 93 /* exit is syscall #93 */
svc 0 /* invoke syscall */
x86_64 GNU Assembler syntax version:
.text
.globl _start
min = 0
max = 10
_start:
mov $min,%r15 /* loop index */
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
The first goal for the modification of these programs is simple, to begin, we are to make the loop do something! As is it stands now, these loops do nothing, and we must add logic to print a word each time the loop completes.
Loop v1
So where do I start? Conveniently on the AArch64 and x86_64 systems we are working with, there are provided "Hello World" example programs! Inside each of these programs are examples of setting up a string and executing a system call to print the string to the screen. That's helpful! Once I investigated this code it was simple to use for my modification in the loop.
AArch64 Loop v1
.text
.globl _start
min = 0
max = 10
_start:
mov x19, min
loop:
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 */
add x19, x19, 1
cmp x19, max
b.ne loop
mov x0, 0 /* status -> 0 */
mov x8, 93 /* exit is syscall #93 */
svc 0 /* invoke syscall */
.data
msg: .ascii "Loop\n"
len= . - msg
To quickly explain what's going on here, beginning with the ".data" section there is a label "msg" pointing to the first byte of my string "Loop\n". There is also a label "len" being set to the value of the expression calculating the length of the string pointed to by "msg". Using each of these values, they are loaded into the registers responsible for arguments inside the body of the example loop.There are three arguments added into registers x0-x2 to prepare for a "write" system call.
Arg#1 into register x0, the file descriptor for stdout.
Arg#2 into register x1, the address of the beginning of the string to be printed.
Arg#3 into register x2, the length of the message in bytes.
Once that is complete all that's left to do is call "write" by setting register x8 to the integer value 64 and executing. This is done inside the body of the example loop, so this is done a total of 10 times for this example.
x86_64 Loop v1
The procedure for the x86_64 version of these modifications are identical, however the syntax and some of the values differ slightly. For example, the value for the "write" syscall in x86_64 is 1 instead of 64. Here is what the finished product looks like:
.text
.globl _start
min = 0
max = 10
_start:
mov $min,%r12
loop:
movq $len,%rdx /* message length */
movq $msg,%rsi /* message location */
movq $1,%rdi /* file descriptor stdout */
movq $1,%rax /* syscall sys_write */
syscall
inc %r12
cmp $max,%r12
jne loop
movq $0,%rdi /* exit status */
movq $60,%rax /* syscall sys_exit */
syscall
.section .data
msg: .ascii "Loop\n"
len = . - msg
With the first objective complete, I have a fully functional "Loop v1" printing out a string ten times.
Loop v2
With v1 wrapped up we are provided another task, add the loop index to the output of the string. This is accomplished with some brief modifications to Loop v1. This will be explained once again in relation to the AArch64 version, and then the solution for the x86_64 version will be provided as well.
AArch64 Loop v2
.text
.globl _start
min = 0
max = 10
_start:
mov x19, min
loop:
// Prepare message
add x20, x19, 48 /* add index to ascii '0' */
adr x21, msg+6 /* store address of placeholder byte */
strb w20, [x21] /* overwrite placeholder byte */
// Print
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
mov x0, 0 /* status -> 0 */
mov x8, 93 /* exit is syscall #93 */
svc 0 /* invoke syscall */
.data
msg: .ascii "Loop: #\n"
len= . - msg
First is modifying the string to have a placeholder for the loop index digit, the string becomes "Loop: #\n", the # being the placeholder. An important detail is that the placeholder is the 6th byte of the string. Next is converting the integer value of our current index to the accompanying ascii character. The "add" instruction is used for this purpose, adding the current index as an offset to the acsii value for the character '0'. Since the digits on the ascii table are all in order, adding the current index will simply give us the corresponding character for the current index. For example, the character '0' is represented by the integer value 48, adding a loop index of 1 will produce 49, the integer value representing the character '1'. After this addition is complete and stored in register x20, a pointer to the 6th byte in the string is created in register x21. Finally, the converted character value in x20 is stored into register x21, effectively overwriting the placeholder character in the 6th byte of the string. The loop can continue like normal and print the string to the screen.
x86_64 Loop v2
.text
.globl _start
min = 0
max = 10
_start:
mov $min,%r12
loop:
mov %r12,%r13 /* preserve the index value */
add $'0',%r13 /* add the value of ascii '0' */
movb %r13b,msg+6 /* overwrite placeholder */
movq $len,%rdx /* message length */
movq $msg,%rsi /* message location */
movq $1,%rdi /* file descriptor stdout */
movq $1,%rax /* syscall sys_write */
syscall
inc %r12
cmp $max,%r12
jne loop
movq $0,%rdi /* exit status */
movq $60,%rax /* syscall sys_exit */
syscall
.section .data
msg: .ascii "Loop: #\n"
len = . - msg
For this x86_64 version of Loop v2 the sequence of events are slightly different based on how the instructions function compared to their AArch64 counterparts. In this version the add instruction only takes two arguments, storing the result in the 2nd. To account for this, the current index is first stored in r13 and the value of ascii '0' is added to that. The instruction to replace the placeholder character "movb" accepts the label "msg" plus the offset of 6. This I can skip setting up a pointer to the placeholder memory location, and instead place the character directly into msg+6.
To Be Continued...
The toughest part of this lab has yet to come, there will be Loop v3 and finally Loop v4 extending the loops to 30 iterations and modifying the output yet again. These modifications I will cover in a part 2 post since this post feels cluttered enough running through Loop v1 and v2.
- Get link
- X
- Other Apps
Comments
Post a Comment