Reverse Engineering for Beginners

(avery) #1
CHAPTER 21. STRUCTURES CHAPTER 21. STRUCTURES

42 $LC0: .ascii "a=%d; b=%d; c=%d; d=%d\n"<0>


Structure fields come in registers $A0..$A3 and then get reshuffled into $A1..$A4 forprintf(). But there are two SRA
(“Shift Word Right Arithmetic”) instructions, which preparecharfields. Why? MIPS is a big-endian architecture by default 31
on page 433, and the Debian Linux we work in is big-endian as well. So when byte variables are stored in 32-bit structure
slots, they occupy the high 31..24 bits. And when acharvariable needs to be extended into a 32-bit value, it must be shifted
right by 24 bits. charis a signed type, so an arithmetical shift is used here instead of logical.

21.4.4 One more word.


Passing a structure as a function argument (instead of a passing pointer to structure) is the same as passing all structure
fields one by one. If the structure fields are packed by default, the f() function can be rewritten as:

void f(char a, int b, char c, int d)
{
printf ("a=%d; b=%d; c=%d; d=%d\n", a, b, c, d);
};

And that leads to the same code.

21.5 Nested structures


Now what about situations when one structure is defined inside of another?

#include <stdio.h>

struct inner_struct
{
int a;
int b;
};

struct outer_struct
{
char a;
int b;
struct inner_struct c;
char d;
int e;
};

void f(struct outer_struct s)
{
printf ("a=%d; b=%d; c.a=%d; c.b=%d; d=%d; e=%d\n",
s.a, s.b, s.c.a, s.c.b, s.d, s.e);
};

int main()
{
struct outer_struct s;
s.a=1;
s.b=2;
s.c.a=100;
s.c.b=101;
s.d=3;
s.e=4;
f(s);
};

... in this case, bothinner_structfields are to be placed between the a,b and d,e fields of theouter_struct.

Let’s compile (MSVC 2010):

Listing 21.24: Optimizing MSVC 2010 /Ob0
$SG2802 DB 'a=%d; b=%d; c.a=%d; c.b=%d; d=%d; e=%d', 0aH, 00H
Free download pdf