Chapter 16 Exercises: ARM64 Architecture
Exercise 1: Register Identification
For each register name, state: (a) its size in bits, (b) what it is an alias for or view of (if applicable), and (c) its conventional role.
a) X0 b) W0 c) X30 d) XZR e) SP f) X29 g) W8 h) X19
Exercise 2: Zero-Extension Behavior
Predict the final value of X3 (in hex) after the following sequence:
MOV X3, #0xFFFFFFFF00000000
MOV W3, #0xDEADBEEF
Explain why.
Exercise 3: S Suffix and Flags
Which of the following instructions update the condition flags N, Z, C, V? For those that do, state which flags might be affected.
a) ADD X0, X1, X2
b) ADDS X0, X1, X2
c) SUB X4, X4, #1
d) SUBS X4, X4, #1
e) CMP X0, X1
f) MOV X0, #42
g) TST X0, #0xFF
h) ANDS X0, X0, X1
Exercise 4: Pseudoinstruction Expansion
Write the actual ARM64 instruction that each pseudoinstruction assembles to:
a) CMP X0, X1
b) CMN X0, X1
c) TST X0, #0xF
d) MOV X1, X2 (register-to-register move)
e) MOV X0, #0 (clear a register)
Exercise 5: Load/Store Discipline
The following are valid x86-64 instructions. Rewrite each as a sequence of valid ARM64 instructions. Assume: X0 = rax, X1 = rbx, X2 = rcx, SP = rsp.
a) add rax, [rbx]
b) add [rbx], rax
c) inc qword [rsp+8]
d) imul rax, [rbx]
e) xor [rbx], rax (XOR memory with register)
Exercise 6: RISC vs. CISC Analysis
For each characteristic, identify whether it describes RISC, CISC, or Both:
a) Variable-length instruction encoding b) All instructions are 4 bytes c) Memory operands in arithmetic instructions d) Large number of general-purpose registers (≥16) e) Condition flags set only when explicitly requested f) Single instruction to copy a memory block g) Internal translation to micro-ops in modern implementations h) Load/store architecture (memory ops separate from ALU ops)
Exercise 7: Calling Convention Registers
For each register, classify it as: (a) argument register, (b) caller-saved temporary, (c) callee-saved, (d) special purpose.
a) X0 b) X7 c) X8 d) X12 e) X19 f) X25 g) X29 h) X30
Exercise 8: ARM64 Hello World — Modify and Explain
Given this ARM64 Hello World:
.section .data
msg: .ascii "Hello, ARM64!\n"
msg_len = . - msg
.section .text
.global _start
_start:
MOV X8, #64
MOV X0, #1
ADR X1, msg
MOV X2, #msg_len
SVC #0
MOV X8, #93
MOV X0, #0
SVC #0
a) What does each instruction in _start do?
b) What would you change to write to stderr instead of stdout?
c) What would you change to exit with error code 1?
d) Why is ADR X1, msg used instead of MOV X1, msg?
e) What is the ARM64 Linux syscall number for write? For exit?
Exercise 9: Flag Conditions
After CMP X0, X1, determine whether the following branches would be taken, given the initial values:
| X0 | X1 | B.EQ | B.NE | B.LT | B.GT | B.LE | B.GE |
|---|---|---|---|---|---|---|---|
| 5 | 5 | ? | ? | ? | ? | ? | ? |
| 3 | 7 | ? | ? | ? | ? | ? | ? |
| 9 | 2 | ? | ? | ? | ? | ? | ? |
| -1 | 0 | ? | ? | ? | ? | ? | ? |
Exercise 10: Conditional Select
Write the ARM64 code (using CSEL or CSNEG) equivalent to each C expression, assuming X0 holds a and X1 holds b:
a) c = (a == b) ? a : b; — result in X2
b) c = (a > 0) ? a : -a; — absolute value, result in X2
c) c = (a >= b) ? a : b; — max function, result in X2
d) c = (a < b) ? a : b; — min function, result in X2
Exercise 11: Instruction Encoding
ARM64 instructions are always 4 bytes. x86-64 instructions vary from 1-15 bytes.
a) An ARM64 program has 1000 instructions. How many bytes does the .text section use?
b) Suppose the same algorithm on x86-64 uses 750 instructions averaging 4.2 bytes each. Which is larger?
c) The ARM64 program uses 5% more instructions than the x86-64 program, but each ARM64 instruction executes in 1 cycle on average while the x86-64 instruction takes 1.2 cycles. Which is faster?
d) What is the advantage of having instructions at predictable offsets when writing a disassembler?
Exercise 12: Register File Comparison
Fill in the following comparison table:
| Feature | x86-64 | ARM64 |
|---|---|---|
| Number of GP registers | ||
| Register size (maximum) | ||
| 32-bit register names | ||
| Are 8/16-bit register aliases available? | ||
| Return address location | ||
| Does arithmetic always update flags? | ||
| Memory-operand arithmetic? | ||
| Zero register? |
Exercise 13: Historical Context
Answer briefly:
a) What does "ARM" stand for? b) What company originally designed ARM, and in what year? c) What is AArch64? d) What does AAPCS64 stand for? e) Name two current ARM64 hardware platforms you could use to run ARM64 code natively.
Exercise 14: Instruction Set Size
ARM64's fixed 32-bit encoding means that the maximum number of distinct instructions is bounded by 2^32.
a) In practice, ARM64 has roughly 500 distinct instruction mnemonics (counting all variants). What fraction of the 2^32 encoding space does this use? b) x86-64's variable-length encoding means a 1-byte instruction has 256 possible values, a 2-byte instruction has 65,536, etc. For 3-byte instructions, how many are possible? (This is one reason x86-64 uses prefix bytes to extend the opcode space.) c) Why might fixed-width encoding lead to a simpler branch predictor?
Exercise 15: Putting It Together
Write an ARM64 assembly program (without using a C library) that:
- Stores the value 100 in a memory variable
- Loads that value into X0
- Compares it to 50
- If X0 > 50, exits with status 1; otherwise exits with status 0
Use the structure from the Hello World example. Assemble and run it with QEMU.
Bonus Exercise: ARM vs. RISC-V
RISC-V is an open-source RISC ISA. Look up the RISC-V base integer instruction set (RV64I) and compare:
a) How many registers does RV64I have? Does it have a zero register? b) Does it have fixed-width instructions? (Hint: look up the "C" extension) c) Does it update flags? (Hint: RISC-V has no condition flags at all) d) How does it implement "compare and branch"?