简体   繁体   中英

Segmentation fault in Assembly and string

I am trying to make a simple program in assembler, but I do not understand why, I get a fault. I' ve a 64 bit machine running Ubuntu 12.04, and "as" as a assembly compiler. My goal merely is to print the string "Hello" on screen.

I wrote this:

#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

But that's what I get:

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

Why do you think this happens? Any idea?

The calling conventions differ between 32 and 64 bit applications in Linux as well as other OSs. Additionally, for Linux the system call numbers are also different. This is how you invoke the write system call in Linux amd64:

; 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

Additionally, your application needs to call sys_exit to terminate, not return using ret . Read the calling conventions for your platform.

Here is the fix :

#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 

As Michael has already said you need to call sys_exit to avoid segmentation fault .

Edit :
Here is good to mention that int 0x80 invokes 32-bit system calls .
Using int 0x80 for syscall on x64 systems is used for backward compatibility to allow 32-bit applications to run .

On 64-bit systems will be correct to use syscall instruction .
Here is a working version :

.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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM