Chapter 22 Quiz: Inline Assembly


Question 1

In GCC extended inline assembly, the syntax is:

asm(code : outputs : inputs : clobbers);

What does the clobbers list tell the compiler?

A) Which registers the inline assembly will use as inputs B) Which registers and resources the inline assembly modifies without them appearing in the output constraints C) Which C variables will be changed by the inline assembly D) Which instructions in the code string are allowed to be reordered


Question 2

What is the output of the following code (assume x86-64, no overflow)?

int a = 0, b = 15;
asm("addl %1, %0"
    : "+r"(a)
    : "r"(b)
    );
printf("%d\n", a);

A) 0 B) 15 C) 30 D) Undefined behavior — the "+" constraint is invalid


Question 3

Why must RBX typically be listed in the clobbers of a CPUID inline assembly?

A) CPUID uses RBX as the input register B) CPUID modifies EBX (the lower 32 bits of RBX), and RBX is a callee-saved register that the compiler may be using C) RBX contains the return address and must be preserved D) The CPUID instruction requires RBX to be zero before execution


Question 4

What is the difference between "r" and "m" constraints?

A) "r" allows any register; "m" allows any memory location B) "r" means read-only; "m" means read-write (modifiable) C) "r" is for 32-bit registers; "m" is for 64-bit (machine-word) registers D) "r" is for integer registers; "m" is for floating-point/MMX registers


Question 5

The asm volatile qualifier prevents:

A) The compiler from generating machine code for the asm block B) The compiler from moving, deleting, or duplicating the asm block during optimization C) The processor from reordering the asm instructions at runtime D) The linker from removing the asm block from the final binary


Question 6

Which of the following is the correct way to read the TSC (timestamp counter) with serialization, measuring elapsed cycles for a code region?

A)

uint64_t start = RDTSC();
// ... code ...
uint64_t end = RDTSC();

B)

CPUID(); uint64_t start = RDTSC();
// ... code ...
uint64_t end = RDTSC(); CPUID();

C)

LFENCE(); uint64_t start = RDTSC();
// ... code ...
RDTSCP(&end); LFENCE();

D)

MFENCE(); uint64_t start = RDTSC();
// ... code ...
MFENCE(); uint64_t end = RDTSC();

Question 7

CMPXCHG (compare and exchange) has which behavior?

A) It always writes src to the destination memory location B) It compares the destination with EAX/RAX; if equal, writes src to destination and sets ZF=1; otherwise writes destination value to EAX/RAX and sets ZF=0 C) It compares two registers and swaps them if the first is greater D) It is equivalent to XCHG but with a lock prefix


Question 8

Why does XCHG with a memory operand have an implicit LOCK prefix on x86?

A) The Intel manual requires XCHG to be followed by MFENCE B) XCHG modifies two locations simultaneously, which is inherently atomic by bus cycle rules; Intel guarantees this in the architecture specification C) XCHG can only operate on cache-line-aligned addresses, which guarantees atomicity D) XCHG uses a special microcode sequence that disables interrupts during execution


Question 9

What is the difference between MFENCE, SFENCE, and LFENCE?

A) MFENCE = memory fence (all reads+writes); SFENCE = store fence (writes only); LFENCE = load fence (reads only) B) MFENCE = main memory; SFENCE = stack memory; LFENCE = L1 cache C) MFENCE = full serialization; SFENCE = prevents speculative execution; LFENCE = prevents branch prediction D) All three are equivalent; the different names are for documentation purposes only


Question 10

In the constraint "=a"(result), what does "a" mean?

A) The operand must be in any general-purpose register B) The operand must be in EAX/RAX specifically C) The operand is an immediate (literal) value D) The operand is an "aliased" variable (same memory as another operand)


Question 11

Why should inline assembly generally not be used to implement atomic operations in modern C code?

A) Inline assembly atomic operations are always slower than library implementations B) C11 provides <stdatomic.h> with _Atomic types and atomic operations that are portable, correct, and allow the compiler to optimize surrounding code C) Inline assembly cannot specify the LOCK prefix correctly D) Modern CPUs do not support LOCK CMPXCHG in user mode


Question 12

The PAUSE instruction in a spinlock loop:

A) Halts the CPU for a fixed number of nanoseconds B) Yields the CPU to the OS scheduler C) Signals that the CPU is in a spin-wait loop, reducing power consumption and improving performance on hyperthreaded processors D) Performs a memory fence and pipeline flush


Question 13

What is the "red zone" and how does it interact with inline assembly?

A) The red zone is 128 bytes below RSP that leaf functions may use without adjusting RSP; inline asm that calls any function (or uses SVC) may corrupt it B) The red zone is a memory region reserved by the OS for interrupt handling C) The red zone is the 16-byte alignment padding added to the stack by the compiler D) The red zone refers to memory addresses below 0x10000 that are unmapped to catch null-pointer dereferences


Question 14

Consider:

asm("clflush %0" : : "m"(*ptr));

What does "m"(*ptr) tell the compiler?

A) ptr is a memory address, and the asm will modify the memory at that address B) ptr is a memory address, and the asm will read from (or address) the memory at that location; the %0 operand will expand to the memory addressing syntax C) ptr must be dereferenced before being passed to the asm block D) ptr is a pointer to a memory-mapped register


Question 15

The RDTSCP instruction provides which advantage over RDTSC?

A) RDTSCP reads a higher-resolution counter with picosecond precision B) RDTSCP is a serializing instruction on the read side — it waits for all prior instructions to complete before reading the TSC, preventing out-of-order execution from corrupting timing measurements C) RDTSCP automatically adjusts for CPU frequency scaling (turbo boost) D) RDTSCP can only be executed in kernel mode, providing higher security


Question 16

In MSVC (Microsoft Visual C++), which of the following is true about inline assembly?

A) MSVC uses the same extended asm(code:outputs:inputs:clobbers) syntax as GCC B) MSVC uses __asm { } block syntax with Intel syntax assembly; it does not support 64-bit inline asm (use intrinsics instead) C) MSVC does not support inline assembly at all D) MSVC requires the /Ox optimization flag to be disabled for inline assembly to work


Question 17

What does the "memory" clobber do?

A) It tells the compiler that the inline assembly may read or write any memory location, preventing it from caching global variables in registers across the asm boundary B) It reserves memory for the inline assembly to use as temporary storage C) It flushes all CPU caches and write buffers D) It prevents the compiler from allocating variables on the stack within the current function


Question 18

Which of the following correctly uses the "+" (read-write) constraint?

A) asm("incl %0" : "=r"(x) : "r"(x)); — output only, input only B) asm("incl %0" : "+r"(x)); — x is both read and written by the asm C) asm("incl %0" : "r"(x) : "=r"(x)); — input first, then output D) asm("incl %0" : "r"(x)); — implicitly read-write


Question 19

When is the "i" (immediate) constraint appropriate?

A) When the operand is a compile-time constant that can be encoded directly into the instruction as an immediate B) When the operand must be loaded into a register before use C) When the operand is a memory address (pointer) D) When the operand is used for interrupt handling


Question 20

LOCK CMPXCHG on x86-64 is used to implement compare-and-swap. After the instruction executes, how does code determine whether the swap succeeded?

A) By checking the return value of the asm block B) By examining the Zero Flag (ZF): ZF=1 means comparison succeeded and swap was performed; ZF=0 means comparison failed C) By reading the destination memory location and comparing it to the expected value D) By calling __sync_bool_compare_and_swap after the inline asm


Answer Key

  1. B
  2. B
  3. B
  4. A
  5. B
  6. C
  7. B
  8. B
  9. A
  10. B
  11. B
  12. C
  13. A
  14. B
  15. B
  16. B
  17. A
  18. B
  19. A
  20. B