【发布时间】:2016-01-16 14:34:24
【问题描述】:
在我的 Mac 上运行汇编代码时遇到问题。我目前正在阅读 Jeff Duntemann 的《Assembly Step by Step》一书。问题在于它专注于为 32 位 linux 系统编写程序集。我使用的是 64 位 mac os x 系统。我仍然可以使用 nasm -f macho32 在我的 64 位系统上运行 32 位汇编,但显然 Duntemann 书中的代码不起作用,因为 Linux 和 mac os x 中的系统调用不同。我将如何转换这个程序:
; 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 位汇编。
我在网上找到了一个解决方案,但是它使用堆栈并且有其他差异,例如从 esp 寄存器中减去,即使 Duntemann 的程序根本没有引用 esp 寄存器:
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 或其他东西。
【问题讨论】:
-
正如我在your other question 中指出的,Mac OS X 系统调用不是公开记录的接口。本教程使用 32 位 Linux 系统。 (例如,在虚拟机中。)
-
如果在 x86_64 上构建 x86,您应该使用
nasm -f elf -o asmfile.o asmfile.asm构建并链接ld -m elf_i386 -o progname asmfile.ofor linux(您可以在 mac 上尝试,但如上所述 - 不保证)。至于系统调用号码,linux 有unistd_32.h(或者可能只是unistd.h,如果它只是32 位)。通常在/usr/include/asm、/usr/include/asm-x86中找到。如果没有公开记录的接口,则您的 mac 上可能没有类似的接口。该文件包含 linux(32 位)系统上的所有系统调用号。 -
另外,如果您注意到,您的两个版本正在做完全相同的事情并使用完全相同的系统调用
4-syswrite, 1-exit。唯一的区别似乎是 mac 版本正在填充ebx, ecx & edx与推入堆栈的值以进行syswrite调用,然后将0(退出状态)推入堆栈而不是之前直接加载ebx打电话给exit
标签: linux macos assembly x86 32-bit