Debugging 在asm中编写和调试min程序
我正试图写一个程序来寻找asm中整数列表的最小值。以下是我到目前为止的情况:Debugging 在asm中编写和调试min程序,debugging,assembly,x86,att,Debugging,Assembly,X86,Att,我正试图写一个程序来寻找asm中整数列表的最小值。以下是我到目前为止的情况: .section .data data_items: .long 2,3,4,5,1,9,10 # set 10 as the sentinal value .section text .globl _start _start: # %ebx holds min # %edi holds index (destination index) # %eax cu
.section .data
data_items:
.long 2,3,4,5,1,9,10 # set 10 as the sentinal value
.section text
.globl _start
_start:
# %ebx holds min
# %edi holds index (destination index)
# %eax current data item
movl $255, %ebx # set the current min to 255
movl $0, %edi # the index is also zero
start_loop:
movl data_items(,%edi,4), %eax # set %eax equal to the current data item
cmpl $10, %eax # compare %eax with zero to see if we should exit
je exit_loop # if it's the sentinel value, exit
incl %edi # increment the index
cmpl %eax, %edi # compare the current value to the current min
jge start_loop # if it's not less than the current value, go to start
movl %eax, %ebx # move the current value if less that the current min
jmp start_loop # always go back to the start if we've gotten this far
exit_loop:
movl $1, %eax # push the linux system call to %eax (1=exit)
int $0x80 # give linux control (so it will exit)
当我运行此操作时,会得到以下结果:
$as min.s-o min.o&&ld min.o-o min&&min
分段故障(堆芯转储)
如何调试asm?例如,至少在C语言中,编译器会告诉您错误可能是什么以及行号,而在这里我什么都不知道。(注意:错误是使用
.section text
而不是.section.text
,但是如何解决这个问题?在C语言中,很可能编写一个编译时没有警告但崩溃的程序(例如空指针deref),您将看到完全相同的情况。不过,在asm中更可能出现这种情况
您可以使用调试器调试asm,例如GDB。请参阅本手册底部的提示。如果您进行任何系统调用,请使用strace
查看您的程序实际执行的操作
要调试它,您需要在GDB下运行它,并注意到它在第一条指令上出现故障,movl$255,%ebx
。它不访问内存,因此代码提取一定出错。所以,您的节肯定有问题,导致节中的代码链接到可执行文件的非可执行段
objdump-d
也会给你一个提示:默认情况下,它会反汇编.text
部分,而这个程序没有
导致此问题的原因是
text
而不是。text
导致此问题的原因是,具有随机名称的节的默认值不是为数不多的几个特别识别的节之一,而是读+写,不带exec
在GAS中,使用.text
或.data
,.section.text
或.data的特殊快捷指令,以避免这些部分出现此问题
但并非所有的“标准”部分都有特殊指令,您仍然需要.section.rodata
切换到只读数据部分,您应该在其中放置阵列。(读,不写。在较新的工具链上,也没有exec)。但是,您可以使用.comm
或.lcomm
()
另一个可能的问题是,您正在将此32位代码构建为64位可执行文件(除非您使用的是仅限32位的安装,其中默认为
as--32
)。使用32位寻址模式在64位模式下工作,将地址截断为32位。在Linux上访问位置相关可执行文件中的静态数据时,这一点很有效,因为所有代码+数据都链接到低2GB的虚拟地址空间中
但是对(%esp)
或-4(%ebp)
的任何访问都会出现故障,因为64位进程中的堆栈映射到一个高位地址,而低位32之外的非零位
您会注意到GDB中的这个问题,因为
layout reg
将显示所有16个64位整数寄存器RAX..R15。如果您使用非标准名称创建一个节,并且不给它任何属性,那么默认情况下它是可读写的,但不是可执行的。因此,您的代码最终会进入一个不可执行的部分,当处理器拒绝执行第一次执行时会导致分段错误?x86有数百(如果不是数千)个链接,因此不确定从哪里开始。@TagC198:标记wiki的底部有一个关于调试的部分。我不知道有什么好的教程告诉初学者如何开始调试;在我开始做很多组装之前,我已经知道了很多关于低级系统编程的知识,所以在我有这些问题之前,这些问题已经有了意义。