Reverse Engineering for Beginners

(avery) #1

CHAPTER 17. FLOATING-POINT UNIT CHAPTER 17. FLOATING-POINT UNIT


The constants are loaded intoD0andD1: pow() takes them from there. The result will be inD0after the execution of pow().
It is to be passed toprintf()without any modification and moving, becauseprintf()takes arguments ofintegral types
and pointers from X-registers, and floating point arguments from D-registers.


17.6.5 MIPS.


Listing 17.9: Optimizing GCC 4.4.5 (IDA)

main:


var_10 = -0x10
var_4 = -4


; function prologue:
lui $gp, (dword_9C >> 16)
addiu $sp, -0x20
la $gp, (__gnu_local_gp & 0xFFFF)
sw $ra, 0x20+var_4($sp)
sw $gp, 0x20+var_10($sp)
lui $v0, (dword_A4 >> 16) ;?
; load low 32-bit part of 32.01:
lwc1 $f12, dword_9C
; load address of pow() function:
lw $t9, (pow & 0xFFFF)($gp)
; load high 32-bit part of 32.01:
lwc1 $f13, $LC0
lui $v0, ($LC1 >> 16) ;?
; load low 32-bit part of 1.54:
lwc1 $f14, dword_A4
or $at, $zero ; load delay slot, NOP
; load high 32-bit part of 1.54:
lwc1 $f15, $LC1
; call pow():
jalr $t9
or $at, $zero ; branch delay slot, NOP
lw $gp, 0x20+var_10($sp)
; copy result from $f0 and $f1 to $a3 and $a2:
mfc1 $a3, $f0
lw $t9, (printf & 0xFFFF)($gp)
mfc1 $a2, $f1
; call printf():
lui $a0, ($LC2 >> 16) # "32.01 ^ 1.54 = %lf\n"
jalr $t9
la $a0, ($LC2 & 0xFFFF) # "32.01 ^ 1.54 = %lf\n"
; function epilogue:
lw $ra, 0x20+var_4($sp)
; return 0:
move $v0, $zero
jr $ra
addiu $sp, 0x20


.rodata.str1.4:00000084 $LC2: .ascii "32.01 ^ 1.54 = %lf\n"<0>


; 32.01:
.rodata.cst8:00000098 $LC0: .word 0x40400147 # DATA XREF: main+20
.rodata.cst8:0000009C dword_9C: .word 0xAE147AE1 # DATA XREF: main
.rodata.cst8:0000009C # main+18
; 1.54:
.rodata.cst8:000000A0 $LC1: .word 0x3FF8A3D7 # DATA XREF: main+24
.rodata.cst8:000000A0 # main+30
.rodata.cst8:000000A4 dword_A4: .word 0xA3D70A4 # DATA XREF: main+14


And again, we see here LUI loading a 32-bit part of adoublenumber into $V0. And again, it’s hard to comprehend why.


The new instruction for us here isMFC1(“Move From Coprocessor 1”). The FPU is coprocessor number 1, hence “1” in the
instruction name. This instruction transfers values from the coprocessor’s registers to the registers of the CPU (GPR). So
in the end the result from pow() is moved to registers $A3 and $A2, andprintf()takes a 64-bit double value from this
register pair.

Free download pdf