你好世界上的段错...

时间:2016-02-22 04:52:30

标签: assembly

这段代码非常简单,我在x86_64 linux系统上遇到了一个seg错误。这让我很烦。刚刚开始使用asm,请耐心等待!

与NASM组装 nasm -f elf64 test.asm

与之相关联 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'

我的机器:Gentoo x86_64 nomultilib!我编译自己的内核没有IA32仿真。我应该声明我的系统是64位系统。这会归因于我收到的错误吗?

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

解决方案

使用64位寄存器和64位linux调度程序

使用系统调用(不是int 80H)。

谢谢Nate和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 个答案:

答案 0 :(得分:3)

您正在以64位模式运行,但这是32位代码。如果你想要64位代码,你必须重写它。

您应该使用64位寄存器rax, rbx等。在64位Linux中,不再使用int 80h进行系统调用,而是使用新的syscall指令。有关示例,请参阅http://cs.lmu.edu/~ray/notes/linuxsyscalls/(注意,这使用AT& T汇编语法而不是英特尔)。

或者,您可以保持代码相同,并使用nasm -f elf32ld -m elf_i386以32位模式汇编和链接代码。但是,你要学习(相对)过时的技术。 (编辑:实际上,在您的特定系统上似乎没有启用32位兼容性,因此这对您来说根本不起作用。)