Skip to Content
Course content

212: Understanding Go Assembly Syntax Basics

Click on the "Edit" button in the top corner of the screen to edit your slide content.

I'll be honest with you: the first time I ran go tool compile -S on a piece of my code, I felt like I was staring at a corrupted text file. It looks like a chaotic jumble of letters and numbers. But here is the secret: assembly isn't actually "coding" in the way you're used to. It's more like a very strict recipe for a very literal-minded robot.

The "Prep Bowl" Mental Model

Imagine you're working in a professional kitchen. You have a massive walk-in fridge (this is your Main Memory/RAM) where all the ingredients are kept. However, the head chef has a rule: you cannot chop, stir, or season anything while it's still in the fridge. To do any actual work, you must first move an ingredient into a small prep bowl on your counter.

In Go assembly, those prep bowls are the Registers (like AX, BX, CX). If you want to add two numbers, you can't just "add the fridge to the fridge." You have to:

  • Grab the first number from the fridge and put it in Bowl A (MOVQ from memory to AX).
  • Grab the second number and put it in Bowl B (MOVQ from memory to BX).
  • Mix Bowl B into Bowl A (ADDQ BX to AX).
  • Put the result back into the fridge so it can be used later (MOVQ AX back to memory).

Where Go Keeps Its Scratchpad

Go uses a specific flavor of assembly called Plan 9. If you've spent time with C++ or Rust assembly, this will look slightly "off" to you. The most important thing to realize is that Go doesn't just use hardware registers; it uses a Stack.

Think of the stack as a vertical pile of trays. When a function is called, Go carves out a chunk of this pile for that specific function. When you see something like a+8(SP), you're essentially saying: "Go to the top of the stack (SP), move down 8 bytes, and grab the value stored there." That's how Go handles your local variables and function arguments.

The Vocabulary of Moving Data

You don't need to memorize a thousand instructions to be productive here. Most of what you'll see in Go assembly boils down to a few core operations. I usually group them by their "verb":

  • MOVQ: The "Move" operation. It's actually a copy. MOVQ AX, BX doesn't move the value out of AX; it copies the value from AX into BX. The 'Q' stands for "Quadword," which just means 64 bits.
  • ADDQ / SUBQ: Basic math. These modify the destination register.
  • SHLQ / SHRQ: Shift Left or Shift Right. I see these constantly in Go's internal code because shifting bits is a lightning-fast way to multiply or divide by powers of two.
  • CMPQ: Compare. This doesn't "do" anything to the data; it just sets a hidden flag (like a light switch) that tells the next instruction whether the values were equal, or if one was larger.

Deconstructing a Simple Operation

Let's look at a real example. Suppose you wrote a Go function that adds two numbers and then doubles the result. It would look like this in Go:

func AddAndDouble(a, b int64) int64 {
    return (a + b) * 2
}

If you look at the assembly output, it'll look something like this (simplified for clarity):

MOVQ a+8(SP), AX    // Grab 'a' from the stack and put it in bowl AX
MOVQ b+16(SP), BX    // Grab 'b' from the stack and put it in bowl BX
ADDQ BX, AX          // Add BX to AX. Now AX holds (a + b)
SHLQ $1, AX          // Shift AX left by 1 bit (this is a fast * 2)
MOVQ AX, ret+24(SP)  // Put the final result back on the stack for the caller

Notice the flow: Memory $\rightarrow$ Register $\rightarrow$ Math $\rightarrow$ Memory. That's the heartbeat of almost every single function in your Go program. It feels tedious, but this is exactly why assembly is so fast—there's no guesswork, just direct movement of data.




📋 Practical Task

Reverse Engineering the "Absolute Difference" Assembly

I've provided a snippet of Go assembly below. Your task is to analyze the instructions and write the original Go function that produced this logic. Pay close attention to the CMPQ and the conditional jumps (JGE stands for "Jump if Greater or Equal").

// Assume a and b are int64
MOVQ a+8(SP), AX
MOVQ b+16(SP), BX
CMPQ BX, AX
JGE is_greater_or_equal

// This part only runs if a < b
MOVQ BX, AX
SUBQ AX, BX // Wait, look closely at the subtraction order here
MOVQ BX, ret+24(SP)
RET

is_greater_or_equal:
SUBQ BX, AX
MOVQ AX, ret+24(SP)
RET

Your goal: Write the Go function func CalculateDifference(a, b int64) int64 that implements this exact logic. Submit your Go code.

Rating
0 0

There are no comments for now.

to be the first to leave a comment.