汇编程序输出未在我的Linux机器上运行 [英] Assembler output does not run on my Linux machine
问题描述
我跟进了此页并编译以下代码
I followed up this page and compiled the following code
; 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
均不能运行.
none of the executables hp64A
and hp64B
can run.
$ ./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
如何运行这些可执行文件?
How can I run these executable files?
推荐答案
您可能对动态链接器的路径错误.
You presumably have the wrong path for the dynamic linker.
如果要制作动态可执行文件,尤其是要链接任何库时,请使用GCC .您的发行版使用正确的ld.so路径配置它,依此类推.(使用 gcc -v
查看正确的路径,和/或 ldd ./a.out
或 readelf
从以下位置打印ELF解释器路径:您系统上的有效可执行文件.)
Use GCC if you want to make a dynamic executable, especially if you want to link any libraries. Your distro configures it with the right ld.so path and so on. (Use gcc -v
to see the right path, and/or ldd ./a.out
or readelf
to print the ELF interpreter path from a working executable on your system.)
-
gcc main.o
正常链接,包括CRT启动,libc和libgcc帮助程序功能.
gcc main.o
links normally, including CRT startup, libc, and libgcc helper functions.
gcc -no-pie -nostartfiles start.o
省略了CRT(因此您可以编写 _start
).在Linux上,确实可以正常工作.glibc安排通过动态链接器挂钩调用其init函数,因此,如果您知道自己在做什么,它就可以工作.
gcc -no-pie -nostartfiles start.o
omits CRT (so you can write a _start
). On Linux this does happen to work; glibc arranges for its init functions to be called via dynamic linker hooks so if you know what you're doing it can work.
通常,如果要使用libc函数,请编写由CRT启动代码调用的 main
.
In general if you want to use libc functions, though, write a main
that's called by CRT startup code.
我在这里使用了 -no-pie
,因为您的代码使用了 mov r32,imm32
优化来将静态地址放入寄存器中;它取决于非PIE默认代码模型.(否则,请使用相对于RIP的LEA.)
I used -no-pie
here because your code uses the mov r32, imm32
optimization for putting static addresses in registers; it depends on the non-PIE default code model. (Otherwise use RIP-relative LEA).
gcc -nostdlib
省略了CRT和标准库.之后,您也可以在GCC命令行上手动添加一些库.(如果 -pie
是您的GCC的默认设置,即使没有库,这仍将成为PIE.
gcc -nostdlib
omits CRT and standard libs. You can also manually add some libraries onto the GCC command line after that. (If -pie
is the default for your GCC, this will still make a PIE even if there are no libraries. static-pie is a separate thing not on by default.)
gcc -nostdlib -static
生成普通的静态ELF可执行文件(暗含 -no-pie
),就像您从 ld中获得的一样
gcc -nostdlib -static
makes a plain static ELF executable (implying -no-pie
), like you'd get from just ld
如果您从上述任何一项中省略了 -no-pie
(除了 -static
,则除外),如果您的GCC配置了 -enable,则会获得PIE-default-pie
就像大多数发行版在过去几年中所做的那样.( 32位绝对地址x86-64 Linux?)另请参见回复:static-pie
If you omit -no-pie
from any of these (except with -static
) you get a PIE if your GCC was configured with --enable-default-pie
like most distros have done for the last couple years. (32-bit absolute addresses no longer allowed in x86-64 Linux?) See also What's the difference between "statically linked" and "not a dynamic executable" from Linux ldd? re: static-pie
在PIE可执行文件中,您还需要通过PLT或通过其GOT条目调用库函数,例如 call [printf wrt .. got]
Also in a PIE executable, you need to call library functions through the PLT or via their GOT entry, like call [printf wrt.. got]
`int 0x80`
不这样做有两个原因:
- legacy 32-bit ABI: What happens if you use the 32-bit int 0x80 Linux ABI in 64-bit code?
- Don't use a raw
_exit
system call after printing with stdio functions. If you pipe the output, stdout will be full-buffered and output will be lost whensys_exit
quits without flushing stdio buffers first. Return frommain
orcall sys_exit
.
这篇关于汇编程序输出未在我的Linux机器上运行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!