如何在OS X上运行此汇编代码?

时间:2013-09-08 22:46:40

标签: macos gcc assembly nasm

开始学习汇编,我得到了一些在Linux上创建的Hello World汇编代码。我想让它适用于64位Mac OS X.

code.asm

SECTION .data       
    hola:   db "Hola!",10   
    tam:    equ $-hola      

SECTION .text       
    global main     

main:               

    mov edx,tam     
    mov ecx,hola        
    mov ebx,1       
    mov eax,4       
    int 0x80        

    mov ebx,0       
    mov eax,1       
    int 0x80        

这就是我的所作所为:

nasm -f macho32 -o object.o code.asm
gcc -m32 -o program object.o

告诉我:

  

架构i386的未定义符号:“_ main”,引自:         从crt1.10.6.o ld开始:找不到架构i386的符号

正在搜索此错误,我发现了这个问题:nasm and gcc: 32 bit linking failed (64 bit Mac OS X)

一个答案说

  

您遇到的问题是您正在创建一个32位Linux(ELF)   目标文件与Mac OS X对象格式不兼容。   尝试将'-f elf'切换为'-f macho32'。

但我肯定在使用-f macho32。那么问题是什么呢?

2 个答案:

答案 0 :(得分:5)

我一直在努力教自己一些入门级汇编编程,我遇到了类似的问题。我最初使用nasm使用elf编译,但是当我尝试使用ld链接目标文件并创建可执行文件时,这不起作用。

我认为主要问题"what would the problem be then?" [to get this to run on 64bit MacOSX]的答案是:您正在使用-f macho32但期望它在64位计算机上运行,​​您需要将命令选项更改为{{1当然,这不会解决你的汇编代码是为不同的架构编写的事实(稍微多一点)。

我在正确的命令中找到了this handy answer来编译和链接你的代码(重构你的汇编代码后使用正确的语法而不是* nix作为duskwuff陈述):-f macho64

经过一番搜索,这是我学到的东西......

  1. 在Mac 64bit上,最好使用nasm -f macho64 main.asm -o main.o && ld -e _main -macosx_version_min 10.8 -arch x86_64 main.o -lSystem汇编程序而不是as(如果你想要更原生的东西),但是如果你想要更多的可移植代码(了解差异)。< / LI>
  2. nasm未附带默认情况下安装的macho64输出类型
  3. 装配是一个痛苦的事(这个旁边)
  4. 现在我的学习咆哮已经不在了......

    以下是使用nasm在MacOSX 64上运行的代码(如果您使用nasm更新了nasm,则归功于Dustin Schultz):

    macho64

    我使用的代码与MacOSX64原生的section .data hello_world db "Hello World!", 0x0a section .text global start start: mov rax, 0x2000004 ; System call write = 4 mov rdi, 1 ; Write to standard out = 1 mov rsi, hello_world ; The address of hello_world string mov rdx, 14 ; The size to write syscall ; Invoke the kernel mov rax, 0x2000001 ; System call number for exit = 1 mov rdi, 0 ; Exit success = 0 syscall ; Invoke the kernel 汇编程序一起使用:

    as

    编译命令:.section __TEXT,__text .global start start: movl $0x2000004, %eax # Preparing syscall 4 movl $1, %edi # stdout file descriptor = 1 movq str@GOTPCREL(%rip), %rsi # The string to print movq $100, %rdx # The size of the value to print syscall movl $0, %ebx movl $0x2000001, %eax # exit 0 syscall .section __DATA,__data str: .asciz "Hello World!\n"

    链接命令:as -arch x86_64 -o hello_as_64.o hello_as_64.asm

    执行命令:ld -o hello_as_64 hello_as_64.o

    我在旅途中找到的一些有用的资源:

    ./hello_as_64 OSX汇编程序参考https://developer.apple.com/library/mac/documentation/DeveloperTools/Reference/Assembler/Assembler.pdf

    在Mac OSX上编写64位程序集http://www.idryman.org/blog/2014/12/02/writing-64-bit-assembly-on-mac-os-x/

    无法使用AS 链接目标文件: Can't link object file using ld - Mac OS X

    OSX i386 SysCalls http://www.opensource.apple.com/source/xnu/xnu-1699.26.8/osfmk/mach/i386/syscall_sw.h

    OSX主系统呼叫定义http://www.opensource.apple.com/source/xnu/xnu-1504.3.12/bsd/kern/syscalls.master

    OSX Syscall https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man2/syscall.2.html

答案 1 :(得分:4)

你需要:

  1. 将标签名称从main更改为_main(两个地方都有)。在Mac OS X下,符号命名的工作方式略有不同。

  2. 更改将参数传递给系统调用的方式。 Mac OS X对Linux内核使用不同的调用约定;此代码可移植!我不知道有没有关于它如何工作的官方文档,但是在GDB中查看像_exit()这样的标准库函数的反汇编可能是有益的。

  3. 这是我系统上的_exit,例如:

        <_exit+0>:  mov    $0x40001,%eax
        <_exit+5>:  call   0x96f124c2 <_sysenter_trap>
        <_exit+10>: jae    0x96f10086 <_exit+26>
        <_exit+12>: call   0x96f1007d <_exit+17>
        <_exit+17>: pop    %edx
        <_exit+18>: mov    0x15a3bf9f(%edx),%edx
        <_exit+24>: jmp    *%edx
        <_exit+26>: ret
        <_exit+27>: nop
    

    0x40001中设置的额外位是......很奇怪,但在这里可以安全地忽略。

    调用_sysenter_trap后的内容是错误处理。

    _sysenter_trap是:

        <_sysenter_trap+0>: pop    %edx
        <_sysenter_trap+1>: mov    %esp,%ecx
        <_sysenter_trap+3>: sysenter
        <_sysenter_trap+5>: nop
    

    考虑到所有事情,你可能最好不要链接到libSystem(相当于libc的OS X),而不是试图直接调用内核。