如何在mac上运行.asm文件

发布于 2020-04-13 22:02:14 阅读 1492

学习汇编的小伙伴,如果想在mac上体验汇编语言,那么怎么在mac上运行汇编语言.asm的文件呢?

首先安装nasm

brew install nasm

学习汇编的网站很多,比如我就找了一个比较靠谱的网站tutorialspoint,这个网站有点像菜鸟教程,上面有段汇编的代码如下

segment .text       ;code segment
   global _start    ;must be declared for linker 

_start:               ;tell linker entry point
   mov edx,len       ;message length
   mov ecx,msg     ;message to write
   mov ebx,1       ;file descriptor (stdout)
   mov eax,4       ;system call number (sys_write)
   int 0x80       ;call kernel

   mov eax,1       ;system call number (sys_exit)
   int 0x80       ;call kernel

segment .data      ;data segment
   msg    db 'Hello, world!',0xa   ;our dear string
   len    equ    $ - msg          ;length of our dear string

然后执行下面语句

nasm -f macho64 hello_world.asm

可是报错了

hello_world.asm:6: error: Mach-O 64-bit format does not support 32-bit absolute addresses

是因为我们现在用的是64位的mac系统,不是32位的系统,而教程上给的是32位的寄存器,那么我们只要把32位的寄存器改成64位寄存器即可,如edx改为rdx(要改成rdx,可以看下这个维基上不同处理器对应的寄存器的寄存器名称)。

当然还有一个要注意,由于我们在mac上运行,需要将 mov rax 4mov rax 1改为mov rax, 0x2000004mov rax, 0x2000001

因为macOS的内核XNU是分为BSD层和Mach层。我们常用的系统调用都属于BSD的系统调用(也就是上面教程给的)。而macOS的BSD层在逻辑地址上是位于Mach层之上的,BSD层要从0x2000000开始。因此,我们实际使用的调用号应该是syscall.h给出的调用号加上0x2000000之后的结果,如write的调用号就应当是0x2000004。

更改后的结构(我顺便把后面的注释翻译了下)

global start; 给链接器使用,必须声明
section .text; 代码段
; unistd_32.h  (locate unistd_32.h [ubuntu /usr/src/linux-headers-5.3.0-28-generic/arch/x86/include/generated/uapi/asm/unistd_32.h]))
start:
   ; 告诉链接器这边是入口
 mov rax, 0x2000004; (#define __NR_write 4+ 0x2000000) 系统调用(详情unistd_32.h)
 mov rdi, 1; (stdout) 文件描述符(1是标准出)
 mov rsi, msg; 写的字符串
 mov rdx, msg.len; 写的长度
   ; 上面就相当于与执行 write(int fildes [rbx], const void *buf [rcx], size_t nbyte [rdx] ); = rax(rbx, rcx, rdx);
 syscall
 ;(内核执行)
 mov rax, 0x2000001; (#define __NR_exit 1 + 0x2000000,详情unistd_32.h) 系统调用退出
 mov rdi, 0; 0
 ; 上面就相当于与执行 exit(int status) = rax(rbx)
 syscall;(内核执行)
section .data
;数据段
msg: db "Hello, world!", 10
; 声明的helloword, db = define byte, 0xa = \n ( char(0xa) = \n )
.len: equ $ - msg
; 声明helloword的长度 equ = equal

然后执行

nasm -f macho64 hello_world.asm
ld -macosx_version_min 10.7.0 -lSystem -o hello_world hello_world.o
./hello_world #输出Hello, World

当然还是要劝退想在mac上执行汇编的小伙伴,还是在mac上安装了linux的虚拟机吧,网上的现成的代码运行时没问题的,但是mac还需要改代码,非常麻烦。