【问题标题】:Why does osx 64-bit asm syscall segfault为什么osx 64位asm syscall segfault
【发布时间】:2015-12-06 07:15:18
【问题描述】:

我正在尝试在 OSX 上以汇编语言编写一个 x86-64 hello world,但是每当我进行系统调用来编写时,它都会出现段错误。我已经通过 Gnu C 内联汇编尝试了等效的系统调用,并且它可以工作,所以我非常困惑:

        .section        __TEXT,__text,regular,pure_instructions
        .globl  _main
        .align  4, 0x90
_main:
        .cfi_startproc
        movq 0x2000004, %rax
        movq 1, %rdi
        leaq _hi(%rip), %rsi
        movq 12, %rdx
        syscall

        xor   %rax, %rax
        ret
        .cfi_endproc

        .section        __DATA,__data
        .globl  _hi
_hi:
        .asciz   "Hello world\n"

这是基于以下工作的 Gnu C:

#include <string.h>

int main() {
  char *hw = "Hello World\n";
  unsigned long long result;
  asm volatile ("movq %1, %%rax\n"
       "movq %2, %%rdi\n"
       "movq %3, %%rsi\n"
       "movq %4, %%rdx\n"
       "syscall\n"
       : "=rax" (result)
       : "Z" (0x2000004),
         "Z" (1),
         "r" (hw),
         "Z" (12)
       : "rax", "rdi", "rsi", "rdx");
}

编译后的 C 块生成以下 asm:

        .section        __TEXT,__text,regular,pure_instructions
        .globl  _main
        .align  4, 0x90
_main:                                  ## @main
        .cfi_startproc
## BB#0:
        pushq   %rbp
Ltmp2:
        .cfi_def_cfa_offset 16
Ltmp3:
        .cfi_offset %rbp, -16
        movq    %rsp, %rbp
Ltmp4:
        .cfi_def_cfa_register %rbp
        leaq    L_.str(%rip), %rcx
        movq    %rcx, -8(%rbp)
        ## InlineAsm Start
        movq $33554436, %rax
movq $1, %rdi
movq %rcx, %rsi
movq $12, %rdx
syscall

        ## InlineAsm End
        movq    %rcx, -16(%rbp)
        xorl    %eax, %eax
        popq    %rbp
        ret
        .cfi_endproc

        .section        __TEXT,__cstring,cstring_literals
L_.str:                                 ## @.str
        .asciz   "Hello World\n"

【问题讨论】:

    标签: macos assembly segmentation-fault x86-64 system-calls


    【解决方案1】:

    您的问题出在以下几行:

    movq 0x2000004, %rax
    movq 1, %rdi
    leaq _hi(%rip), %rsi
    movq 12, %rdx
    

    请注意,在 at&t 语法中,如果您想使用常量,必须 在它们前面加上 $(美元符号),否则您将引用内存地址。如果没有 $ 符号,您的值是直接间接地址。

    例如:

    movq 0x2000004, %rax
    

    尝试从内存地址0x2000004 移动四字并将其放入%rax

    您可能只需将代码修改为如下所示:

    movq $0x2000004, %rax
    movq $1, %rdi
    leaq _hi(%rip), %rsi
    movq $12, %rdx
    

    请注意,我在每个常量的开头添加了一个美元符号。

    【讨论】:

      【解决方案2】:

      在这种情况下,这是一个简单的 64 位“Hello World”(或 Hello StackOverflow)。它应该建立在 OSX 上。试试看:

      section .data
          string1 db  0xa, "  Hello StackOverflow!!!", 0xa, 0xa, 0
          len equ $ - string1
      
      section .text
          global _start
      
          _start:
          ; write string to stdout
              mov     rax, 1              ; set write to command
              mov     rsi, string1        ; string1 to source index
              mov     rdi, rax            ; set destination index to 1 (stdout) already in rax
              mov     rdx, len            ; set length in rdx
              syscall                     ; call kernel
      
              ; exit
              xor     rdi,rdi             ; zero rdi (rdi hold return value)
              mov     rax, 0x3c           ; set syscall number to 60 (0x3c hex)
              syscall                     ; call kernel
      
      ; **Compile/Output**
      ;
      ;     $ nasm -felf64 -o hello-stack_64.o hello-stack_64.asm
      ;     $ ld -o hello-stack_64 hello-stack_64.o
      
      ;     $ ./hello-stack_64
      ;
      ;       Hello StackOverflow!!!
      

      【讨论】:

        猜你喜欢
        • 2014-09-11
        • 2015-06-29
        • 2014-01-12
        • 2010-12-28
        • 1970-01-01
        • 2014-01-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多