GDB:汇编指令计算

7

我刚开始学习汇编语言。除了正在调试的实际代码之外,是否有一种方法可以在GDB中执行计算?例如,我正在使用Linux IA-32汇编(AT&T语法)逐步执行以下内容:

   ;$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

我不明白$eax是如何变成2的。我可以在gdb中执行像“-0x4(%esi,%ebx,4)”这样的指令并分析结果吗?

据我所知,$ebx乘以4得到8,然后加上$esi得到9。然后减去-4得到5。然后将5加到$eax上,$eax为2,则应得到7。但实际上$eax是2。


1
可能是如何直接在gdb中运行汇编?的重复问题。 - HostileFork says dont trust SE
@HostileFork,我猜你得把这些指令转换成shell命令。我想我找到了我的计算问题所在。加法是针对$esi地址的,然后新计算出来的地址被取消引用并加到$eax中。 - user994165
@user994165,这里讲解了lea和其他指令(如add)的区别。对于后者,会计算内存引用的有效地址(例如-0x4(%esi, %ebx, 4)),然后将该地址指向的值加载到CPU中,并加到%eax寄存器中。 - scottt
指令 add -0x4(%esi,%ebx,4),%eax 将执行以下操作:将 %ebx 乘以 4 得到 8,加上 %esi 得到 0xbffff0b0,再减去 4 得到地址 0xbffff0ac。从该地址读取的数据将被加到 %eax 中。假设 0xbffff0ac 处的数据为零。但这并不能回答你在 GDB 中如何评估汇编表达式的真正问题。 - Michael Burr
1个回答

7

如果您想评估表达式,可以使用寄存器。

print 命令是 gdb 的好朋友。

基本上,您可以通过在寄存器前加上美元符号来查询寄存器,例如:

print $ecx

或者在表达式中使用它们:
print $esi + $ebx + 4

您可以使用*运算符(类似于C语言)对内存进行解引用:
print *$ecx

该语句将打印由ecx指向的内存地址的内容。

虽然你不能直接输入汇编代码,但你可以将其转换为更高级别的表达式,例如:

print $eax - ($esi * $ebx)

此外,您可以使用 C 数据类型的强制转换将其转换为各种类型,例如:
print (char)$ecx

将会打印出ecx的内容作为字符。

print *(char**)$ecx

这里会将ecx解释为一个指向char*的指针,然后对其进行解引用。这样,您就可以看到在ecx包含的地址处字符串的内容。
当然,这只是冰山一角。 gdb是非常强大的工具。您还可能发现display命令很有用。它基本上与print相同,不同之处在于每当代码停止时(使用断点时很有用),它将重复print命令。您可以使用info registersinfo all-registers检查大多数寄存器,如果您足够韧性,也可以这样做。
您还可以使用set更改寄存器的内容:
set $eax = 20

使用stepi逐步执行指令,或者continue运行程序。

附注:如果您不知道如何设置断点等,请学习相关知识。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接