汇编Linux系统调用与汇编OS x系统调用 [英] Assembly Linux system calls vs assembly OS x system calls
问题描述
我在Mac上运行汇编代码时遇到问题.我目前正在阅读杰夫·邓特曼(Jeff Duntemann)的《汇编一步一步》(Assembly Step by Step)一书.问题在于它专注于为32位linux系统编写程序集.我正在使用64位Mac OS X系统.我仍然可以使用nasm -f macho32在64位系统上运行32位汇编程序,但是显然Duntemann的书中的代码不起作用,因为Linux和mac os x中的系统调用是不同的.我将如何转换该程序:
I have a problem with running assembly code on my mac. I am currently going through Jeff Duntemann's book Assembly Step by Step. The problem is that it focuses on writing assembly for 32 bit linux systems. I am using a 64 bit mac os x system. I can still run 32 bit assembly on my 64 bit system using nasm -f macho32, but apparently the code from Duntemann's book does not work because the system calls in Linux and mac os x are different. How would I convert this program:
; 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 sys_write call
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
以便它可以在我的Mac OS X系统上运行?我希望使用32位汇编的解决方案,因为我正在尝试学习它而不是64位汇编,因为这要复杂得多.
so that it would run on my mac os x system? I would prefer a solution that in 32 bit assembly because I am trying to learn that instead of 64 bit assembly which is much more complicated.
我在网上找到了一个解决方案,但是它使用了堆栈,并且还有其他区别,例如即使Duntemann的程序根本没有引用esp寄存器,也要从esp寄存器中减去:
I have found a solution online, but it uses the stack and has other differences such as subtracting from the esp register even though Duntemann's program doesn't reference the esp register at all:
global start
section .text
start:
push dword msg.len
push dword msg
push dword 1
mov eax, 4
sub esp, 4
int 0x80
add esp, 16
push dword 0
mov eax, 1
sub esp, 12
int 0x80
section .data
msg: db "Hello, world!", 10
.len: equ $ - msg
所以我想我想知道是一个逐步过程,该过程如何将linux系统调用转换为mac os x系统调用?这样一来,当我浏览本书时,我可以做到这一点,而不必在虚拟机或其他设备上下载linux.
So I guess what I want to know is a step by step process of how to convert a linux system call to a mac os x system call? That way as I'm going through this book I can just do that instead of having to download linux on a virtual machine or something.
推荐答案
该解决方案是错误的. sub esp, 12
行应为sub esp, 4
.它没有传递0作为退出状态.它传递了一个垃圾值.
That solution is wrong. The line sub esp, 12
should be sub esp, 4
. It's not passing 0 as the exit status; it's passing a garbage value.
Mac OS X具有BSD系统调用.很难找到示例,因为大多数BSD程序不会直接进行系统调用;它们链接到libc,并调用包装系统调用的libc中的函数.但是在汇编语言中,直接系统调用比libc调用更简单.
Mac OS X has BSD system calls. Examples are hard to find, because most programs for BSD don't make direct system calls; they link to libc and call functions in libc that wrap the system calls. But in assembly language, direct system calls can be simpler than libc calls.
对于32位Intel代码,OS X和Linux均响应int 0x80
.它们都使用eax
中的系统呼叫号码,并且都在eax
中返回结果.主要区别在于:
For 32-bit Intel code, OS X and Linux both respond to int 0x80
. They both take the system call number in eax
, and they both return the result in eax
. The major differences are these:
- Linux在寄存器(
ebx
,ecx
,edx
)中接受参数,但是OS X在堆栈上接受参数.您以相反的顺序推送参数,然后再推送4个字节. - 发生错误时,Linux在
eax
中放置一个负数,但是OS X在eax
中放置一个正数. OS X还设置了条件代码,因此如果发生错误或未发生错误,jb
或jnb
将会跳转. - 系统调用具有不同的编号,有些具有不同的参数.
- Linux takes the arguments in registers (
ebx
,ecx
,edx
), but OS X takes the arguments on the stack. You push the arguments in reverse order, then push an extra 4 bytes. - When an error happens, Linux puts a negative number in
eax
, but OS X puts a positive number ineax
. OS X also sets a condition code sojb
orjnb
would jump if an error did or did not happen. - The system calls have different numbers, and some have different arguments.
BSD系统使用名为syscalls.master的文件来定义系统调用.我已链接到Mac OS X中的 syscalls.master 10.4.11x86 .我们可以使用它来查找每个系统调用的名称,参数和返回类型.例如:
BSD systems use a file named syscalls.master to define system calls. I have linked to syscalls.master from Mac OS X 10.4.11x86. We can use it to find the name, arguments, and return type for each system call. For example:
4 PRE NONE ALL { user_ssize_t write(int fd, user_addr_t cbuf, user_size_t nbyte); }
write(2)系统调用为4,因此我们将4加载到eax
中.它具有3个参数,因此我们按相反的顺序进行推送:我们将缓冲区中的字节数推送,然后推送指针到缓冲区,然后推送文件描述符.推入参数后,我们可能会推sub esp, 4
推入4个额外字节.然后我们执行int 0x80
.然后,我们可能想要add esp, 16
删除我们推送的内容.
The write(2) system call is number 4, so we load eax
with 4. It has 3 arguments, so we push them in reverse order: we push the number of bytes in the buffer, then push a pointer to the buffer, then push the file descriptor. After pushing the arguments, we push 4 extra bytes, perhaps with sub esp, 4
. Then we do int 0x80
. Then we probably want to add esp, 16
to remove what we pushed.
大多数参数和返回值都是4字节整数,但是OS X中的off_t
始终是8字节整数.我们必须小心lseek(2)之类的呼叫.
Most arguments and return values are 4-byte integers, but off_t
in OS X is always an 8-byte integer. We must be careful with calls like lseek(2).
199 NONE NONE ALL { off_t lseek(int fd, off_t offset, int whence); }
offset参数是一个8字节的整数,因此我们将其作为一对4字节的双字进行推送.英特尔处理器是低位字节的,并且堆栈会变小,因此我们在推低双字之前先推高双字. lseek(2)的返回类型也是off_t.它位于寄存器eax
和edx
中,其低位字位于eax
中,高位字位于edx
中.
The offset argument is an 8-byte integer, so we push it as a pair of 4-byte double-words. Intel processors are little-endian, and the stack grows down, so we push the high dword before pushing the low dword. The return type of lseek(2) is also an off_t. It comes in registers eax
and edx
, with the low word in eax
and the high word in edx
.
某些系统调用很奇怪.为了捕获信号,与Linux不同,OS X没有对signal(3)的系统调用.我们必须使用sigaction(2),但这很奇怪:
Some system calls are strange. To catch a signal, OS X has no system call for signal(3), unlike Linux. We must use sigaction(2), but it's strange:
46 NONE KERN ALL { int sigaction(int signum, struct __sigaction *nsa, struct sigaction *osa); }
第二个参数不是常规的sigaction结构.这是一个更大的结构,其中包括一个额外的蹦床区域.如果我们不在libc中调用sigaction(),则必须提供我们自己的蹦床!它不同于Linux和其他BSD内核.
The second argument isn't a regular sigaction struct. It's a bigger struct that includes an extra field for a trampoline. If we don't call sigaction() in libc, then we must provide our own trampoline! It's different from Linux and from other BSD kernels.
这篇关于汇编Linux系统调用与汇编OS x系统调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!