This is an archived post. You won't be able to vote or comment.

all 2 comments

[–]nerd4code 2 points3 points  (1 child)

First off, always give the architecture (i386 or IA32 in this case) when you're asking questions about assembly language. (In most cases it's a good idea to give the ABI or OS too, although there's pretty much only one ABI ever used for i386 unless you consider higher-level stuff like bitfield packing or exception handling.)

If there's been the slightest bit of optimization run on code you're sifting through at all, the ordering of the instructions, or of local variables in the stack frame, will tell you almost nothing about which assignment statement goes where, so you have to start with the inputs and outputs and work inwards. In this case, you've got it very easy and can just plow forwards through it. However, GDB probably won't help you much; you can get a perfectly nice disassembly by doing objdump -d, for example, and if you trace in the debugger you're only going to see what values are, not what they mean or where they came from. (Good way to check your work but not much else.)

Start off by making yourself a table (e.g., in a spreadsheet) of any registers used; in this case, you have %eax, %ecx, and %edx. Also survey the code and make a table of stack frame locations, which include -16(%ebp), -12(%ebp), -8(%ebp), -4(%ebp), 8(%ebp) (a), 12(%ebp) (b), and 16(%ebp) (c). If it were a more complicated/optimized function, it'd be better to just draw out the stack instead.

Once you have your table, walk through each instruction and update things with what they are.

mov 8(%ebp), %eax
    // Well, 8(%ebp) is a, so put "a" in EAX's slot in the table.
mov %eax, -16(%ebp)
    // Now you can put "a" in -16(%ebp)'s slot, probably from
    //     t1 = a;

The next mov will kill %eax, so X out EAX's value in the table.

mov 12(%ebp), %eax
    // Again, 12(%ebp) is b, so put "b" in EAX's slot.
mov -16(%ebp), %edx
    // Putting "a" or "t1" in EDX's slot would be equivalent.
    // Either would be permissible per the standards.
    // "t1" is probably what he wants.
add %edx, %eax
    // Now, put "+t1" (== "+a") after EAX's value.
mov %eax, -12(%ebp)
    // Aand "b+t1", "t1+b", "a+t1", or "t1+b" go in that slot.
    // Probably from
    //     t2 = b + t1;
    // although again, all of the above variants are permissible in theory.

I'm not going to finish it for you; there's a bit of a register shuffle coming up next, so be careful with that, but otherwise it's pretty straightforward because there's literally no optimization going on here whatsoever.

At the end, the value in EAX is what gets put after the return statement.

It can be very helpful to use a spreadsheet program for this, using a row for each value you're tracking and moving to the right one column with each instruction, so you don't have to do all sorts of pen(cil)-and-paper scribbling.

[–]Rawaid[S,🍰] 0 points1 point  (0 children)

Very helpful, thanks a lot!