SPO 600 - Lab 3
In Lab 3, I'll be looking at Assembler and Assembly Language. For this lab, I will write a program that prints a message and its loop count for each iteration - in Assembly Language.
Here's the expected output:
Loop: 0
Loop: 1
Loop: 2
Loop: 3
Loop: 4
Loop: 5
Loop: 6
Loop: 7
Loop: 8
Loop: 9
Looks quite simple, isn't it? Well, in C that would get the job done:
But in Assembly Language, it is much more complicated. In fact, you actually have to manually convert the number into ASCII, concatenate it into the string, and then print it out:
The next part of this lab can be quite tricky, if not confusing - I have to print 0 to 30 (with leading zeros), like this:
Loop: 00
Loop: 01
Loop: 02
Loop: 03
Loop: 04
Loop: 05
...
Loop: 29
Loop: 30
Once again, a simple job in high-level programming languages like C, but not in Assembly Language. To print a double-digit number in Assembly, I will have to do some math first - more specifically, division. In x86_64 assembly, idiv takes one operand, but it uses the value stored in rax as dividend. The quotient and remainder is stored in rax and rdx, respectively.
After doing all that math, all I have to do is to concatenate the 2 digits I extracted into the string.
Next, I have to write the same program for the aarch64 architecture. The logic is pretty much the same, but in aarch64 architecture I have to use msub instead.
msub takes four operands and does a multiply and subtract operation. This is useful for calculating the remainder of an integer division, for example:
means "load r0 with r3-(r1*r2)".
Regarding x86_64 and aarch64 assembler, I personally doesn't found too much differences between them, only in aarch64, I don't have to put a percentage and dollar sign before the registers and Immediate values, respectively like x86_64 did - which makes my life a bit easier.
On the other hand, instructions in x86_64 are read from left to right, while in aarch64 some instructions are read from left to right (e.g. ldr, str and strb), some instructions are read from right to left (e.g. add, mov and cmp). Since I have been reading things from left to right throughout my entire life, instructions in aarch64 can be quite difficult to read. (I know, Classical Chinese are read from right to left, but by the time I am learning Chinese, it is already read from left to right.)
In general, I am fine with writing programs on either architecture.
If anyone is interested in the source code of programs I wrote, you can find it at here:
https://github.com/wu-geoff/SPO600/blob/master/xerxes/lab3/step8/lab3.s
https://github.com/wu-geoff/SPO600/blob/master/aarchie/lab3/step9/hello.s
Here's the expected output:
Loop: 0
Loop: 1
Loop: 2
Loop: 3
Loop: 4
Loop: 5
Loop: 6
Loop: 7
Loop: 8
Loop: 9
Looks quite simple, isn't it? Well, in C that would get the job done:
#include <stdio.h> int main(){ for(int i = 0; i < 10; i++){ printf("Loop: %d\n", i); } return 0; }
But in Assembly Language, it is much more complicated. In fact, you actually have to manually convert the number into ASCII, concatenate it into the string, and then print it out:
.text .globl _start start = 0 max = 10 _start: mov $start,%r15 loop: mov %r15,%r14 add $48,%r14 mov %r14b,msg+6 movq $len,%rdx movq $msg,%rsi mov $1,%rdi mov $1,%rax syscall inc %r15 cmp $max,%r15 jne loop mov $0,%rdi mov $60,%rax syscall .section .data msg: .ascii "Loop: \n" .set len , . - msg
The next part of this lab can be quite tricky, if not confusing - I have to print 0 to 30 (with leading zeros), like this:
Loop: 00
Loop: 01
Loop: 02
Loop: 03
Loop: 04
Loop: 05
...
Loop: 29
Loop: 30
Once again, a simple job in high-level programming languages like C, but not in Assembly Language. To print a double-digit number in Assembly, I will have to do some math first - more specifically, division. In x86_64 assembly, idiv takes one operand, but it uses the value stored in rax as dividend. The quotient and remainder is stored in rax and rdx, respectively.
After doing all that math, all I have to do is to concatenate the 2 digits I extracted into the string.
Next, I have to write the same program for the aarch64 architecture. The logic is pretty much the same, but in aarch64 architecture I have to use msub instead.
msub takes four operands and does a multiply and subtract operation. This is useful for calculating the remainder of an integer division, for example:
msub r0,r1,r2,r3
means "load r0 with r3-(r1*r2)".
Conclusion
Overall my experience with assembler is positive. Although it is so low-level I can't even print a number out without converting it ASCII by myself, I do found programming in Assembly Language very amusing. On a side note, after writing programs in Assembly Language, I finally understand why C was a high-level programming language in the 1980s.Regarding x86_64 and aarch64 assembler, I personally doesn't found too much differences between them, only in aarch64, I don't have to put a percentage and dollar sign before the registers and Immediate values, respectively like x86_64 did - which makes my life a bit easier.
On the other hand, instructions in x86_64 are read from left to right, while in aarch64 some instructions are read from left to right (e.g. ldr, str and strb), some instructions are read from right to left (e.g. add, mov and cmp). Since I have been reading things from left to right throughout my entire life, instructions in aarch64 can be quite difficult to read. (I know, Classical Chinese are read from right to left, but by the time I am learning Chinese, it is already read from left to right.)
In general, I am fine with writing programs on either architecture.
If anyone is interested in the source code of programs I wrote, you can find it at here:
https://github.com/wu-geoff/SPO600/blob/master/xerxes/lab3/step8/lab3.s
https://github.com/wu-geoff/SPO600/blob/master/aarchie/lab3/step9/hello.s
Comments
Post a Comment