我有以下程序max.s
,该程序查找数字列表的最大值:
$ as max.s -g -o max.o && ld max.o -g -o max && ./max
ubuntu$ echo $?
222
该程序的代码如下:
.section .data
data_items:
.long 2,45,222,22,11,22,33,44,5,0
.section .text
.globl _start
_start:
movl $0, %edi
movl data_items(,%edi,4), %eax
movl %eax, %ebx
start_loop:
cmpl $0, %eax
je loop_exit
incl %edi
movl data_items(,%edi,4), %eax
cmpl %ebx, %eax
jle start_loop
movl %eax, %ebx
jmp start_loop
loop_exit:
movl $1, %eax
int $0x80
在此程序上运行gdb
的正确方法是什么?换句话说:
gdb max.s
还是gdb max.o
或gdb max
吗?l
并再次执行layout src
,它将显示源。为什么会这样?答案 0 :(得分:1)
我要运行gdb max.s还是gdb max.o或gdb max吗?
尝试一下?实际上只有最后一个命令有效。
要调试程序,您需要一个可以运行的程序。由于max.s
和max.o
都不是可运行的,因此当GDB尝试execve(2)
给定程序时,尝试对其进行调试将导致某种错误。 / p>
对于max.s
,您还可能会从GDB收到错误消息,说它不知道如何处理该文件。
如果我键入“ layout src”,则显示“无可用来源”。但是,如果我然后键入l并再次执行src布局,它将显示源。为什么会这样?
我不知道那部分。可能是GDB TUI中的错误。
答案 1 :(得分:0)
如果我输入“ layout src”,它会显示“无可用来源”
您始终可以使用layout reg
来显示寄存器+反汇编。这样,您就不必关心汇编器+链接器,包括行号,而仅是标签的符号。 (符号帮助GDB知道从标签停止后的第一条指令停止时开始的反汇编。x86机器代码不能明确地向后解码。)
您想要源代码行的唯一原因是查看注释,但是通常您将编辑器放在另一个窗口中,对于一个小的循环或块,您会知道预期会发生什么。注释是为了使您在离开代码一段时间后可以更快地将图片传递到头脑中,而不是仅在编写代码/仍在处理代码时花很多时间。但是,如果您确实想提醒某个时刻注册的内容,则只需在编辑器中转到源代码即可。
反汇编通常比源反汇编有用。并排除了一些错误类别,例如无法按照您的想法工作的宏定义,或在组装+反汇编后变得明显的错字。
使用si
和ni
而不是源代码行按指令进行单步操作。
b *0x1234
在数字地址处设置一个断点(您可以从反汇编中复制/粘贴),也可以单步设置到您想要断点的位置并在此处使用b
。
另请参见the x86 tag wiki的底部以获取有关调试asm的更多提示。尤其是对进行系统调用的任何代码使用strace
。
as max.s -g -o max.o && ld max.o -g -o max
您可以使用一个命令来完成此操作:gcc -nostdlib -static -g max.s -o max
。您可能会或可能不会发现那么容易。但是,如果您可以将它们组装成32位或64位,则可以方便地添加一个-m32
而不是为as
和ld
添加不同的选项。或者,如果您想调用相同的命令并在其他源文件上使用它,则max.s
仅出现一次。最大的优点是,如果您想为自己的asm函数gcc -no-pie -fno-pie foo.c foo.S
Just Works编写C测试工具。
(我个人通常会省略-o max
部分,而只是调试gdb ./a.out
。但是有可能混淆一下a.out
是从哪个来源来的。)