Debugging 在asm中编写和调试min程序

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

我正试图写一个程序来寻找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 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的底部有一个关于调试的部分。我不知道有什么好的教程告诉初学者如何开始调试;在我开始做很多组装之前,我已经知道了很多关于低级系统编程的知识,所以在我有这些问题之前,这些问题已经有了意义。