你好世界上的段错...

Raf*_*ael 5 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'
Run Code Online (Sandbox Code Playgroud)

我的机器: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
Run Code Online (Sandbox Code Playgroud)

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

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

谢谢Nate和Michael

32位Linux SYSCALL表

64位Linux SYSCALL表

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
Run Code Online (Sandbox Code Playgroud)

.

rafael@rcepeda ~/asm $ ./a.out 
Rafael
Run Code Online (Sandbox Code Playgroud)

Nat*_*dge 4

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

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

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

  • 此 32 位代码应该可以在 64 位 Linux 环境中运行,因为所示的示例很可能不在地址空间底部 4GB 之外运行。`int 0x80` 在 64 位代码中仍然可用,但不是首选机制。强制使用“系统调用”的一种情况是访问堆栈上的内存。由于 64 位的堆栈值高于 4GB,它们会被截断,并且对于 32 位“int 0x80”调用毫无用处。 (3认同)