[汇编]小议MacOS停的汇编环境
[汇编]小议MacOS下的汇编环境
在读《Assembly Language Step by Step - Programming with Linux》[1]这本书时,里面有这样一段代码[2]:
上面的代码通过80h中断来调用Linux的syscall,来向屏幕输出Eat at Joe's!这串字符。这个代码在MacOS下不能直接用的,因为MacOS的内核是FreeBSD的port,所以syscall的调用要遵从FreeBSD的习惯。
上面的例子中我们可以看到,在Linux中给syscall传参数主要靠寄存器(eax, ebx, ecx...),而在MacOS中调用则靠堆栈。这是由于Linux和FreeBSD在内核的实现上面有很大不同。因此,可以将上面的代码改写,使其可以在MacOS下面编译运行。
以下是改造后的代码:
注意到参数都改用push入栈了,这是FreeBSD的习惯。
其次,我们将80h调用封装进了_syscall函数,这是FreeBSD的习惯(如果不将_syscall封装进函数直接调用,则还需将eax入栈,详细说明请参考[5])。
最后,用来编译代码的命令也不同:
MacOS使用macho格式来保存可执行文件,此外在使用ld连接时,需要指定入口地址为_start。
更多关于MacOS下汇编的知识可以参考[3]和[4]。
[1] http://www.amazon.com/Assembly-Language-Step-Step-Programming/dp/0470497025
[2] http://www.duntemann.com/assembly.html
[3] http://orangejuiceliberationfront.com/intel-assembler-on-mac-os-x/
[4] http://salahuddin66.blogspot.com/2009/08/nasm-in-mac-os-x.html
[5] http://www.freebsd.org/doc/en/books/developers-handbook/x86-system-calls.html
在读《Assembly Language Step by Step - Programming with Linux》[1]这本书时,里面有这样一段代码[2]:
; Executable name : EATSYSCALL ; Version : 1.0 ; Created date : 1/7/2009 ; Last update : 2/18/2009 ; Author : Jeff Duntemann ; Description : A simple program in assembly for Linux, using NASM 2.05, ; demonstrating the use of Linux INT 80H syscalls to display text. ; ; Build using these commands: ; nasm -f elf -g -F stabs eatsyscall.asm ; ld -o eatsyscall eatsyscall.o ; SECTION .data ; Section containing initialised data EatMsg: db "Eat at Joe's!",10 EatLen: equ $-EatMsg SECTION .bss ; Section containing uninitialized data SECTION .text ; Section containing code global _start ; Linker needs this to find the entry point! _start: nop ; This no-op keeps gdb happy... mov eax,4 ; Specify mov ebx,1 ; Specify File Descriptor 1: Standard Output mov ecx,EatMsg ; Pass offset of the message mov edx,EatLen ; Pass the length of the message int 80H ; Make kernel call MOV eax,1 ; Code for Exit Syscall mov ebx,0 ; Return a code of zero int 80H ; Make kernel call
上面的代码通过80h中断来调用Linux的syscall,来向屏幕输出Eat at Joe's!这串字符。这个代码在MacOS下不能直接用的,因为MacOS的内核是FreeBSD的port,所以syscall的调用要遵从FreeBSD的习惯。
上面的例子中我们可以看到,在Linux中给syscall传参数主要靠寄存器(eax, ebx, ecx...),而在MacOS中调用则靠堆栈。这是由于Linux和FreeBSD在内核的实现上面有很大不同。因此,可以将上面的代码改写,使其可以在MacOS下面编译运行。
以下是改造后的代码:
SECTION .data ; Section containing initialised data EatMsg: db "Eat at Joe's!",10 EatLen: equ $-EatMsg SECTION .bss ; Section containing uninitialized data SECTION .text ; Section containing code global _start ; Linker needs this to find the entry point! _syscall: int 0x80 ;system call ret _start: nop ; This no-op keeps gdb happy... push dword EatLen ; Pass the length of the message push dword EatMsg ; Pass offset of the message push dword 1 ; Specify File Descriptor 1: Standard Output mov eax,0x4 ; System call number (sys_write) call _syscall ; Make kernel call add esp, 12 ; Clean stack (3 arguments * 4) push dword 0 ; Return a code of zero mov eax,0x1 ; Code for Exit Syscall call _syscall ; Make kernel call
注意到参数都改用push入栈了,这是FreeBSD的习惯。
其次,我们将80h调用封装进了_syscall函数,这是FreeBSD的习惯(如果不将_syscall封装进函数直接调用,则还需将eax入栈,详细说明请参考[5])。
最后,用来编译代码的命令也不同:
nasm -f macho -g eatsyscall.asm ld -e _start -o eatsyscall eatsyscall.o
MacOS使用macho格式来保存可执行文件,此外在使用ld连接时,需要指定入口地址为_start。
更多关于MacOS下汇编的知识可以参考[3]和[4]。
[1] http://www.amazon.com/Assembly-Language-Step-Step-Programming/dp/0470497025
[2] http://www.duntemann.com/assembly.html
[3] http://orangejuiceliberationfront.com/intel-assembler-on-mac-os-x/
[4] http://salahuddin66.blogspot.com/2009/08/nasm-in-mac-os-x.html
[5] http://www.freebsd.org/doc/en/books/developers-handbook/x86-system-calls.html