Lab 5 64-Bit Assembly Language

 

Lab 5 - 64-Bit Assembly Language

Introduction


In this post, I’ll go through my experiments with x86_64 assembly language. I’ll walk through each code example, explain what it does in simple terms, and show what kind of output you should expect. It’s all about understanding how loops work at the assembly level and figuring out how to output messages using system calls.

Let’s dive in and break things down step by step!


Basic Loop in Assembly

Let’s start with a simple loop. This loop doesn’t do anything yet — it just counts from 0 to 4:

.text

 .globl    _start

min = 0

max = 5


_start:

    mov     $min, %r15    # Start loop index at 0


loop:

    # (Nothing here yet)

    inc     %r15          # Increment index

    cmp     $max, %r15    # Compare index to max (5)

    jne     loop          # If not equal, keep looping


    # Exit

    mov     $0, %rdi

    mov     $60, %rax

    syscall

Print "Loop" Each Time

We modify the loop to print the word "Loop" every time it runs:

.text

 .globl    _start

min = 0

max = 5


_start:

    mov     $min, %r15


loop:

    mov     $len, %rdx    # Length of the message

    mov     $msg, %rsi    # Message location

    mov     $1, %rdi      # STDOUT

    mov     $1, %rax      # sys_write

    syscall


    inc     %r15

    cmp     $max, %r15

    jne     loop


    mov     $0, %rdi

    mov     $60, %rax

    syscall


.section .data

msg:    .ascii  "Loop\n"

len =   . - msg

Output:

Loop

Loop

Loop

Loop

Loop

Print "Loop" with Number

Here we print Loop: 0, Loop: 1, etc.

.text

 .globl    _start

min = 0

max = 6


_start:

    mov     $min, %r15


loop:

    # Print "Loop: "

    mov     $len, %rdx

    mov     $msg, %rsi

    mov     $1, %rdi

    mov     $1, %rax

    syscall


    # Print number (single digit)

    lea     buffer(%rip), %r9

    mov     %r15, %r8

    add     $48, %r8            # Convert to ASCII

    movb    %r8b, (%r9)

    add     $1, %r9

    movb    $10, (%r9)          # Newline


    mov     $2, %rdx

    mov     $buffer, %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: "

len =   . - msg

buffer: .space 2

Output:

Loop: 0

Loop: 1

Loop: 2

Loop: 3

Loop: 4

Loop: 5

Show 2 Digits (00–32)

This one prints numbers in two digits like 00, 01, ..., 32:

.text

 .globl    _start

min = 0

max = 33


_start:

    mov     $min, %r15


loop:

    mov     $len, %rdx

    mov     $msg, %rsi

    mov     $1, %rdi

    mov     $1, %rax

    syscall


    lea     buffer(%rip), %r9

    mov     %r15, %rax

    xor     %rdx, %rdx

    mov     $10, %r11

    div     %r11              # Divide by 10

    mov     %rax, %r8         # Tens

    mov     %rdx, %r10        # Ones


    add     $48, %r8

    movb    %r8b, (%r9)

    add     $1, %r9


    add     $48, %r10

    movb    %r10b, (%r9)

    add     $1, %r9


    movb    $10, (%r9)


    mov     $3, %rdx

    mov     $buffer, %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: "

len =   . - msg

buffer: .space 3


Output:

Loop: 00

Loop: 01

Loop: 02

...

Loop: 31

Loop: 32


Skip Leading Zero for Single Digit

Now, we skip the leading 0 for numbers < 10, so it looks like 0, 1, ..., 9, then 10, etc.

# (Same as above, but skips tens digit if it's 0)

cmp     $0, %r8

je      units_digit


Output:

Loop: 0

Loop: 1

...

Loop: 9

Loop: 10

...

Loop: 32


Print in Hexadecimal

Finally, we print loop numbers in hexadecimal (0, 1, 2, ..., A, B, C, ..., 1F):

mov     $16, %r11            # Use base 16

cmp     $58, %r10            # If > 9, convert to A–F using ASCII offset


Output:

Loop: 0

Loop: 1

...

Loop: 9

Loop: A

Loop: B

...

Loop: 1F


Reflection

Assembly programming is still very hard for me. Even simple tasks like printing a number require a lot of manual steps, moving data into registers, converting integers to ASCII, and managing buffers. Unlike high-level languages, nothing is abstracted. I had to slowly work through each instruction and understand what it does. While it's challenging, it's also satisfying when it works. This lab definitely gave me more respect for low-level development!


Comments

Popular posts from this blog

Project Stage 2.A

Project Stage 3

Project Stage 2.C

Welcome to My SPO600 Journey

Lab1 6502 Assembly Language

Stage 1 Completed

Project Stage 2.B

Lab 4 Building GCC on My Linux VM

Lab 2 Adventures in 6502 Assembly

Project Stage 1 Diving In!