This blog will be about the Assembler language designed for two systems. (arm aarch64 and the x86_64 systems)
I will be using the objdump program in Linux for analyzing the assembly language in a compiled C language program.
Command: objdump -d program_1
First, I will be analyzing an assembly language code for “Hello World!” written by CTyler of Seneca College.
/*
This is a 'hello world' program in x86_64 assembler using the
GNU assembler (gas) syntax. Note that this program runs in 64-bit
mode.
CTyler, Seneca College, 2014-01-20
Licensed under GNU GPL v2+
*/
.text
.globl _start
_start:
movq $len,%rdx /* message length */
movq $msg,%rsi /* message location */
movq $1,%rdi /* file descriptor stdout */
movq $1,%rax /* syscall sys_write */
syscall
movq $0,%rdi /* exit status */
movq $60,%rax /* syscall sys_exit */
syscall
.section .rodata
msg: .ascii "Hello, world!\n"
len = . - msg
Note: The assembly language source code has the declaration of variables at the end of the script (msg and len).
The program first loads the variable len into register x and loads the variable msg into the register i.
Note: Variable len is for removing the spacing when converting from assembly language code to ASCII(American Standard Code for Information Interchange). This is similar to human languages where one language is not understood by another language and require a translator.
The program then returns control of the system to the user using the syscall command.
Here is a basic program written in assembly language for the x86_64 system provided by CTyler of Seneca College (https://wiki.cdot.senecacollege.ca/wiki/SPO600_Assembler_Lab):
.text
.globl _start
start = 0 /* starting value for the loop index; note that this is a symbol (constant), not a variable */
max = 10 /* loop exits when the index hits this number (loop condition is i<max) */
_start:
mov $start,%r15 /* loop index */
loop:
/* ... body of the loop ... do something useful here ... */
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
This program will require a custom file called a “Makefile”
Note: This “Makefile” can be used for both x86_64 and arm aarch64 systems
Code:
BINARIES=hello-world
all: ${BINARIES}
AS_ARGS=-g
hello-world: hello-world.s
world -g -o hello-world.o -f elf64 hello-world.s
ld -o hello-world hello-world.o
clean:
rm ${BINARIES} *.o || true
Command: make hello-world
Note: All this program does is loop and do nothing.
The basic code and the hello world code will have to be combined together to make the program do something.
Task: Make it have an output like:
Loop:
Loop:
Loop:
Loop:
Loop:
Loop:
Loop:
Loop:
Loop:
Loop:
Code(x86_64):
.text .globl _start start = 0 max = 10 _start: movq $len,%rdx movq $msg,%rsi movq $start,%r15 #load %r15 with 0 loop: movq $1,%rdi movq $1,%rax syscall #Send output to host inc %r15 #Increment the value of %r15 cmp $max,%r15 #Compares %r15 with the value at $max jne loop #jump to loop if not equal to $max mov $0,%rdi mov $60,%rax syscall .section .data msg: .ascii "Loop: \n" len = . - msg
Now to make it more complex with it count with numbers up to a maximum
Task: Make it have an output like:
Loop: 01 Loop: 02 Loop: 03 Loop: 04 Loop: 05 Loop: 06 Loop: 07 Loop: 08 Loop: 09 Loop: 10 Loop: 11 Loop: 12 Loop: 13 Loop: 14 Loop: 15 Loop: 16 Loop: 17 Loop: 18 Loop: 19 Loop: 20 Loop: 21 Loop: 22 Loop: 23 Loop: 24 Loop: 25 Loop: 26 Loop: 27 Loop: 28 Loop: 29 Loop: 30
Code(x86_64):
.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) */ cvt = 48 d = 10 _start: mov $start,%r15 /* loop index */ loop: /* ... body of the loop ... do something useful here ... */ /* rdx must be zero before div */ movq $msg,%rsi movq $d,%r10 movq %r15,%rax /*putting increment into rax because div divides by rax*/ xor %rdx, %rdx /* makes rdx 0*/ div %r10 /*rax div 10 (increment/10) */ movq %rax,%r9 /*store quotient to r9 */ add $cvt,%r9 movq %rdx,%r8 /* storing remainder, needed to display 2nd digit */ add $cvt,%r8 movq $len,%rdx movb %r9b, msg+6 #Shift the 1st digit right 6 positions movb %r8b, msg+7 #Shift the 2nd digit right 7 positions movq $1,%rdi movq $1,%rax syscall 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 .section .data msg: .ascii "Loop: \n" len = . - msg
Code(arm aarch64):
.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) */ ten = 10 _start: mov x19, start #Moves r19 with start mov x22, ten #Moves r22 with ten loop: #The start of the loop adr x1, msg #Loads r1 with msg mov x2, len #Moves value of len into r2 mov x0, 1 #Moves value of 1 into r0 mov x8, 64 #Moves value of 64 into r8 svc 0 #Invokes syscall adr x23, msg #Loads r23 with msg add x19, x19, 1 #Adds the value in r19 with 1 and stores it in r19 udiv x20, x19, x22 #Unsigned divide using value in r20 and r19 then store quotient/reminder in r19 msub x21, x22, x20, x19 #For calculating reminder #Multiply r22 with r20 then subtracts r19 with the result and stores it in r21 #Mathematically: r21=r19-(r22*r20) cmp x20, 0 #Compare value in r20 if it is 0 beq skip #If it is equal to 0 then jump to skip loop add x20, x20, '0' #Adds the value in r20 with 0 and stores it in r20 strb w20, [x23,6] #Writes a byte string into r20 from r23 with 6 bytes #(Note:w20 instead of x20 for writing into registry) skip: add x21, x21, '0' #Adds r21 with 0 and store into r21 strb w21, [x23,7] #Writes a byte into r21 from r23 with 7 bytes cmp x19, max #Compares r19 if it is the value of max bne loop #Jump to loop if it is not the value of max mov x0, 0 #Moves the value of 0 into r0 mov x8, 93 #Moves value of 93 into r8 svc 0 #Invoke syscall .data msg: .ascii "Loop: 0\n" #Display of Loop in ASCII to host len = . - msg #Get positional parameter to host
Comment: This is way too complicated to figure out the ASCII, the loop logic, and the mathematics using registries for either x86_64 or arm aarch64. Also the formatting of WordPress is bad, cannot insert a tab(5 spaces) right away.