Lab 5 – X86_64

In the last blog, we finished the program that prints “Hello World” 30 times on Aarch64 machine, now we are going to code the same program on X86_64 machine using assembly language.

Step 1: start with a basic hello world program

.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 .data
msg:    .ascii      "Hello, world!: 0\n"
        len = . - msg

Step 2: loop 30 times output

.text
.globl	_start

_start:
	movb 	$'0', %r12b
	movq	$min, %r10

loop:

	movq	%r10, %r9
	movq	$len,%rdx			/* message length */
	movq 	$msg,%rsi			/* message location */
	
	movq 	$msg+15, %r11
	movb 	%r12b, (%r11)
	
	movq	$1,%rdi				/* file descriptor stdout */
	movq	$1,%rax				/* syscall sys_write */
	syscall
	
	inc		%r12b
	
	inc		%r10
	cmp		$max, %r10
	jne		loop

	movq	$0,%rdi				/* exit status */
	movq	$60,%rax			/* syscall sys_exit */
	syscall


.section .data
msg:	.ascii      "Hello, world!: 0\n"
	len = . - msg
min = 0
max = 30
division = 10 

Step 3: deal with the second digit output

Now the already looped the output 30 times, but the we have not dealt with second digit output, so the output is :

On X86_64 machine, getting reminder is a little different:

        movq    $0, %rdx         /*initialize rdx to 0 for division*/
        movq    %r10, %rax     /*store the r10 value into rax for division*/
        div     %r9              /*divide rax value by 10(r9)*/

        movq    %rax, %r14    /*store the rax value(quotient) into r14*/
        movq    %rdx, %r15    /*store the rdx value(remainder) int r15*/

After dividing, the quotient and remainder will be stored into rax and rdx.

Lab 5 on X86_64

.text
.globl  _start

_start:
        movq    $min, %r10      /*store the min vlaue into r10 as a loop index*/
        movq    $division, %r9   /*store the division value(10) into r9*/

loop:
        cmp     %r9, %r10      /*compare r10(loop index) with 10*/
        jl      digit_1          /*if r10 is less than 10, go to the subroutine digit_1*/
        jmp     digit_2          /*if r10 is greater or equal to 10, go to the subroutine digit_2*/


digit_1:
        movq    %r10, %r15      /*store the r10 value into r15*/
        add     $'0', %r15       /*add '0' to r15 so the value will be ascii number character value*/

        movq    $msg+15, %r11   /*the digit location within string*/
        movb    %r15b, (%r11)   /*store the digit at the location*/

        jmp     print           /*go to the subroutine print*/

digit_2:
        movq    $0, %rdx         /*initialize rdx to 0 for division*/
        movq    %r10, %rax     /*store the r10 value into rax for division*/
        div     %r9              /*divide rax value by 10(r9)*/

        movq    %rax, %r14    /*store the rax value(quotient) into r14*/
        movq    %rdx, %r15    /*store the rdx value(remainder) int r15*/

        add     $'0', %r14       /*add '0' to r14 so the value will be ascii number character value*/
        add     $'0', %r15       /*add '0' to r15 so the value will be ascii number character value*/

        movq    $msg+14, %r11   /*the digit location within string*/
        movb    %r14b, (%r11)   /*store the digit at the location*/

        movq    $msg+15, %r12   /*the digit loctaion within string*/
        movb    %r15b, (%r12)   /*store the digit at the location*/

        jmp     print   /*go to the subroutine print*/


print:
        movq    $len,%rdx                       /* message length */
        movq    $msg,%rsi                       /* message location */


        movq    $1,%rdi                         /* file descriptor stdout */
        movq    $1,%rax                         /* syscall sys_write */
        syscall
        inc             %r12b

        inc             %r10      /*increment loop index*/
        cmp             $max, %r10  /*compare the max with r10*/
        jne             loop      /*if the max value and the r10(loop index) value is not equal,*/
                                  /*   redo the loop subroutine*/

        movq    $0,%rdi                         /* exit status */
        movq    $60,%rax                        /* syscall sys_exit */
        syscall


.section .data
msg:    .ascii      "Hello, world!:   \n"
        len = . - msg
min = 0
max = 30
division = 10

In X86 part, I encountered many seg faults. To deal with that, I tried to use gdb to deal with that. But unfortunately, the gdb barely gives me useful information.

I will write another blog to describe how to use gdb to debug assembly code.

Leave a comment

Design a site like this with WordPress.com
Get started