top of page

LAB4 ASSEMBLY LANGUAGE PROGRAM AARCH64

Moving to the Aarch64 architecture I found difficulties with adapting to the assemlby language at first.


Everything is reversed whereas on the x86 comp if we wanted to move the register we would use this command and please note the other differences as well here.


x86


mov %rax,%r15 // We are moving the value of %rax into -> %r15


Aarch64


mov x0,x15 // We are moving the value of x15 into -> x0


------------------------------

OTHER NOTES

-----------------------------

Note how on x86 we were going right to left while on ARM ( Aarch64 ) we went from right to left. It is also worth noting that while on the x86 gas assembly language we used % to identify a register while on the ARM we exclude this symbol.


On the ARM architecture a register can have 3 different preceding characters r,x,w whereas r is ambiguos, x is 64 bits and w is 32 bits.


-----------------------------

WRITING TO MEMORY

-----------------------------

Also on the ARM architecture which i discovered is that you cannot write to memory from an address, you need to move that memory first into a register using the adr command, make your changes then move it back once again versus the x86 where we could directly modify a piece of memory


If we have a piece of text in memory and want to add to it, it is not as simple as the x86 way of just calling a mov %register,msg+5 we must first move that memory into a register in ARM architecture


In order for us to write to memory we first need to use the adr command and move the block of memory into a register


adr x15,[msg+6] // msg is our block of memory and the +6 is location within that memory address


Next we need to store a value we wish to save into another register and add 48 to it so that it can be interpreted as text


mov x14,15

add x14,x14,48


Finally we need to store the value into the register that holds the memory location


strb w14,[x15] Note we are using w14 because we only want to store a single byte, if we used x14 we would override the register with too much data and get an error.


Because x15 has the memory location of msg stored in it, we do not need to do anything else. x15 is a pointer to msg now, and whatever we do to x15 we do to msg.


----------------------

PRINTING NUMBER 0-30 IN A LOOP

----------------------


Using the div command was a bit differnt on the Aarch64 compared to the X86 because the ARM architecture does not hold the remainder in a register like in x86. So in order for us to get the remainder we needed to use a separate command to extract it from the quotient as seen below.


udiv x0,x1,x2 // x0 is where the output of x1 the divident ( divided ) by x2 the diviser will be stored

msub x4,x0,x2,x1 // x4 will be where our remainder is stored. Basically x0 is the quotient from above and we subtract that from x2 * x1


Now we have our remainder and quotient we can print them both out 01,02,03...29,30


----------------------

SURPRESSING LEADING 0's

----------------------


This part was very similar to the x86 version of our program, basically we do a compare and a jump if statement

cmp x0,0 // x0 is the register that holds our quotient and we compare it to 0

b.eq $label // If the above compare is true that x0 == 0 we will branch to our label which will skip over any leading 0 characters


----------------------

FULL CODE

----------------------

.text

.globl _start


start = 0 // Global variables

max = 30


_start:

mov x19,start


loop:

mov x12,10 // These 3 lines find the quotient and the remainder

udiv x13,x19,x12

msub x14,x13,x12,x19


cmp x13,0 // Skip leading zero characters

b.eq print


adr x15,msg + 5 // Append the quotient to our string if it is not zero

add x13,x13,48

strb w13,[x15]


print:

adr x11,msg+6 // Append the remainder to our string

add x14,x14,48

strb w14,[x11]


// Print our 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 */


add x19,x19,1 // Loop if x19 is less than 30

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


4 views0 comments

Recent Posts

See All

Closing Thoughts

For my final blog post I would like to discuss what I have learned and plan to utilize in the future from this course. So although I was not able to successfully improve my package to operate function

Stage 3 Optimization(COMPUTER ARCHITECTURE ENDIANESS)

Seeing as how the compiler flags did not provide any optimization I will on to my next attempt which is converting big endian to small endian. The aarch64 architecture uses the little endian byte orde

Stage 3 Optimization(Compiler Flags)

My first attempt to optimize the project will be to work with the compiler flag options. By default the compiler is set to compile in this manner "gcc -E -g -o2" The -E option represents preprocesses

bottom of page