7
votes

I'm new to assembly. Is there a way to execute a calculation in GDB apart from the actual code being debugged? For example, I'm stepping through the following using Linux IA-32 assembly (AT&T syntax):

   ;$esi is 0xbffff0a8 which refers to 1 after this command. $eax is 2
   0x08048cd5 <+42>:    lea    -0x20(%ebp),%esi

   ;$eax=ebx=2 after this instruction
   0x08048cd8 <+45>:    mov    %ebx,%eax 

   ;$eax equals 2 after this instruction               
   0x08048cda <+47>:    add    -0x4(%esi,%ebx,4),%eax

I'm just not seeing how $eax ends up at 2. Can I assue an instruction like: -0x4(%esi,%ebx,4) in gdb and analyze the result?

As I understand it, $ebx is multiplied by 4 to yield 8. That is added to $esi to give 9. Then -4 is subtracted to give 5. Then five is added to $eax which was 2 to yield 7. Instead $eax is 2.

1
@HostileFork, I guess you have to convert the instructions to shell commands. I think I see the problem with my calculation. The additions are to the address in $esi address, then the newly calculated address gets dereferenced and added to $eax.user994165
@user994165, this is the difference lea and other instructions like add. For the latter, the effective address of a memory reference like -0x4(%esi, %ebx, 4) is calculated, the value pointed to by that address is then loaded into the CPU and added to %eax.scottt
The instruction add -0x4(%esi,%ebx,4),%eax will do the following: %ebx is multiplied by 4 to yield 8, which is added to %esi to get 0xbffff0b0 from which 4 is subtracted to get an address of 0xbffff0ac. The data from that address is added to %eax. Presumably, the data at 0xbffff0ac is zero. But this doesn't answer your real question of how to evaluate assembly expressions in GDB.Michael Burr

1 Answers

7
votes

You can evaluate expressions using registers, if that's what you're asking.

gdb's print command is your friend.

Basically you can query the registers by prepending a dollar sign, e.g.

print $ecx

or use them in expressions:

print $esi + $ebx + 4

You can dereference the memory using the * operator (like in C):

print *$ecx

will print the contents of the memory location pointed to by ecx.

While you can't directly type in assembly code, you can translate the expression into something more high-level, like this:

print $eax - ($esi * $ebx)

Also, you can convert to various types using casts to C data-types, e.g.

print (char)$ecx

would print the contents of ecx as a character.

print *(char**)$ecx

which would interpret ecx as a pointer to char*, which you then dereference. So you'd see the contents of the string at the address contained in ecx.

This is just the tip of the iceberg though. gdb is very powerful tool. You might also find the display command useful. It's basically the same as print, except it will repeat the print command whenever the code is stopped (useful with breakpoints). You can examine most registers using info registers, or info all-registers if you're masochistic.

You can also change the contents of registers, using set:

set $eax = 20

and stepi through instructions, or continue running the program.

P.S. You'll probably want to learn how to set breakpoints, etc., if you don't know that.