Reverse Engineering for Beginners

(avery) #1

CHAPTER 18. ARRAYS CHAPTER 18. ARRAYS


"June",
"July",
"August",
"September",
"October",
"November",
"December"
};


// in 0..11 range
const char* get_month1 (int month)
{
return month1[month];
};


18.5.1 x64


Listing 18.9: Optimizing MSVC 2013 x64

_DATA SEGMENT
month1 DQ FLAT:$SG3122
DQ FLAT:$SG3123
DQ FLAT:$SG3124
DQ FLAT:$SG3125
DQ FLAT:$SG3126
DQ FLAT:$SG3127
DQ FLAT:$SG3128
DQ FLAT:$SG3129
DQ FLAT:$SG3130
DQ FLAT:$SG3131
DQ FLAT:$SG3132
DQ FLAT:$SG3133
$SG3122 DB 'January', 00H
$SG3123 DB 'February', 00H
$SG3124 DB 'March', 00H
$SG3125 DB 'April', 00H
$SG3126 DB 'May', 00H
$SG3127 DB 'June', 00H
$SG3128 DB 'July', 00H
$SG3129 DB 'August', 00H
$SG3130 DB 'September', 00H
$SG3156 DB '%s', 0aH, 00H
$SG3131 DB 'October', 00H
$SG3132 DB 'November', 00H
$SG3133 DB 'December', 00H
_DATA ENDS


month$ = 8
get_month1 PROC
movsxd rax, ecx
lea rcx, OFFSET FLAT:month1
mov rax, QWORD PTR [rcx+rax*8]
ret 0
get_month1 ENDP


The code is very simple:



  • The firstMOVSXDinstruction copies a 32-bit value fromECX(wheremonthargument is passed) toRAXwith sign-
    extension (because themonthargument is of typeint). The reason for the sign extension is that this 32-bit value is
    to be used in calculations with other 64-bit values. Hence, it has to be promoted to 64-bit^10.

  • Then the address of the pointer table is loaded intoRCX.

  • Finally, the input value (month) is multiplied by 8 and added to the address. Indeed: we are in a 64-bit environment
    and all address (or pointers) require exactly 64 bits (or 8 bytes) for storage. Hence, each table element is 8 bytes wide.


(^10) It is somewhat weird, but negative array index could be passed here asmonth(negative array indices will have been explained later:52 on page 571)


. And if this happens, the negative input value ofinttype is sign-extended correctly and the corresponding element before table is picked. It is not going
to work correctly without sign-extension.

Free download pdf