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

查看:29
本文介绍了汇编 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.

我在网上找到了一个解决方案,但它使用堆栈并有其他差异,例如从 esp 寄存器中减去,即使 Duntemann 的程序根本没有引用 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.master10.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 个参数,所以我们以相反的顺序推送它们:我们推送缓冲区中的字节数,然后推送一个指向缓冲区的指针,然后推送文件描述符.推入参数后,我们推入 4 个额外字节,可能带有 sub esp, 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 字节整数,但 off_t 在 OS X 中始终是 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 字节的双字推送.Intel 处理器是 little-endian,堆栈向下增长,因此我们先推送高双字,然后再推送低双字.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天全站免登陆