装配和字符串中的分段错误

时间:2013-08-29 14:31:36

标签: linux assembly

我想在汇编程序中创建一个简单的程序,但我不明白为什么,我得到了一个错误。 我有一台运行Ubuntu 12.04的64位机器,以及作为汇编编译器的“as”。 我的目标只是在屏幕上打印字符串“Hello”。

我写了这个:

#print.s
.section .data
.globl StringToPrint

 StringToPrint: .asciz "Hello"

 .globl _start

  _start:       
    movq $4, %rax
    movq $1, %rbx
    movq $StringToPrint, %rcx
    movq $5, %rdx
    int $0x80
 _done:    
    ret

但这就是我得到的:

$ as print.s -o print.o
$ ld print.o -o print
$ ./print
Hello[1]    10679 segmentation fault (core dumped)  ./print

为什么你认为这会发生?有什么想法吗?

2 个答案:

答案 0 :(得分:2)

Linux和其他操作系统中的32位和64位应用程序的调用约定不同。此外,对于Linux,系统呼叫号码也不同。这是您在Linux amd64中调用write系统调用的方法:

; sys_write(stdout, message, length)

mov    rax, 1        ; sys_write
mov    rdi, 1        ; stdout
mov    rsi, message  ; message address
mov    rdx, length   ; message string length
syscall

此外,您的应用程序需要调用sys_exit来终止,而不是使用ret返回。阅读适用于您平台的调用约定。

答案 1 :(得分:1)

以下是修复:

#print.s
.section .data

.globl StringToPrint
    StringToPrint: .asciz "Hello"   

.globl _start

  _start:

        movl    $5, %edx             # string length
        movl    $StringToPrint, %ecx # pointer to string to write
        movl    $1, %ebx             # file handle (stdout)
        movl    $4, %eax             # system call number (sys_write)
        int     $0x80                # Passes control to interrupt vector

        #sys_exit (return_code)  
        movl    $1, %eax             #System call number 1: exit()
        movl    $0, %ebx             #Exits with exit status 0
        int     $0x80                #Passes control to interrupt vector 

正如Michael已经说过你需要调用sys_exit以避免分段错误。

编辑
值得一提的是int 0x80调用了32位系统调用 在x64系统上使用int 0x80用于syscall用于向后兼容,以允许运行32位应用程序。

在64位系统上使用syscall指令是正确的 这是一个工作版本:

.section .data
StringToPrint: .asciz "Hello"

.section .text
.globl _start

_start:

        movq    $1, %rax                # sys_write
        movq    $1, %rdi                # stdout
        movq    $StringToPrint, %rsi    # pointer to string to write
        movq    $5, %rdx                # string length
        syscall

        movq    $60, %rax               # sys_exit
        movq    $0, %rdi                # exit code
        syscall