【问题标题】:Simple assembly level program gives a segmentation fault简单的汇编级程序给出了分段错误
【发布时间】:2013-07-25 02:43:58
【问题描述】:

我想知道是否有人可以帮助我理解为什么我的汇编程序给我一个分段错误。 (别担心,这是一个相当短的程序。)

segment .data

    a dq 175
    b dq 4096


segment .text

    global _start

_start:

    mov rax, [a]    ; move *a into rax
    add rax, [b]    ; add *b to rax
    xor rax, rax    ; set to zero
    ret             ; return

它应该将 a 和 b 的值相加,然后在程序终止时将它们作为最后的退出代码返回,对吗?所以echo $? 应该打印4271它应该打印0,因为xor

但是,是的,编译使用:nasm -f elf64 -l main.lst main.asm -o main.o && ld main.o -o main.exec

然后运行:./main.exec && echo $?

我们一如既往地非常感谢您的帮助。

【问题讨论】:

    标签: assembly 64-bit nasm


    【解决方案1】:

    您不能使用_start 标签中的ret,因为它不是called。

    segment .data
    
        a dq 175
        b dq 4096
    
    
    segment .text
    
         global _start
    
     _start:
    
        mov rax, [a]    ; move *a into rax
        add rax, [b]    ; add *b to rax
        xor rax, rax    ; set to zero
    
        mov rdi, rax
        mov al, 60 ; sys_exit
        syscall
    

    试试看。 (未经测试!)

    【讨论】:

    • 天哪,现在这么明显
    • 你为什么将 rad 移到 rdi btw? PS:我在 linux 上,所以我想我需要 int 0x80 而不是 mov al, 60
    • 不,rax 的高位为 0,所以mov al, 60 使rax 60 (sys_exit)。 rdi 是第一个(唯一的)参数。 64 位 Linux 使用 syscall 而不是 int 0x80int 0x80 仍然可以在 64 位代码中使用旧的 32 位系统调用号(有人告诉我)。
    • 那么系统调用是一种旧的做事方法吗?我正在关注一本(实际上并不是特别好)的书,它介绍了(特别是)64 位 Linux asm。那里使用的约定是 int 0x80。
    • 我认为syscall 会是较新的方法。 int 0x80 是较旧的方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-24
    • 1970-01-01
    • 2012-09-16
    • 1970-01-01
    相关资源
    最近更新 更多