Reverse Engineering for Beginners

(avery) #1
CHAPTER 41. DIVISION BY 9 CHAPTER 41. DIVISION BY 9
instructions. The first instruction loads0x8E39into the low 16 bits of register and the second instruction isMOVT, it loads
0x383Einto the high 16 bits of the register. IDAis fully aware of such sequences, and for the the sake of compactness
reduces them to one single “pseudo-instruction”.

TheSMMUL(Signed Most Significant Word Multiply) instruction two multiplies numbers, treating them as signed numbers and
leaving the high 32-bit part of result in theR0register, dropping the low 32-bit part of the result.

The“MOV R1, R0,ASR#1”instruction is an arithmetic shift right by one bit.

“ADD R0, R1, R0,LSR#31”isR0 =R1 +R 0 >> 31


There is no separate shifting instruction in ARM mode. Instead, an instructions like (MOV,ADD,SUB,RSB)^2 can have a suffix
added, that says if the second operand must be shifted, and if yes, by what value and how.ASRstands forArithmetic Shift
Right,LSR—Logical Shift Right.

41.2.2 Optimizing Xcode 4.6.3 (LLVM) (Thumb-2 mode).


MOV R1, 0x38E38E39
SMMUL.W R0, R0, R1
ASRS R1, R0, #1
ADD.W R0, R1, R0,LSR#31
BX LR

There are separate instructions for shifting in Thumb mode, and one of them is used here—ASRS(arithmetic shift right).

41.2.3 Non-optimizing Xcode 4.6.3 (LLVM) and Keil 6/2013


Non-optimizing LLVM does not generate the code we saw before in this section, but instead inserts a call to the library
function___divsi3.

What about Keil: it inserts a call to the library function__aeabi_idivmodin all cases.

41.3 MIPS


For some reason, optimizing GCC 4.4.5 generate just a division instruction:

Listing 41.4: Optimizing GCC 4.4.5 (IDA)
f:
li $v0, 9
bnez $v0, loc_10
div $a0, $v0 ; branch delay slot
break 0x1C00 ; "break 7" in assembly output and objdump

loc_10:
mflo $v0
jr $ra
or $at, $zero ; branch delay slot, NOP

Here we see here a new instruction: BREAK. It just raises an exception. In this case, an exception is raised if the divisor
is zero (it’s not possible to divide by zero in conventional math). But GCC probably did not do very well the optimization
job and did not see that $V0 is never zero. So the check is left here. So if $V0 is zero somehow, BREAK is to be executed,
signaling to theOSabout the exception. Otherwise, MFLO executes, which takes the result of the division from the LO
register and copies it in $V0.

By the way, as we may know, the MUL instruction leaves the high 32 bits of the result in register HI and the low 32 bits in
register LO. DIV leaves the result in the LO register, and remainder in the HI register.

If we alter the statement to “a % 9”, the MFHI instruction is to be used here instead of MFLO.

(^2) These instructions are also called “data processing instructions”

Free download pdf