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

2q5ifsrm  于 2022-11-13  发布在  其他
关注(0)|答案(3)|浏览(155)

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

代码.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中启动:未找到体系结构i386的符号
搜索此错误时,我发现了以下问题:nasm and gcc: 32 bit linking failed (64 bit Mac OS X)
一个回答说
您遇到的问题是,您正在创建一个与Mac OS X对象格式不兼容的32位Linux(ELF)对象文件。请尝试将“-f elf”切换为“-f macho 32”。
但是我肯定使用的是-f macho32,那么问题是什么呢?

nnt7mjpx

nnt7mjpx1#

我也曾尝试自学一些入门级汇编编程,但也遇到了类似的问题。我最初使用nasmelf进行编译,但当我尝试使用ld链接目标文件并创建可执行文件时,这并不起作用。
我认为你主要问题的答案"what would the problem be then?" [to get this to run on 64bit MacOSX]是:**您正在使用-f macho32,但希望它在64位计算机上运行,您需要将命令选项更改为-f macho64。*当然,这不会解决您的汇编代码是为不同的体系结构编写的这一事实(稍后将详细介绍)。
我在右边的命令中找到了this handy answer,在这个示例中可以使用它来编译和链接代码(
在重构汇编代码以使用正确的语法,而不是duskwuff所述的 *nix之后 *):nasm -f macho64 main.asm -o main.o && ld -e _main -macosx_version_min 10.8 -arch x86_64 main.o -lSystem

经过一番搜索,我发现......

1.在Mac 64位上,使用as汇编程序而不是nasm可能会更好(如果您想要更本地的代码),但如果您想要更可移植的代码(了解它们的区别)。

  1. nasm不随默认安装的macho64输出类型一起提供
    1.组装是一个痛苦的keister(这一边)
    现在我的学习咆哮已经不碍事了...
    下面是应该使用nasm在MacOSX 64上运行的代码(如果您已将nasm更新为macho64,请将其记入Dustin Schultz):
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

我在MacOSX64自带的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

我在旅途中发现的一些有用资源:

AS 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/
无法使用ld链接对象文件Can't link object file using ld - Mac OS X
OSX i386系统呼叫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系统调用https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man2/syscall.2.html

nhaq1z21

nhaq1z212#

您需要:
1.将标签名称从main更改为_main(在两个位置)。符号命名在Mac OS X下的工作方式稍有不同。
1.更改向系统调用传递参数的方式。Mac OS X对内核使用与Linux不同的调用约定;这段代码可移植!我不知道它是如何工作的,因为有任何官方文档,但是在GDB中查看像_exit()这样的标准库函数的反汇编可能是有启发性的。
例如,我的系统上有_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的OSX),而不是尝试直接调用内核。

ewm0tg9j

ewm0tg9j3#

我写了一篇关于这个主题的博客文章:https://cs-flex.hashnode.dev/linux-assembly-on-macos
您有3个主要选项:

  1. VM --我不推荐
    1.如果您不介意每月支付20-30美元,那么租用Linux服务器是一个不错的选择
    1.(我个人最好的选择)使用Docker创建一个Linux容器,它共享一个文件夹(卷)并在那里运行汇编程序。如果你以前没有使用过Docker--我仍然认为这个选择是最好的。
    您可以在我的博客文章中阅读详细信息(特别是如果您以前没有使用过Docker)。
    第一个
    您将能够运行container并通过
docker-compose up  # build and run docker container
docker exec -it linux-container bash  # "ssh" into container

在这之后,你所有在Docker文件夹中的代码都将被“链接”到'Docker中的/code/文件夹中。因此,你可以像运行Linux一样在Docker容器中执行它。

相关问题