/*********
exit.asm
*/
[SECTION .text]
global _start
_start:
xor eax, eax
xor ebx, ebx
mov al, 1
int 0x80
//****************************
First I used nasm -f elf exit.asm to generate the object file.
首先,我使用nasm -f elf exit.asm生成目标文件。
then I ran the following "ld" command on my Mac OS X 10.7, it has the these outputs and warning, I tried to run it on my 32 bit linux machine, everything went through just fine, Could you please explain why would not the linker work on my Mac?
然后我在我的Mac OS X 10.7上运行了以下“ld”命令,它有这些输出和警告,我试图在我的32位linux机器上运行它,一切都很顺利,请你解释为什么不会链接器在我的Mac上运行?
Thank you!
谢谢!
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
after I specify my arch and version, I got:
在我指定我的拱门和版本之后,我得到了:
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 个解决方案
#1
6
Getting the program to link is the easy part:
获取程序链接很容易:
- Change
_start
tostart
- 改变_start开始
$ nasm -f macho exit.asm
- $ nasm -f macho exit.asm
$ ld -arch i386 -o exiter exit.o
- $ ld -arch i386 -o exiter exit.o
The problem is that exit.asm
is calling the i386 Linux exit()
system call (EAX = 1) and the program would NOT exit with a zero status as intended on OS X.
问题是exit.asm正在调用i386 Linux exit()系统调用(EAX = 1),并且程序不会以OS X上的预期状态退出。
System Calls
A system call is a request to the kernel. exit()
, unlike sqrt()
, must make a request to a software component with higher privileges in its implementation since it terminates a running program. Apps can't create or terminate processes by themselves. System calls provide a way for apps to ask the kernel to perform actions on their behalf.
系统调用是对内核的请求。与sqrt()不同,exit()必须向其实现中具有更高权限的软件组件发出请求,因为它终止正在运行的程序。应用无法自行创建或终止进程。系统调用为应用程序提供了一种让内核代表他们执行操作的方法。
Making a syscall goes something like this:
制作系统调用是这样的:
- Apps describe the operation they want to perform by placing data in CPU registers (or memory pointed to by registers), e.g.
- The value
1
in EAX is the system call number ofexit
. - EAX中的值1是退出的系统调用号。
- The value
0
in EBX (EBX was cleared byxor
) is the first argument to the syscall, the exit status. - EBX中的值0(EBX由xor清除)是系统调用的第一个参数,即退出状态。
- The value
- 应用程序通过将数据放入CPU寄存器(或寄存器指向的存储器)来描述他们想要执行的操作,例如, EAX中的值1是退出的系统调用号。 EBX中的值0(EBX由xor清除)是系统调用的第一个参数,即退出状态。
- Apps issue an instruction that causes control to transfer to the kernel, e.g.
-
int 80
on i386 - i386上的int 80
-
sycall
on x86-64 - x86-64上的sycall
-
svc
in Thumb mode on ARMv7 - ARMv7上的Thumb模式下的svc
-
- 应用程序发出一条指令,使控件转移到内核,例如在ARMv7上的Thumb模式下,x86-64 svc上的i386 sycall上的int 80
- The kernel inspects the request and decides to perform or deny it.
- 内核检查请求并决定执行或拒绝它。
- The kernel transfers control back to the app with the return value in an agreed upon location, e.g. EAX on i386.
- 内核将控制权转移回应用程序,并在约定的位置返回值,例如: i386上的EAX。
Linux and OS X both provide a void exit(int)
function for C programs but don't agree on the details on how to describe this request to the kernel. The code in exit.asm
is at the same level as the implementation of the _exit()
function in libc
.
Linux和OS X都为C程序提供了一个void exit(int)函数,但是对于如何向内核描述这个请求的细节并不一致。 exit.asm中的代码与libc中_exit()函数的实现处于同一级别。
Even between different architectures running Linux the syscall numbers and calling convention differ. e.g. On x86-64 Linux, exit(0)
is more commonly issued like this:
即使在运行Linux的不同架构之间,系统调用号和调用约定也不同。例如在x86-64 Linux上,退出(0)更常发布如下:
xor rdi, rdi
mov al, 60
syscall
You can see this by disassembling _exit
in /lib64/libc.so.6
.
你可以通过在/lib64/libc.so.6中反汇编_exit来看到这一点。
Can't We Just Call exit() from libc Instead?
You can. But you'd have to link the program with libc
. It's the difference between linking exit.asm
above with:
您可以。但是你必须将程序与libc链接起来。链接exit.asm与上面的区别是:
$ cc -m32 -nostdlib exit.o -o exiter
and
和
exit-libc.asm
出口libc.asm
extern exit
global main
main:
push 0
call exit
which has to be linked with:
必须与以下内容联系:
$ cc -m32 exit-libc.o -o exit-libc
Try this and take a look at the file size.
试试这个,看看文件大小。
#2
3
Mac OS X doesn't use ELF, so you'll want to generate a Mach-O object to link with on that system. On my machine nasm
appears to only support 32-bit output, so you'll need to match that architecture when linking, too.
Mac OS X不使用ELF,因此您需要生成一个Mach-O对象以在该系统上进行链接。在我的机器上,nasm似乎只支持32位输出,因此在链接时你也需要匹配该架构。
I also had to change _start
to start
to get it to link.
我还必须更改_start以开始链接。
Here's a working example with your code:
以下是您的代码的工作示例:
$ 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
Note that the program probably doesn't do what you want on Mac OS X, since it doesn't do system calls the same way as Linux.
请注意,该程序可能无法在Mac OS X上执行您想要的操作,因为它不像Linux那样执行系统调用。
#3
2
Most of the time when you receive this error:
大多数情况下,当您收到此错误时:
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
It is because it is looking for your "main()" function(label) to me the label "start:". It is always best to specify the your main label with "ld -e".
这是因为它正在寻找你的“main()”函数(标签)给我标签“start:”。最好用“ld -e”指定主标签。
For nasm:
-o hello.tmp - outfile
-f macho - specify format
Linux - elf or elf64
Mac OSX - macho
For 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
For Shell:
./hello.o - execution
One-liner:
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
Let me know if this helps!
如果这有帮助,请告诉我!
I wrote how to do it on my blog here:
我在博客上写了如何做到这一点:
http://blog.burrowsapps.com/2013/07/how-to-compile-helloworld-in-intel-x86.html
http://blog.burrowsapps.com/2013/07/how-to-compile-helloworld-in-intel-x86.html
For a more verbose explanation, I explained on my Github here:
有关更详细的解释,我在这里向我的Github解释:
https://github.com/jaredsburrows/Assembly
https://github.com/jaredsburrows/Assembly
#4
0
The standard mac gcc won't link elf objects. For people who need to stick with the elf format and develop on a mac, you need a cross compiler...
标准mac gcc不会链接elf对象。对于需要坚持使用elf格式并在mac上开发的人来说,你需要一个交叉编译器......
http://crossgcc.rts-software.org/doku.php?id=compiling_for_linux
http://crossgcc.rts-software.org/doku.php?id=compiling_for_linux
Then you can proceed with something similar to this...
然后你可以继续进行类似的事情......
/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
#1
6
Getting the program to link is the easy part:
获取程序链接很容易:
- Change
_start
tostart
- 改变_start开始
$ nasm -f macho exit.asm
- $ nasm -f macho exit.asm
$ ld -arch i386 -o exiter exit.o
- $ ld -arch i386 -o exiter exit.o
The problem is that exit.asm
is calling the i386 Linux exit()
system call (EAX = 1) and the program would NOT exit with a zero status as intended on OS X.
问题是exit.asm正在调用i386 Linux exit()系统调用(EAX = 1),并且程序不会以OS X上的预期状态退出。
System Calls
A system call is a request to the kernel. exit()
, unlike sqrt()
, must make a request to a software component with higher privileges in its implementation since it terminates a running program. Apps can't create or terminate processes by themselves. System calls provide a way for apps to ask the kernel to perform actions on their behalf.
系统调用是对内核的请求。与sqrt()不同,exit()必须向其实现中具有更高权限的软件组件发出请求,因为它终止正在运行的程序。应用无法自行创建或终止进程。系统调用为应用程序提供了一种让内核代表他们执行操作的方法。
Making a syscall goes something like this:
制作系统调用是这样的:
- Apps describe the operation they want to perform by placing data in CPU registers (or memory pointed to by registers), e.g.
- The value
1
in EAX is the system call number ofexit
. - EAX中的值1是退出的系统调用号。
- The value
0
in EBX (EBX was cleared byxor
) is the first argument to the syscall, the exit status. - EBX中的值0(EBX由xor清除)是系统调用的第一个参数,即退出状态。
- The value
- 应用程序通过将数据放入CPU寄存器(或寄存器指向的存储器)来描述他们想要执行的操作,例如, EAX中的值1是退出的系统调用号。 EBX中的值0(EBX由xor清除)是系统调用的第一个参数,即退出状态。
- Apps issue an instruction that causes control to transfer to the kernel, e.g.
-
int 80
on i386 - i386上的int 80
-
sycall
on x86-64 - x86-64上的sycall
-
svc
in Thumb mode on ARMv7 - ARMv7上的Thumb模式下的svc
-
- 应用程序发出一条指令,使控件转移到内核,例如在ARMv7上的Thumb模式下,x86-64 svc上的i386 sycall上的int 80
- The kernel inspects the request and decides to perform or deny it.
- 内核检查请求并决定执行或拒绝它。
- The kernel transfers control back to the app with the return value in an agreed upon location, e.g. EAX on i386.
- 内核将控制权转移回应用程序,并在约定的位置返回值,例如: i386上的EAX。
Linux and OS X both provide a void exit(int)
function for C programs but don't agree on the details on how to describe this request to the kernel. The code in exit.asm
is at the same level as the implementation of the _exit()
function in libc
.
Linux和OS X都为C程序提供了一个void exit(int)函数,但是对于如何向内核描述这个请求的细节并不一致。 exit.asm中的代码与libc中_exit()函数的实现处于同一级别。
Even between different architectures running Linux the syscall numbers and calling convention differ. e.g. On x86-64 Linux, exit(0)
is more commonly issued like this:
即使在运行Linux的不同架构之间,系统调用号和调用约定也不同。例如在x86-64 Linux上,退出(0)更常发布如下:
xor rdi, rdi
mov al, 60
syscall
You can see this by disassembling _exit
in /lib64/libc.so.6
.
你可以通过在/lib64/libc.so.6中反汇编_exit来看到这一点。
Can't We Just Call exit() from libc Instead?
You can. But you'd have to link the program with libc
. It's the difference between linking exit.asm
above with:
您可以。但是你必须将程序与libc链接起来。链接exit.asm与上面的区别是:
$ cc -m32 -nostdlib exit.o -o exiter
and
和
exit-libc.asm
出口libc.asm
extern exit
global main
main:
push 0
call exit
which has to be linked with:
必须与以下内容联系:
$ cc -m32 exit-libc.o -o exit-libc
Try this and take a look at the file size.
试试这个,看看文件大小。
#2
3
Mac OS X doesn't use ELF, so you'll want to generate a Mach-O object to link with on that system. On my machine nasm
appears to only support 32-bit output, so you'll need to match that architecture when linking, too.
Mac OS X不使用ELF,因此您需要生成一个Mach-O对象以在该系统上进行链接。在我的机器上,nasm似乎只支持32位输出,因此在链接时你也需要匹配该架构。
I also had to change _start
to start
to get it to link.
我还必须更改_start以开始链接。
Here's a working example with your code:
以下是您的代码的工作示例:
$ 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
Note that the program probably doesn't do what you want on Mac OS X, since it doesn't do system calls the same way as Linux.
请注意,该程序可能无法在Mac OS X上执行您想要的操作,因为它不像Linux那样执行系统调用。
#3
2
Most of the time when you receive this error:
大多数情况下,当您收到此错误时:
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
It is because it is looking for your "main()" function(label) to me the label "start:". It is always best to specify the your main label with "ld -e".
这是因为它正在寻找你的“main()”函数(标签)给我标签“start:”。最好用“ld -e”指定主标签。
For nasm:
-o hello.tmp - outfile
-f macho - specify format
Linux - elf or elf64
Mac OSX - macho
For 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
For Shell:
./hello.o - execution
One-liner:
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
Let me know if this helps!
如果这有帮助,请告诉我!
I wrote how to do it on my blog here:
我在博客上写了如何做到这一点:
http://blog.burrowsapps.com/2013/07/how-to-compile-helloworld-in-intel-x86.html
http://blog.burrowsapps.com/2013/07/how-to-compile-helloworld-in-intel-x86.html
For a more verbose explanation, I explained on my Github here:
有关更详细的解释,我在这里向我的Github解释:
https://github.com/jaredsburrows/Assembly
https://github.com/jaredsburrows/Assembly
#4
0
The standard mac gcc won't link elf objects. For people who need to stick with the elf format and develop on a mac, you need a cross compiler...
标准mac gcc不会链接elf对象。对于需要坚持使用elf格式并在mac上开发的人来说,你需要一个交叉编译器......
http://crossgcc.rts-software.org/doku.php?id=compiling_for_linux
http://crossgcc.rts-software.org/doku.php?id=compiling_for_linux
Then you can proceed with something similar to this...
然后你可以继续进行类似的事情......
/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