Go
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Functions and Methods
-
Section 4: Concurrency
-
Section 5: Packages and Tooling
-
Section 6: More Standard Library
-
Section 7: Building Services
-
Section 8: Advanced Go
-
Section 9: Go in the Cloud-Native Ecosystem
-
Section 10: Data Structures and Algorithms in Go
-
Section 11: Testing and Deployment
-
Section 12: Practical Projects
-
Section 13: More Standard Library Practice
-
Section 14: More Practice Projects
-
Section 15: Design Patterns in Go
-
Section 16: Interview Practice
-
Section 17: Package fmt In Depth
-
Section 18: Package strings and strconv
-
Section 19: Package os and io
-
Section 20: Package time
-
Section 21: Package sort and container
-
Section 22: Package encoding
-
Section 23: Package net/http In Depth
-
Section 24: Package context
-
Section 25: Package regexp and bytes
-
Section 26: Package errors In Depth
-
Section 27: Package crypto and hash
-
Section 28: Package flag and log
-
Section 29: Package sync In Depth
-
Section 30: More Practice Exercises
-
Section 31: Go Modules and Workspaces In Depth
-
Section 32: Generics Deep Dive (Go 1.18+)
-
Section 33: Testing Package In Depth
-
Section 34: More Interview and Whiteboard Practice
-
Section 35: Package math and unicode
-
Section 36: Package path and filepath
-
Section 37: Package database/sql
-
Section 38: Package text/template and html/template
-
Section 39: Package archive and compress
-
Section 40: Lower-Level net Package
-
Section 41: Package runtime and reflect
-
Section 42: Package embed and io/fs
-
Section 43: Go Assembly and CGO Basics
-
Section 44: Building CLIs and TUIs
-
Section 45: Go Performance Tuning
-
Section 46: More Real-World Projects
-
Section 47: Go in Production
-
Section 48: Go Design Patterns
-
Section 49: Go Interfaces Deep Dive
-
Section 50: Final Practice and Review
212: Understanding Go Assembly Syntax Basics
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 (
MOVQfrom memory to AX). - Grab the second number and put it in Bowl B (
MOVQfrom memory to BX). - Mix Bowl B into Bowl A (
ADDQBX to AX). - Put the result back into the fridge so it can be used later (
MOVQAX 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, BXdoesn'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.
There are no comments for now.