如何在程序集上运行调试器

时间:2019-10-09 01:16:42

标签: assembly gdb

我有以下程序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的正确方法是什么?换句话说:

  1. 我会运行gdb max.s还是gdb max.ogdb max吗?
  2. 如果我键入“ layout src”,则显示“无可用来源”。但是,如果我随后输入l并再次执行layout src,它将显示源。为什么会这样?

enter image description here

2 个答案:

答案 0 :(得分:1)

  

我要运行gdb max.s还是gdb max.o或gdb max吗?

尝试一下?实际上只有最后一个命令有效。

要调试程序,您需要一个可以运行的程序。由于max.smax.o都不是可运行的,因此当GDB尝试execve(2)给定程序时,尝试对其进行调试将导致某种错误。 / p>

对于max.s,您还可能会从GDB收到错误消息,说它不知道如何处理该文件。

  

如果我键入“ layout src”,则显示“无可用来源”。但是,如果我然后键入l并再次执行src布局,它将显示源。为什么会这样?

我不知道那部分。可能是GDB TUI中的错误。

答案 1 :(得分:0)

  

如果我输入“ layout src”,它会显示“无可用来源”

您始终可以使用layout reg来显示寄存器+反汇编。这样,您就不必关心汇编器+链接器,包括行号,而仅是标签的符号。 (符号帮助GDB知道从标签停止后的第一条指令停止时开始的反汇编。x86机器代码不能明确地向后解码。)

您想要源代码行的唯一原因是查看注释,但是通常您将编辑器放在另一个窗口中,对于一个小的循环或块,您会知道预期会发生什么。注释是为了使您在离开代码一段时间后可以更快地将图片传递到头脑中,而不是仅在编写代码/仍在处理代码时花很多时间。但是,如果您确实想提醒某个时刻注册的内容,则只需在编辑器中转到源代码即可。

反汇编通常比源反汇编有用。并排除了一些错误类别,例如无法按照您的想法工作的宏定义,或在组装+反汇编后变得明显的错字。

使用sini而不是源代码行按指令进行单步操作。

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而不是为asld添加不同的选项。或者,如果您想调用相同的命令并在其他源文件上使用它,则max.s仅出现一次。最大的优点是,如果您想为自己的asm函数gcc -no-pie -fno-pie foo.c foo.S Just Works编写C测试工具。

(我个人通常会省略-o max部分,而只是调试gdb ./a.out。但是有可能混淆一下a.out是从哪个来源来的。)