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

标签 linux assembly x86-64

我在 Linux x86_64 上使用 YASM。

我正在关注 Internet 上的汇编语言介绍。我已经介绍了基本数据类型。现在我正在研究循环构造。很好,但我的第一次尝试失败了。此代码段错误围绕 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

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

最佳答案

嗯,你正在使用x86中断调用

int     0x80 

应该改成

syscall

对于 x86_64。在使用 64 位 寄存器时,您依赖于 x86 兼容性。正如 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)

关于linux - 为什么在使用 cmp 指令时会出现段错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30246258/

相关文章:

assembly - Intel x86_64 汇编,如何在 x87 和 SSE2 之间移动? (计算 double 的反正切)

linux - 不断将 Linux 命令的输出写入文件

linux - 我不明白为什么在 bash 中比较字符串时遇到问题

c - 需要帮助将 64 位 Intel 汇编指令解密为 C

assembly - INT 10H 函数 06H 移动光标

gcc - 无法编译程序集 :/usr/bin/ld: i386 architecture of input file `array1.o' is incompatible with i386:x86-64 output

c++ - 操作中的整数溢出

c - ASM 转 C : how to dereference a pointer and add an offset?

linux - 在 R 中,使用 Ubuntu,尝试根据 GMP C lib 安装一个 lib,它找不到 GMP,但我安装了 GMP

linux - 关于 pthread_create 和文件描述符,我可以假设什么?