Assembler Lab

Write at very first beginning

After I finally finish all the tasks, I feel that there is a remarkable thing has been accomplished. It was hard at first, I tried hundreds of times, changed every single of element to figure out what does this syntax means. After I could read those code, the logic is simple. Everything has to be placed in its own place(address). I will choose gas, it seems more straight forward to me.  


Login on x86_64
$ ssh siwen@xerxes.cdot.systems

Download the code examples and unpacking the archive
$ cp /public/spo600-assembler-lab-examples.tgz .
$ tar xvzf spo600-assembler-lab-examples.tgz

hello.c
/* Hello World in traditional C using printf() */

#include <stdio.h>

int main() {
        printf("Hello World!\n");
}


hello2.c
/* Hello World with a direct write to stdout (file descriptor 1) */

#include <unistd.h>

int main() {
        write(1,"Hello World!\n",13);
}


hello3.c
/* Hello World using a direct kernel system call to write to
   file descriptor 1 (stdout) */

#include <unistd.h>
#include <sys/syscall.h>

int main() {
        syscall(__NR_write,1,"Hello World!\n",13);
}


Tasks
1. Build and run the three C versions of the program for x86_64. Take a look at the differences in the code. 
$ cd spo600/examples/hello/c
$ make
gcc     -g -O0 -fno-builtin     -o hello                        hello.c
gcc     -g -O0 -fno-builtin     -o hello-static -static         hello.c
gcc     -O3 -g          -o hello-opt                    hello.c
gcc     -g -O0 -fno-builtin     -o hello2                       hello2.c
gcc     -g -O0 -fno-builtin     -o hello3                       hello3.c

2. Use the objdump -d command to dump (print) the object code (machine code) and disassemble it into assembler for each of the binaries. Find the <main> section and take a look at the code. Notice the total amount of code.
$ objdump -d hello | less
0000000000401126 <main>:
  401126:       55                            push   %rbp
  401127:       48 89 e5                   mov    %rsp,%rbp
  40112a:       bf 10 20 40 00          mov    $0x402010,%edi
  40112f:       b8 00 00 00 00          mov    $0x0,%eax
  401134:       e8 f7 fe ff ff              callq  401030 <printf@plt>
  401139:       b8 00 00 00 00         mov    $0x0,%eax
  40113e:       5d                             pop    %rbp
  40113f:        c3                             retq

$ objdump -d hello2 | less
0000000000401126 <main>:
  401126:       55                                push   %rbp
  401127:       48 89 e5                       mov    %rsp,%rbp
  40112a:       ba 0d 00 00 00              mov    $0xd,%edx
  40112f:       be 10 20 40 00               mov    $0x402010,%esi
  401134:       bf 01 00 00 00               mov    $0x1,%edi
  401139:       e8 f2 fe ff ff                   callq  401030 <write@plt>
  40113e:       b8 00 00 00 00              mov    $0x0,%eax
  401143:       5d                                  pop    %rbp
  401144:       c3                                   retq
  401145:       66 2e 0f 1f 84 00 00       nopw   %cs:0x0(%rax,%rax,1)
  40114c:       00 00 00
  40114f:       90                                    nop

$ objdump -d hello3 | less
0000000000401126 <main>:
  401126:       55                            push   %rbp
  401127:       48 89 e5                   mov    %rsp,%rbp
  40112a:       b9 0d 00 00 00         mov    $0xd,%ecx
  40112f:       ba 10 20 40 00          mov    $0x402010,%edx
  401134:       be 01 00 00 00          mov    $0x1,%esi
  401139:       bf 01 00 00 00          mov    $0x1,%edi
  40113e:       b8 00 00 00 00          mov    $0x0,%eax
  401143:       e8 e8 fe ff ff              callq  401030 <syscall@plt>
  401148:       b8 00 00 00 00          mov    $0x0,%eax
  40114d:       5d                             pop    %rbp
  40114e:       c3                              retq
  40114f:       90                              nop

3. Review, build, and run the x86_64 assembly language programs. Take a look at the code using objdump -d objectfile and compare it to the source code. Notice the absence of other code (compared to the C binary, which had a lot of extra code).
$ cd spo600/examples/hello/assembler/x86_64
$ make
nasm    -g      -o hello-nasm.o -f elf64        hello-nasm.s
ld              -o hello-nasm                   hello-nasm.o
as      -g      -o hello-gas.o          hello-gas.s
ld                      -o hello-gas            hello-gas.o

$ nano hello-gas.s
.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

$ objdump -d hello-gas | less
hello-gas:     file format elf64-x86-64
Disassembly of section .text:
0000000000401000 <_start>:
  401000:       48 c7 c2 0e 00 00 00    mov    $0xe,%rdx
  401007:       48 c7 c6 00 20 40 00    mov    $0x402000,%rsi
  40100e:       48 c7 c7 01 00 00 00    mov    $0x1,%rdi
  401015:       48 c7 c0 01 00 00 00    mov    $0x1,%rax
  40101c:       0f 05                   syscall
  40101e:       48 c7 c7 00 00 00 00    mov    $0x0,%rdi
  401025:       48 c7 c0 3c 00 00 00    mov    $0x3c,%rax
  40102c:       0f 05                   syscall

4. Build and run the three C versions of the program for aarch64. Verify that you can disassemble the object code in the ELF binary using objdump -d objectfile and take a look at the code.
Login on ARMv8
$ ssh siwen@aarchie.cdot.systems

Download the code examples and unpacking the archive
$ cp /public/spo600-assembler-lab-examples.tgz .
$ tar xvzf spo600-assembler-lab-examples.tgz 

$ cd spo600/examples/hello/c 
$make
gcc     -g -O0 -fno-builtin     -o hello                        hello.c
gcc     -g -O0 -fno-builtin     -o hello-static -static         hello.c
gcc     -O3 -g          -o hello-opt                    hello.c
gcc     -g -O0 -fno-builtin     -o hello2                       hello2.c
gcc     -g -O0 -fno-builtin     -o hello3                       hello3.c
 


$ objdump -d hello | less
0000000000400594 <main>:
  400594:       a9bf7bfd        stp     x29, x30, [sp, #-16]!
  400598:       910003fd        mov     x29, sp
  40059c:       90000000        adrp    x0, 400000 <_init-0x418>
  4005a0:       9119c000        add     x0, x0, #0x670
  4005a4:       97ffffb7        bl      400480 <printf@plt>
  4005a8:       52800000        mov     w0, #0x0                        // #0
  4005ac:       a8c17bfd        ldp     x29, x30, [sp], #16
  4005b0:       d65f03c0        ret
  4005b4:       00000000        .inst   0x00000000 ; undefined
 

$objdump -d hello2 | less
0000000000400594 <main>:
  400594:       a9bf7bfd        stp     x29, x30, [sp, #-16]!
  400598:       910003fd        mov     x29, sp
  40059c:       d28001a2        mov     x2, #0xd                        // #13
  4005a0:       90000000        adrp    x0, 400000 <_init-0x418>
  4005a4:       9119e001        add     x1, x0, #0x678
  4005a8:       52800020        mov     w0, #0x1                        // #1
  4005ac:       97ffffb1        bl      400470 <write@plt>
  4005b0:       52800000        mov     w0, #0x0                        // #0
  4005b4:       a8c17bfd        ldp     x29, x30, [sp], #16
  4005b8:       d65f03c0        ret
  4005bc:       00000000        .inst   0x00000000 ; undefined
 

$ objdump -d hello3 | less
0000000000400594 <main>:
  400594:       a9bf7bfd        stp     x29, x30, [sp, #-16]!
  400598:       910003fd        mov     x29, sp
  40059c:       528001a3        mov     w3, #0xd                        // #13
  4005a0:       90000000        adrp    x0, 400000 <_init-0x418>
  4005a4:       9119e002        add     x2, x0, #0x678
  4005a8:       52800021        mov     w1, #0x1                        // #1
  4005ac:       d2800800        mov     x0, #0x40                       // #64
  4005b0:       97ffffb4        bl      400480 <syscall@plt>
  4005b4:       52800000        mov     w0, #0x0                        // #0
  4005b8:       a8c17bfd        ldp     x29, x30, [sp], #16
  4005bc:       d65f03c0        ret
 

5. Review, build, and run the aarch64 assembly language programs. Take a look at the code using objdump -d objectfile and compare it to the source code. 
 $ cd spo600/examples/hello/assembler/aarch64
$ make 
as      -g      -o hello.o      hello.s
ld              -o hello        hello.o


$ nano hello.s
.text
.globl _start
_start:

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

        mov     x0, 0           /* status -> 0 */
        mov     x8, 93          /* exit is syscall #93 */
        svc     0               /* invoke syscall */

.data
msg:    .ascii      "Hello, world!\n"
len=    . - msg
 
$ objdump -d hello | less
00000000004000b0 <_start>:
  4000b0:       d2800020        mov     x0, #0x1                        // #1
  4000b4:       100800e1        adr     x1, 4100d0 <msg>
  4000b8:       d28001c2        mov     x2, #0xe                        // #14
  4000bc:       d2800808        mov     x8, #0x40                       // #64
  4000c0:       d4000001        svc     #0x0
  4000c4:       d2800000        mov     x0, #0x0                        // #0
  4000c8:       d2800ba8        mov     x8, #0x5d                       // #93
  4000cc:       d4000001        svc     #0x0
 

6. Here is a basic loop in x86_64 assembler - this loops from 0 to 9, using r15 as the index (loop control) counter:

.text
.globl  _start

start = 0
max = 10

_start:
        mov     $start,%r15

loop:
        mov     $len,%rdx
        mov     $msg,%rsi
        mov     $1,%rdi
        mov     $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 .rodata

msg:    .ascii      "Loop\n"
        len = . - msg


 
Then modify the message so that it includes the loop index values, showing each digit from 0 to 9 like this:

.text
.globl  _start

start = 0
max = 10

_start:
        mov     $start,%r15

loop:
        mov     $0x30,%r14
        add     %r15,%r14
        movb    %r14b,msg+6
        mov     $len,%rdx
        mov     $msg,%rsi
        mov     $1,%rdi
        mov     $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
 

 
 

7. Repeat step 6 for aarch64.


.text
.globl _start

start = 0
max = 10

_start:
        mov     x10,start

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     x10,x10,1
        cmp     x10,max
        b.lt    loop

        mov     x0, 0           /* status -> 0 */
        mov     x8, 93          /* exit is syscall #93 */
        svc     0               /* invoke syscall */

.data
msg:    .ascii      "Loop\n"
len=    . - msg
 
 
 
 
 


.text
.globl _start

start = 0
max = 10

_start:
        mov     x10,start

loop:
        mov     x0, 1           /* file descriptor: 1 is stdout */
        adr     x1, msg         /* message location (memory address) */
        mov     x2, len         /* message length (bytes) */

        add     x11,x10,48
     adr     x12,msg+6 
     strb    w11,[x12]

        mov     x8, 64          /* write is syscall #64 */
        svc     0               /* invoke syscall */

        add     x10,x10,1
        cmp     x10,max
        b.lt    loop

        mov     x0, 0           /* status -> 0 */
        mov     x8, 93          /* exit is syscall #93 */
        svc     0               /* invoke syscall */

.data
msg:    .ascii      "Loop:   \n"
len=    . - msg
 



8. Extend the code to loop from 00-30, printing each value as a 2-digit decimal number.
.text
.globl  _start

start = 0
max = 31

_start:
        mov     $start,%r15

loop:
        mov     $0x30,%r13
        mov     $0x30,%r14
        mov     $0,%rdx
        mov     %r15,%rax
        mov     $10,%r12
        div     %r12
        add     %rax,%r13
        add     %rdx,%r14
        movb    %r13b,msg+6
        movb    %r14b,msg+7
        mov     $len,%rdx
        mov     $msg,%rsi
        mov     $1,%rdi
        mov     $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\n"
        len = . - msg
 
  
9. Repeat step 8 for aarch64. 

.text
.globl _start

start = 0
max = 31

_start:
        mov     x10,start
        mov     x9,10
loop:
        mov     x0, 1           /* file descriptor: 1 is stdout */
        adr     x1, msg         /* message location (memory address) */
        mov     x2, len         /* message length (bytes) */

        udiv    x11,x10,x9
        msub    x12,x9,x11,x10
        add     x11,x11,48
        add     x12,x12,48
        adr     x13,msg+6
        adr     x14,msg+7
        strb    w11,[x13]
        strb    w12,[x14]

        mov     x8, 64          /* write is syscall #64 */
        svc     0               /* invoke syscall */

        add     x10,x10,1
        cmp     x10,max
        b.lt    loop

        mov     x0, 0           /* status -> 0 */
        mov     x8, 93          /* exit is syscall #93 */
        svc     0               /* invoke syscall */

.data
msg:    .ascii      "Loop:   \n"
len=    . - msg
 
 
 
Extend the assembler programs (both x86_64 and aarch64) to suppress the high digit when it is 0. 
.text
.globl _start

start = 0
max = 31

_start:
        mov     x10,start
        mov     x9,10
loop:
        mov     x0, 1           /* file descriptor: 1 is stdout */
        adr     x1, msg         /* message location (memory address) */
        mov     x2, len         /* message length (bytes) */

        udiv    x11,x10,x9
        msub    x12,x9,x11,x10

        cmp     x11,0
        b.eq    ones
        add     x11,x11,48
        adr     x13,msg+6
        strb    w11,[x13]
ones:
        add     x12,x12,48
        adr     x14,msg+7
        strb    w12,[x14]

        mov     x8, 64          /* write is syscall #64 */
        svc     0               /* invoke syscall */

        add     x10,x10,1
        cmp     x10,max
        b.lt    loop

        mov     x0, 0           /* status -> 0 */
        mov     x8, 93          /* exit is syscall #93 */
        svc     0               /* invoke syscall */

.data
msg:    .ascii      "Loop:   \n"
len=    . - msg
 
 
 
.text
.globl  _start

start = 0
max = 31

_start:
        mov     $start,%r15

loop:
        mov     $0x30,%r13
        mov     $0x30,%r14
        mov     $0,%rdx
        mov     %r15,%rax
        mov     $10,%r12
        div     %r12
        add     %rax,%r13
        add     %rdx,%r14

        cmp     $0x30,%r13
        je      ones
        movb    %r13b,msg+6

ones:
        movb    %r14b,msg+7
        mov     $len,%rdx
        mov     $msg,%rsi
        mov     $1,%rdi
        mov     $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\n"
        len = . - msg
 


Comments

Popular posts from this blog

Project - Stage 2.3 - After Optimize

Project - Stage 1.0 - Project Optimize Plan