汇编程序输出未在我的Linux机器上运行 [英] Assembler output does not run on my Linux machine

查看:64
本文介绍了汇编程序输出未在我的Linux机器上运行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我跟进了页并编译以下代码

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`

不这样做有两个原因:

  1. 旧版32位ABI:
  1. legacy 32-bit ABI: What happens if you use the 32-bit int 0x80 Linux ABI in 64-bit code?
  2. 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 when sys_exit quits without flushing stdio buffers first. Return from main or call sys_exit.

这篇关于汇编程序输出未在我的Linux机器上运行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆