5
/*********
exit.asm
*/

[SECTION .text]

global _start


_start:
xor eax, eax
xor ebx, ebx
mov al, 1
int 0x80

//****************************

首先,我使用 nasm -f elf exit.asm 生成目标文件。

然后我在我的 Mac OS X 10.7 上运行了以下“ld”命令,它有这些输出和警告,我试图在我的 32 位 linux 机器上运行它,一切都很好,你能解释一下为什么不链接器在我的 Mac 上工作?

谢谢!

Alfred says: ld -o exiter exit.o
ld: warning: -arch not specified
ld: warning: -macosx_version_min not specified, assuming 10.7
ld: warning: ignoring file exit.o, file was built for unsupported file format ( 0x7f 0x45      0x4c 0x46 0x 1 0x 1 0x 1 0x 0 0x 0 0x 0 0x 0 0x 0 0x 0 0x 0 0x 0 0x 0 ) which is not the   architecture being linked (x86_64): exit.o
Undefined symbols for architecture x86_64:
  "start", referenced from:
    implicit entry/start for main executable
ld: symbol(s) not found for inferred architecture x86_64

在我指定了我的拱门和版本之后,我得到了:

Alfred says: ld -arch x86_64 -macosx_version_min 10.7 -o exiter exit.o
ld: warning: ignoring file exit.o, file was built for unsupported file format ( 0x7f 0x45     0x4c 0x46 0x 1 0x 1 0x 1 0x 0 0x 0 0x 0 0x 0 0x 0 0x 0 0x 0 0x 0 0x 0 ) which is not the   architecture being linked (x86_64): exit.o
 Undefined symbols for architecture x86_64:
 "start", referenced from:
    implicit entry/start for main executable
 ld: symbol(s) not found for architecture x86_64
4

4 回答 4

8

让程序链接起来很简单:

  • 更改_startstart
  • $ nasm -f macho exit.asm
  • $ ld -arch i386 -o exiter exit.o

问题是exit.asm调用 i386 Linuxexit()系统调用(EAX = 1 )并且程序不会OS X 上的预期以零状态退出。

系统调用

系统调用是对内核的请求。exit()与 不同sqrt(),必须在其实现中向具有更高权限的软件组件发出请求,因为它终止正在运行的程序。应用程序无法自行创建或终止进程。系统调用为应用程序提供了一种请求内核代表它们执行操作的方法。

进行系统调用是这样的:

  • 应用程序通过将数据放入 CPU 寄存器(或寄存器指向的内存)中来描述他们想要执行的操作,例如
    • EAX中的值1是的系统调用号。exit
    • EBX0中的值(EBX was clear by )是系统调用的第一个参数,即退出状态。xor
  • 应用程序发出一条指令,导致控制权转移到内核,例如
    • int 80在 i386 上
    • sycall在 x86-64 上
    • svc在 ARMv7 上处于 Thumb 模式
  • 内核检查请求并决定执行或拒绝它。
  • 内核将控制权转移回应用程序,并将返回值放在约定的位置,例如i386 上的EAX

Linux 和 OS X 都void exit(int)为 C 程序提供了一个函数,但在如何向内核描述这个请求的细节上并不一致。中的代码与中的函数exit.asm实现处于同一级别。_exit()libc

即使在运行 Linux 的不同架构之间,系统调用编号和调用约定也不同。例如,在 x86-64 Linux 上,exit(0)更常见的是这样发布:

xor rdi, rdi
mov al, 60
syscall

你可以通过_exit/lib64/libc.so.6.

我们不能直接从 libc 调用 exit() 吗?

你可以。但是您必须将程序与libc. 这是上面链接之间的区别exit.asm

$ cc -m32 -nostdlib exit.o -o exiter

退出-libc.asm

extern exit
global main
main:
push 0
call exit

这必须与:

$ cc -m32 exit-libc.o -o exit-libc

试试这个,看看文件大小。

于 2013-05-28T21:07:37.933 回答
5

Mac OS X 不使用 ELF,因此您需要生成一个 Mach-O 对象以在该系统上链接。在我的机器上nasm似乎只支持 32 位输出,因此您在链接时也需要匹配该架构。

我还必须更改_startstart使其链接。

这是您的代码的一个工作示例:

$ cat exit.asm 
[SECTION .text]

global start

start:
xor eax, eax
xor ebx, ebx
mov al, 1
int 0x80
$ nasm -f macho exit.asm 
$ ld -arch i386 -macosx_version_min 10.7  -o exiter exit.o 
$ ./exiter 
$ echo $?
236

请注意,该程序可能不会在 Mac OS X 上执行您想要的操作,因为它不像 Linux 那样执行系统调用。

于 2013-05-28T21:04:11.267 回答
3

大多数情况下,您会收到此错误:

ld: warning: PIE disabled. Absolute addressing (perhaps -mdynamic-no-pic) not 
allowed in code signed PIE, but used in _start from hello.o. To fix this 
warning, don't compile with -mdynamic-no-pic or link with -Wl,-no_pie

这是因为它正在寻找你的“main()”函数(标签)给我标签“start:”。最好使用“ld -e”指定主标签。

对于 nasm:

-o hello.tmp - outfile
-f macho - specify format
Linux - elf or elf64
Mac OSX - macho

对于 ld:

-arch i386 - specify architecture (32 bit assembly)
-macosx_version_min 10.6 (Mac OSX - complains about default specification)
-no_pie (Mac OSX - removes ld warning)
-e main - specify main symbol name (Mac OSX - default is start)
-o hello.o - outfile

对于壳牌:

./hello.o - execution

单线:

nasm -o hello.tmp -f macho hello.s && ld -arch i386 -macosx_version_min 10.6 -no_pie -e _main -o hello.o hello.tmp && ./hello.o

让我知道这是否有帮助!

我在我的博客上写了如何做到这一点:

http://blog.burrowsapps.com/2013/07/how-to-compile-helloworld-in-intel-x86.html

对于更详细的解释,我在我的 Github 上进行了解释:

https://github.com/jaredsburrows/Assembly

于 2013-07-23T03:08:09.177 回答
0

标准的 mac gcc 不会链接 elf 对象。对于需要坚持使用elf格式并在mac上开发的人,你需要一个交叉编译器......

http://crossgcc.rts-software.org/doku.php?id=compiling_for_linux

然后你可以继续进行类似的事情......

/usr/local/gcc-4.8.1-for-linux32/bin/i586-pc-linux-ld -m elf_i386 -T link.ld -o kernel kasm.o kc.o
于 2015-12-03T16:48:13.887 回答