汇编程序输出未在我的Linux机器上运行

我跟踪了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,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

可执行文件hp64Ahp64B均无法运行。

$ ./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

如何运行这些可执行文件?

yj9981n 回答:汇编程序输出未在我的Linux机器上运行

您可能对动态链接器的路径错误。

如果要制作动态可执行文件,尤其是要链接任何库时,请使用GCC 。您的发行版使用正确的ld.so路径配置它,依此类推。 (使用gcc -v查看正确的路径,和/或ldd ./a.outreadelf从系统上运行的可执行文件中打印ELF解释器路径。)

  • gcc main.o正常链接,包括CRT启动,libc和libgcc帮助器功能。
  • gcc -no-pie -nostartfiles start.o省略了CRT(因此您可以编写_start)。在Linux上,这确实起作用。 glibc安排通过动态链接器挂钩调用其init函数,因此,如果您知道自己在做什么,它就可以工作。

    但是,通常,如果您想使用libc函数,请编写一个main,它由CRT启动代码调用。

    我在这里使用-no-pie是因为您的代码使用mov r32,imm32优化来将静态地址放入寄存器;它取决于非PIE默认代码模型。 (否则,请使用相对于RIP的LEA。)

  • gcc -nostdlib -no-pie省略了CRT和标准库,但仍可以使PIE动态执行。之后,您还可以在GCC命令行上手动添加一些库。
  • gcc -nostdlib -static生成一个普通的静态ELF可执行文件(暗含-no-pie),就像您仅从ld获得

如果您从-no-pie中省略了-static(除非--enable-default-pie),并且您的GCC已配置为call [printf wrt.. got],就像过去的大多数发行版一样,您将获得PIE。 (32-bit absolute addresses no longer allowed in x86-64 Linux?

在PIE可执行文件中,您还需要call library functions through the PLT or via their GOT entry,例如`int 0x80`


_exit

不这样做有两个原因:

  1. 旧版32位ABI:What happens if you use the 32-bit int 0x80 Linux ABI in 64-bit code?
  2. 在使用stdio函数进行打印后,请勿使用原始的sys_exit系统调用。如果通过管道传输输出,则stdout将被全缓冲,并且当{{1退出而无需先刷新stdio缓冲区。从maincall sys_exit返回。
本文链接:https://www.f2er.com/3144852.html

大家都在问