1.8. PRINTF() WITH SEVERAL ARGUMENTS
; set 4th argument of printf():
.text:00000030 li $a3, 3
; get address of printf():
.text:00000034 lw $v0, (printf & 0xFFFF)($gp)
.text:00000038 or $at, $zero
; call printf():
.text:0000003C move $t9, $v0
.text:00000040 jalr $t9
.text:00000044 or $at, $zero ; NOP
; function epilogue:
.text:00000048 lw $gp, 0x20+var_10($fp)
; set return value to 0:
.text:0000004C move $v0, $zero
.text:00000050 move $sp, $fp
.text:00000054 lw $ra, 0x20+var_4($sp)
.text:00000058 lw $fp, 0x20+var_8($sp)
.text:0000005C addiu $sp, 0x20
; return
.text:00000060 jr $ra
.text:00000064 or $at, $zero ; NOP
8 arguments
Let’s use again the example with 9 arguments from the previous section:1.8.1 on page 50.
#include <stdio.h>
int main()
{
printf("a=%d; b=%d; c=%d; d=%d; e=%d; f=%d; g=%d; h=%d\n", 1, 2, 3, 4, 5, 6, 7, 8);
return 0;
};
Optimizing GCC 4.4.5
Only the first 4 arguments are passed in the $A0 ...$A3 registers, the rest are passed via the stack.
This is the O32 calling convention (which is the most common one in the MIPS world). Other calling
conventions (like N32) may use the registers for different purposes.
SWabbreviates “Store Word” (from register to memory). MIPS lacks instructions for storing a value into
memory, so an instruction pair has to be used instead (LI/SW).
Listing 1.58: Optimizing GCC 4.4.5 (assembly output)
$LC0:
.ascii "a=%d; b=%d; c=%d; d=%d; e=%d; f=%d; g=%d; h=%d\012\000"
main:
; function prologue:
lui $28,%hi(gnu_local_gp)
addiu $sp,$sp,-56
addiu $28,$28,%lo(gnu_local_gp)
sw $31,52($sp)
; pass 5th argument in stack:
li $2,4 # 0x4
sw $2,16($sp)
; pass 6th argument in stack:
li $2,5 # 0x5
sw $2,20($sp)
; pass 7th argument in stack:
li $2,6 # 0x6
sw $2,24($sp)
; pass 8th argument in stack:
li $2,7 # 0x7
lw $25,%call16(printf)($28)
sw $2,28($sp)