NASM-64位分段故障调用过程

时间:2018-12-13 20:50:33

标签: assembly nasm

当我运行程序时,我遇到了段错误。该程序包括两个数字之间的简单加法,将值存储在变量中,然后打印出来以进行系统调用。

这是我称之为的代码:

section .bss
    res: resq 1
    fout: resq 1

section .data
     msg dq 'Hello, world!', 0xa  ;string to be printed
     len equ $ - msg     ;length of the string 
     filename dq 'hello.txt'

section .text
     global _start:     ;must be declared for linker (ld)

_start:             ;tells linker entry point
     mov rcx,5
     mov rdx,4
     call sum
     mov [res],rax

     mov    rdx,1     ;message length
     mov    rcx,res  ;message to write
     mov    rbx,1       ;file descriptor (stdout)
     mov    rax,4       ;system call number (sys_write)
     syscall        ;call kernel

     mov    rax,1       ;system call number (sys_exit)
     syscall       ;call kernel

 sum:
     mov rax,rcx
     add rax,rdx
     add rax,'0'
     ret

调试信息:

 (gdb) n
 sum () at Hello.asm:41
 41              mov rax,rcx
 (gdb) n
 42              add rax,rdx
 (gdb) n
 43              add rax,'0'
(gdb) n
 sum () at Hello.asm:44
 44              ret
 (gdb) n
 0x0000000000000001 in ?? ()
 (gdb) n
 No se pueden encontrar límites en la función actual
 (gdb) quit

结果是分割错误。

1 个答案:

答案 0 :(得分:2)

您尝试将res中的8个字节存储在mov [res],rax中,尽管仅为res分配了1个字节。尽管这是错误的,但这不是导致程序失败的问题。写mov [res], al来解决这个问题。

真正的问题是您的系统电话号码错误。您为i386 Linux使用了系统呼叫号码,但是这些是具有不同号码的amd64系统呼叫。有关正确的系统调用号码,请参考asm/unistd_64.h中的值。对于您的示例,正​​确的数字是1的{​​{1}}和sys_write的{​​{1}}。修正这些数字可使您的程序不再崩溃,但仍无法正常工作。

您还需要修复使用的寄存器。在amd64上系统调用的调用约定与i386不同。您无需将参数放在ebx,ecx等中。而是使用60sys_exitrdirsirdx和{ this answer中概述的{1}}。解决此问题可使您的程序最终运行。