5
votes

This code is really simple and I am getting a seg fault on my x86_64 linux system. It is bothering me a lot. Just getting started with asm so please have patience!

Assembled with NASM nasm -f elf64 test.asm

linked with ld -o test test.o

SECTION .text
    GLOBAL _start

    _start:
        ; print name
        mov eax,4     ; sys_write
        mov ebx,1     ; stdout
        mov ecx,name  ; start address of name
        mov edx,1     ; length
        int 80H       ; syscall

        ; exit program
        mov eax,1     ; sys_exit
        mov ebx,0     ; success
        int 80H       ; sys_call  

SECTION .data
    name DB 'R'

My machine: Gentoo x86_64 nomultilib! I compiled my own kernel without IA32 emulation. I should have stated that my system is a 64 bit only system. Would this attribute to the errors I am receiving?

$ uname -a
Linux rcepeda 4.4.1-2-ARCH #1 SMP PREEMPT Wed Feb 3 13:12:33 UTC 2016 x86_64 GNU/Linux

Solution

use 64 bit registers and 64bit linux dispatcher

use syscall (not int 80H).

Thank you Nate and Michael

32 Bit Linux SYSCALL TABLE

64 Bit Linux SYSCALL TABLE

SECTION .text
    GLOBAL _start

    _start:
        ; print name
        mov rax,1     ; sys_write
        mov rdi,1     ; stdout
        mov rsi,name  ; start address of name
        mov rdx,7 ; length
        syscall

        ; exit program
        mov rax,60    ; sys_exit
        mov rdi,0     ; success
        syscall

SECTION .data
    name DB "Rafael",10

.

rafael@rcepeda ~/asm $ ./a.out 
Rafael
1
works for me. what is your uname -a?YOU
@MichaelPetch: It prints R instead of Hello world, that's all. But otherwise it's real code.Nate Eldredge
@NateEldredge I know it is a complete example, but it is possible the user is not giving us his exact code. Since his title suggests a different output may suggest that the code seg faulting may not be the code being showed. I am therefore requesting clarification. Unless this code is operating outside the lower 4gb address space, it should work even though it is a 64-bit app using a 32-bit int 0x80 mechanism.Michael Petch
I also am with @YOU . I'm very curious what uname -a returns. It would be helpful to show that in your questionMichael Petch
Likely had you built your kernel with IA32 emulation support your program probably would have worked. Most Linux distros enable IA32 emulation with their 64-bit kernel, so that there can be backward compatibility with older 32-bit user code.Michael Petch

1 Answers

3
votes

You're running in 64-bit mode but this is 32-bit code. If you want 64-bit code, you'll have to rewrite it.

You should be using the 64-bit registers rax, rbx, etc. And in 64-bit Linux, system calls are no longer made with int 80h but with the new syscall instruction. See http://cs.lmu.edu/~ray/notes/linuxsyscalls/ for an example (note this uses AT&T assembler syntax instead of Intel).

Alternatively, you can keep the code the same, and assemble and link it in 32-bit mode, using nasm -f elf32 and ld -m elf_i386. But then you're learning (relatively) obsolete technology. (Edit: Actually, it appears 32-bit compatibility is not enabled on your particular system, so this won't work at all for you.)