使用cmp指令时为什么会出现段错误?

时间:2015-05-14 20:00:41

标签: linux assembly x86-64

我在Linux x86_64上使用YASM。

我正在关注互联网上的汇编语言。我已经介绍了基本数据类型。现在我潜入环路建设。很好,但我的第一次尝试是失败。这段代码围绕cmd指令的使用进行了细分:

    segment .data
a       dd  0x01,0x02,0x03,0x04
b       dd  0x03,0x03,0x03,0x03
product dd  0x00

    segment .text
    global _start
_start:

    mov     rax,0

begin_while:
    cmp     rax,4
    jnl     end_while

    inc     rax
    jmp     begin_while
end_while:

    mov     rax,1
    xor     rbx,rbx
    int     0x80

但是当我在_start标签之后添加这几行时,它会按预期运行。即没有段错误。

    push    rbp
    mov     rbp,rsp
    sub     rsp,16

我正在阅读的这本书经常使用这个结构。不是每次都是。我知道这与调用函数时要遵循的过程有关。我想它可能与libc运行时有关。无论如何,我不明白为什么需要它。到目前为止,我写的所有少数简单程序(不是那么多)我从来没有使用它。就在今天,现在我正在使用jmp

有人对此有一个很好的解释吗?

1 个答案:

答案 0 :(得分:1)

好吧,您正在使用x86中断调用

int     0x80 

应改为

syscall

代表x86_64。使用x86寄存器时,您依赖于64-bit兼容性。正如Jester所指出的,您的代码将在x86_64上无错误地编译和运行。 (我已经在AMD64 Linux上确认了这两种方式没有错误)但是,所有平台的实现程度尚不清楚。

在编写x86_64代码时,也应该改变:

mov     rax,1

mov     rax, 0x3c  ; 60 decimal

设置正确的x86_64退出系统调用,而不是依赖x86兼容性。 (在x86_64中,系统调用号1__NR_write 1,请参阅:/usr/include/asm/unistd_64.h/usr/include/asm/unistd_32.h进行比较)