汇编Linux系统调用与汇编OS x系统调用 [英] Assembly Linux system calls vs assembly OS x system calls

查看:97
本文介绍了汇编Linux系统调用与汇编OS x系统调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在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在寄存器(ebxecxedx)中接受参数,但是OS X在堆栈上接受参数.您以相反的顺序推送参数,然后再推送4个字节.
  • 发生错误时,Linux在eax中放置一个负数,但是OS X在eax中放置一个正数. OS X还设置了条件代码,因此如果发生错误或未发生错误,jbjnb将会跳转.
  • 系统调用具有不同的编号,有些具有不同的参数.
  • 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 in eax. OS X also sets a condition code so jb or jnb 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.它位于寄存器eaxedx中,其低位字位于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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆