AAPCS32 2026-10-24
The 32-bit calling convention for the ARM architecture family. Its base variant passes initial arguments in
r0–r3, returns a word in r0, preserves r4–r8, r10, r11, and sp, and requires eight-byte stack pointer alignment at public calls.[ref] Application binary interface 2026-11-05
An application binary interface specifies the conventions that separately compiled program components must share to cooperate at the binary level. It includes a calling convention, representations and layout of data, and platform conventions for object files. A common source-language declaration alone does not ensure that the generated machine instructions agree on where arguments and results reside.
For example, Microsoft's x64 calling convention passes the first two integer arguments in the processor registers
RCX and RDX, and returns a suitable scalar integer result in RAX.[ref]x64 Calling Convention by Microsoft. Parameter passing, integer row; Return values, scalar values fitting in 64 bits
A caller placing 7 and 5 in different processor registers from those expected by the called function can obtain the wrong result even if both sides describe an addition function. Matching the application binary interface allows a compiler and hand-written assembly language to cooperate; it does not require them to use the same internal implementation. ARM architecture family 2026-10-24
A family of processor architectures with several execution states and instruction encodings. The 32-bit instruction sets include the compact Thumb instruction set; the 32-bit AAPCS32 calling convention specifies interoperation at subroutine boundaries.
Assembly language 2026-10-24
A programming language expressing machine instructions through symbolic operation names, processor registers, labels and data directives. A concrete program must respect its instruction set's operand restrictions and the platform's calling convention.
Past exam of the computer science course of the University of Oxford 2015 Compilers 2 b Solution 2026-10-31
We specify a small stack machine instruction convention because the paper does not prescribe instruction spellings or numeric stack frame offsets.
PUSHFP pushes the current frame pointer. LOAD k replaces a stack-top frame address by the value at fixed offset k in that frame. Let SL be the static link offset, X the offset of p's x, and Y the offset of q's parameter y. ADD pops two integers and pushes their sum. RETVAL returns the stack-top value, removes the current activation and restores the caller through the usual calling convention.PUSHFP ; address of q's frame
LOAD SL ; q's static link: address of p's frame
LOAD X ; value of p.x
PUSHFP ; address of q's frame, above x
LOAD Y ; q's local parameter y
ADD ; x + y
RETVAL ; return the sum to sOne static link traversal suffices for
x, despite three intervening calls in the dynamic chain. y is local to q. In this execution the two loads produce and , so the returned integer is .Make the code a leaf procedure called
array_diff, copy the four argument processor registers into the temporaries used above, and replace the final label by a return. The copies are real addu instructions, avoiding an unexplained move pseudo-instruction:array_diff:
addu $t0,$a0,$zero
addu $t1,$a1,$zero
addu $t2,$a2,$zero
addu $t3,$a3,$zero
# insert the code of (i), including its initial zero-count test
# use the local label array_diff_done in place of done
array_diff_done:
jr $ra
sll $zero,$zero,0In the literal insertion, the
done: line from (i) is the array_diff_done: line displayed here; it is not a second return block. Under the usual calling convention, temporary processor registers are caller-saved. This procedure calls no other procedure and changes no saved processor registers, so it needs no stack frame or saved return address.For a 32-bit constant , define and using its unsigned binary representation. Load it with
lui followed by ori; both are single MIPS instructions. For base addresses and count , the main program is:main:
lui $a0,H_A
ori $a0,$a0,L_A
lui $a1,H_B
ori $a1,$a1,L_B
lui $a2,H_C
ori $a2,$a2,L_C
lui $a3,H_N
ori $a3,$a3,L_N
jal array_diff
sll $zero,$zero,0
main_after_call:
# c now contains the differences; continue the main program hereHere each
H_... and L_... is an assembler-time numeric constant, not an executed operation. lui places the high half and clears the low half; ori inserts the low half without sign extension. ThusThe jal instruction saves the return address after its branch delay slot in $ra; jr $ra resumes at main_after_call. A main routine that itself needs to return to a caller must save its incoming $ra before jal and restore it afterwards.The calling convention passes the integer argument in
$a0, returns the result in $v0, and uses jal with $ra for a call and its return address. The callee returns using jr $ra. Its stack frame grows downwards from $sp and must be removed before returning, restoring the caller's stack pointer.The
$s processor registers are callee-saved registers: a callee that uses $s0 or $s1 must restore their incoming values. The $a, $v, and $t processor registers are caller-saved registers; a caller must preserve any of their values that it needs after a call. Consequently foo keeps its own argument in $s0 and the first call's result in $s1, where nested calls preserve them. Because a nested jal overwrites $ra, foo also saves its incoming return address. Every recursive activation has its own stack frame.The supplied MIPS instructions use the paper's simplified convention: pseudoinstructions such as
subi are accepted, and control transfers have no branch delay slot. The completed code below follows that convention. A hardware implementation with delayed control transfers requires suitable scheduling or nop instructions throughout the supplied code as well.The missing MIPS instructions, in order, areThe comparison
bne $t0, $0, fooRet1
subi $a0, $s0, 3
add $v0, $s1, $v0slti $t0, $s0, 3 makes $t0 nonzero exactly when , so the first instruction selects the base case. The second forms from the saved argument, rather than relying on $a0 surviving the first call. After the second call, $s1 holds bar(y-2) and $v0 holds bar(y-3); the final addition puts their sum in $v0, as required by the calling convention.Use the conventional integer calling convention:
$a0 holds the argument and $v0 holds the result. The function is recursive, so every call must preserve its own return address and original argument. The first recursive result must also survive the second call; a caller-saved register alone would not protect it.This implementation reserves a 32-byte stack frame, keeping the stack pointer eight-byte aligned. Offsets 0–15 are available as the outgoing argument area, 16 stores the original argument, 20 stores the first result, 24 is padding, and 28 stores the return address. It changes no callee-saved register. Assemble in classic MIPS delayed-branch mode with instruction reordering disabled, such as
.set noreorder.foo:
addiu $sp,$sp,-32 # allocate 32-byte aligned frame
sw $ra,28($sp) # save caller return address
sw $a0,16($sp) # save original n
beq $a0,$zero,foo_base
sll $zero,$zero,0
addiu $t0,$zero,1
beq $a0,$t0,foo_base
sll $zero,$zero,0
addiu $t0,$zero,2
beq $a0,$t0,foo_base
sll $zero,$zero,0
addiu $a0,$a0,-1
jal foo
sll $zero,$zero,0
sw $v0,20($sp) # preserve foo(n-1) across next call
lw $a0,16($sp) # recover original n
sll $zero,$zero,0
addiu $a0,$a0,-3
jal foo
sll $zero,$zero,0
lw $t0,20($sp)
sll $zero,$zero,0
addu $v0,$v0,$t0 # combine the two recursive results
beq $zero,$zero,foo_return
sll $zero,$zero,0
foo_base:
addu $v0,$a0,$zero # base case result is n
foo_return:
lw $ra,28($sp)
sll $zero,$zero,0
addiu $sp,$sp,32 # release the frame
jr $ra
sll $zero,$zero,0All displayed operation mnemonics denote single machine instructions. In particular,
sll $zero,$zero,0 is the actual harmless shift encoding often abbreviated by the pseudoinstruction nop; addu $v0,$a0,$zero performs a copy without the move pseudoinstruction. Each branch or jump has an explicit harmless branch delay slot, and harmless shifts also separate loads from their subsequent uses. The base cases return the original argument; other calls return the sum of the two recursive values. Every return restores the saved return address and exactly undoes the stack allocation.[ref]MIPS32 Architecture For Programmers Volume II by MIPS Technologies. Revision 2.00, ADDIU and ADDU, pp. 37–38; JAL and JR, pp. 139 and 144
Register allocation 2026-11-05
Register allocation maps temporary values or virtual registers in a compiler's representation to a limited supply of physical processor registers. A value's live range covers where it may still be needed. Overlapping live ranges constrain which values can share a processor register; register spilling moves some storage into computer memory when necessary.[ref]
The LLVM Target-Independent Code Generator. Live Intervals and Register Allocation
For example, in
a=x+y; b=a*z, the processor register holding a can hold b after a's final use, if the target operation permits. If both values are needed later, overwriting a would lose required information. An interference graph represents simultaneous storage requirements, connecting register allocation to graph coloring. Real targets add constraints from register classes, reserved registers, calling conventions and particular machine instructions; minimizing the number of names alone does not solve the whole problem. Return value 2026-10-31
The result a called procedure supplies to its caller on returning. A calling convention specifies the processor register or memory location carrying it, separately from the return address, which identifies where execution resumes. In the elementary MIPS architecture convention, an integer result is placed in
$v0, while $ra carries the return address.