Writing x86 Assembly (Solutions)

The following solutions are for the problems on writing x86 84-bit assembly programs linked here. I encourage you to attempt them by yourself first before looking through the solutions.

deadbeef

Using the write() syscall, print the characters deadbeef\n to stdout without using any global static variables.

First, to print out deadbeef\n, we need to know its ASCII hexadecimal representation first. This can be determined character by character (assuming little endian convention) in this way:

little-endian

Now that we know the ASCII representation, we can implement our assembly code:

.globl main

main:
    movw    $0x0a, %r8w  # Move \n ascii code to %r8
    push    %r8          # Push \n ascii code onto stack
    # Move deadbeef ascii code to %r8
    movq    $0x6665656264616564, %r8
    push    %r8          # Push deadbeef ascii code onto stack
    movq    $0x1, %rax   # System call 1 is write()
    movq    $0x1, %rdi   # File handle 1 is stdout
    movq    %rsp, %rsi   # Argument to write is $0x0a61 on stack
    movq    $9, %rdx     # Number of bytes (length of string)
    syscall              # Invoke write() operation
    pop     %r8          # Restore stack state
    pop     %r8
    retq

Notice that we have to split up the 9-byte (9-character) string into two push instructions, since a 64-bit register can only hold 8 bytes at a time.

Factorials

Write an x86 assembly program to compute the factorial of a number initially stored in %rdi.

.globl main

main:
    movq    $5, %rdi    # Argument n (replace 5 with n)
    movq    $1, %r8     # Counter variable i
    movq    $1, %rax    # Store result of n! in %rax
loop:
    cmp     %r8, %rdi   # If n is less than the counter i...
    jl      exit        # ...then we are done looping and exit
    imulq   %r8         # Multiply %rax by i
    inc     %r8
    jmp     loop
exit:
    retq

Fibonacci Numbers

Write an x86 assembly program to compute the $n$th Fibonacci number, where $n$ is initially stored in %rdi.

.globl main

main:
    movq    $9, %rdi     # Argument n (replace 9 with n)
    movq    $0, %r8      # Counter variable i
    movq    $0, %rax     # Move 0th Fibonacci number to %rax
    movq    $1, %rbx     # Move 1st Fibonacci number to %rbx
loop:
    cmp     %r8, %rdi    # If n is less than or equal to counter i...
    jle     exit         # ...then we are done looping and exit
    movq    %rbx, %rcx
    addq    %rax, %rcx   # %rcx stores %rax + %rbx
    movq    %rbx, %rax
    movq    %rcx, %rbx
    inc     %r8
    jmp     loop
exit:
    retq

Greatest Common Divisor

Using Euclid's Algorithm, calculate the greatest common divisor (GCD) of two numbers $x$ and $y$ initially stored in the registers %rdi and %rsi, respectively. Here is an implementation in Java so you can understand the algorithm:

public static int gcd(int x, int y) {
    if (x == 0) { return y; }
    return gcd(y % x, x);
}

Solution:

.globl main

main:
    movq    $9, %rdi     # Argument x (replace 9 with x)
    movq    $6, %rsi     # Argument y (replace 6 with y)
    movq    $0, %r8      # 0 stored in %r8
loop:
    cmp     %r8, %rdi    # If x is 0...
    je      exit         # ...Return y and exit
    movq    %rsi, %rax
    cqto
    idivq   %rdi         # Divide y by x
    movq    %rdi, %rsi   # Set %rsi to x
    movq    %rdx, %rdi   # set %rdi to y % x
    jmp     loop
exit:
    movq    %rsi, %rax
    retq