【发布时间】:2019-11-07 12:31:22
【问题描述】:
我跟进this页面,编译如下代码
; assembly program that calls a C function on 64-bit Linux
;
; int main(void) {
; printf(fmt, 1, msg1);
; printf(fmt, 2, msg2);
; return 0;
;
; Assemble in 64-bit: nasm -f elf64 -o hp64.o -l hp64.lst hello-printf-64.asm
;
; Link: ld hp64.o -o hp64 -lc --dynamic-linker /lib/ld-2.7.so
; or maybe ld hp64.o -o hp64 -lc --dynamic-linker /lib/ld-linux-x86-64.so.2
; (the "-lc" option is needed to resolve "printf")
;---------------------------------------
section .data
fmt db "%u %s",10,0
msg1 db "Hello",0
msg2 db "Goodbye",0
section .text
extern printf
global _start
_start:
mov edx, msg1
mov esi, 1
mov edi, fmt
mov eax, 0 ; no f.p. args
call printf
mov edx, msg2
mov esi, 2
mov edi, fmt
mov eax, 0 ; no f.p. args
call printf
mov ebx, 0 ; return value
mov eax, 1
int 0x80
通过
nasm -f elf64 -o hp64.o -l hp64.lst hello-printf-64.asm
ld hp64.o -o hp64A -lc --dynamic-linker /lib/ld-2.7.so
ld hp64.o -o hp64B -lc --dynamic-linker /lib/ld-linux-x86-64.so.2
没有一个可执行文件 hp64A 和 hp64B 可以运行。
$ ./hp64A
bash: ./hp64A: No such file or directory
$ ./hp64B
bash: ./hp64B: No such file or directory
虽然两者都是可执行文件。
$ ll
total 30
drwxrwxrwx 1 ar2015 ar2015 4096 Nov 7 23:23 ./
drwxrwxrwx 1 ar2015 ar2015 4096 Nov 7 22:46 ../
-rwxrwxrwx 1 ar2015 ar2015 928 Nov 7 22:47 hello-printf-64.asm*
-rwxrwxrwx 1 ar2015 ar2015 2960 Nov 7 23:21 hp64A*
-rwxrwxrwx 1 ar2015 ar2015 2976 Nov 7 23:21 hp64B*
-rwxrwxrwx 1 ar2015 ar2015 2448 Nov 7 23:21 hp64.lst*
-rwxrwxrwx 1 ar2015 ar2015 1104 Nov 7 23:21 hp64.o*
我的机器是
$ uname -a
Linux ar2015co 4.15.0-66-generic #75~16.04.1-Ubuntu SMP Tue Oct 1 14:01:08 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
如何运行这些可执行文件?
【问题讨论】:
-
大概你的动态链接器不在给定的位置。您应该使用
main作为入口点而不是_start和gcc进行链接。也不要使用退出系统调用,只使用ret或call exit。此外,避免在 64 位代码中使用int 0x80(尽管它适用于此处的退出系统调用)。如果你坚持,找到动态链接器的正确位置,很可能是/lib64/ld-linux-x86-64.so.2 -
我关注了
--dynamic-linker /lib64/ld-linux-x86-64.so.2并使用了gcc。两者都按照您的建议工作。 -
@Jester,在
ld和gcc之间哪个更好?看起来ld创建的文件更小了。 -
如果您使用的是 C 库,最好的选择是
gcc,因为它会做所有正确的事情。 -
100% 同意,如果您想制作动态可执行文件,请使用 GCC,特别是如果您想链接任何库。您的发行版使用正确的 ld.so 路径等对其进行配置。
gcc -nostartfiles省略 CRT(因此您可以编写_start),gcc -nostdlib省略 CRT 和标准库,但仍然可以使 PIE 可执行。
标签: linux assembly x86-64 nasm dynamic-linking