x86 - 装配中出现奇怪的段错误

标签 x86 segmentation-fault fault

我已经使用 nasm 编译器和 ld 链接器用汇编语言编写了一个 hexdump 实用程序。该程序应该转储任何输入文件的十六进制值。但是它在一个特定的过程“LoadBuff”中出现段错误。 loadbuff 的功能是读取输入到一个 16 字节的缓冲区。代码是

LoadBuff:
    push ebx                 
    push edx
    push eax

    mov eax,3       ;sys_read call      
    mov ebx,0               ;read from standard input
    mov ecx,Buff            ;pass the buffer adress
    mov edx,BuffLen         ;pass the number of bytes to be read at a time
    int 80h                 ;call the linux kernel
    mov ebp,eax
    ;cmp eax,0              ;number of characters read is returned in eax
    ;jz exit                ;if zero character is returned i.e end of iinput file      
                            ;jump to exit

    xor ecx,ecx 
    pop eax
    pop edx
    pop ebx
    ret

如果线条
;cmp eax,0                   
;jz exit                      

取消注释代码运行良好,没有任何段错误。但是,当我对其进行注释并将这些行包含在调用方中以便在调用方而不是此处进行相同的比较时,此过程出现段错误。

gdb 回溯给出
#0  0x00000000 in ?? ()

知道为什么会这样吗?

最佳答案

您使用的是 NASM,但没有指定是使用 Intel 风格的语法还是 AT&T 风格的语法。但是,查看您的示例代码,我猜它是 Intel 风格的。

在 Intel 风格的语法中,像 mov 这样的操作像这样工作:

mov <destination>, <source>

换句话说,他们试图模仿“目的地=来源”的思维方式。在 AT&T 语法中,它采用另一种方式:
mov <source>, <destination>

换句话说,他们认为它就像您正在阅读“将源移动到目的地”一样。

现在看看这行代码:
mov ebp, eax

如果您使用的是 Intel 风格的语法(我认为您是因为 AT&T 风格的语法是 mov %ebp, %eax ),那么您正在移动寄存器 eax 的内容。进入 ebp . ebp传统上用作“基指针”……请注意那里的“指针”一词……并且经常完全如此使用。当您在 eax 中获得 0 时,您正在用空指针覆盖现有的基指针。古怪的hijinks接踵而至。

然而,这并不是唯一的问题。另一个问题是:
jz exit

我在您发布的代码中的任何地方都没有看到退出标签,因此您正在程序之外的某个地方(否则汇编程序会发出呜呜声)。在此过程中,您将传递堆栈清理代码,使堆栈处于未知状态。您基本上已将三个寄存器的内容压入堆栈并将它们留在其他例程不期望的地方。

问题是你跳过了清理代码。在您的程序开始时,您正在插入 ebx , edxeax .在您的程序结束时,您以相反的顺序正确地弹出它们( eaxedxebx )。这使堆栈在退出时处于与进入时相同的状态,并且依赖于此的代码设置为按预期运行。

那个jz然而,跳过那个点,所以无论你去哪里,堆栈上都有三个不应该在那里的值。你要跳您的清理代码,而不是 过去 它。

一般规则总是弹出您在程序中推送的内容。这条规则有(极少数)异常(exception)情况,但它们发生的频率还不足以让你现在用它来分散注意力。

关于x86 - 装配中出现奇怪的段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5906645/

相关文章:

c - Unix Socket - 客户端服务器程序(段错误)

c - Strcmp 给出段错误

c - 来自 fork 进程的longjmp

assembly - ModRM : Can't use direct address, 组件 x86

caching - 如何找到 x86 处理器的 cpu 缓存大小

c - 尝试运行时 C 中的段错误

c - 从链表中删除项目时出现段错误

c++ - 来自 hflip 的段错误

iphone - 设置核心数据属性是否会导致错误发生?

performance - resource_stall.other可能意味着什么