简体   繁体   English

从气体组件链接和调用 printf

[英]Linking and calling printf from gas assembly

There are a few related questions to this which I've come across, such as Printf with gas assembly and Calling C printf from assembly but I'm hoping this is a bit different.我遇到了一些与此相关的问题,例如带有气体组件的 Printf 和Calling C printf 与组件但我希望这有点不同。

I have the following program:我有以下程序:

.section .data
format:
    .ascii "%d\n"

.section .text
.globl _start

_start:
    
    // print "55"
    mov $format, %rdi
    mov $55, %rsi
    mov $0, %eax
    call printf # how to link?

    // exit
    mov $60, %eax
    mov $0, %rdi
    syscall

Two questions related to this:与此相关的两个问题:

  • Is it possible to use only as (gas) and ld to link this to the printf function, using _start as the entry point?是否可以仅使用as (gas) 和ld将其链接到printf function,使用_start作为入口点? If so, how could that be done?如果是这样,那该怎么做?
  • If not, other than changing _start to main , what would be the gcc invocation to run things properly?如果不是,除了将_start更改为main之外,还有什么gcc调用可以正常运行?

It is possible to use ld , but not recommended: if you use libc functions, you need to initialise the C runtime.可以使用ld ,但不推荐:如果使用 libc 函数,则需要初始化 C 运行时。 That is done automatically if you let the C compiler provide _start and start your program as main .如果您让 C 编译器提供_start并将您的程序作为main启动,那将自动完成。 If you use the libc but not the C runtime initialisation code, it may seem to work, but it can also lead to strange spurious failure.如果您使用 libc 而不是 C 运行时初始化代码,它可能看起来有效,但也可能导致奇怪的虚假故障。

If you start your program from main (your second case) instead, it's as simple as doing gcc -o program program.s where program.s is your source file.如果你从main (你的第二种情况)开始你的程序,它就像做gcc -o program program.s一样简单,其中program.s是你的源文件。 On some Linux distributions you may also need to supply -no-pie as your program is not written in PIC style (don't worry about this for now).在某些 Linux 发行版上,您可能还需要提供-no-pie ,因为您的程序不是以 PIC 样式编写的(暂时不用担心)。

Note also that I recommend not mixing libc calls with raw system calls.另请注意,我建议不要将 libc 调用与原始系统调用混合使用。 Instead of doing a raw exit system call, call the C library function exit .无需执行原始退出系统调用,而是调用 C 库 function exit This lets the C runtime deinitialise itself correctly, including flushing any IO streams.这让 C 运行时可以正确地自行取消初始化,包括刷新任何 IO 流。

Now if you assemble and link your program as I said in the first paragraph, you'll notice that it might crash.现在,如果您按照我在第一段中所说的那样组装和链接您的程序,您会注意到它可能会崩溃。 This is because the stack needs to be aligned to a multiple of 16 bytes on calls to functions.这是因为在调用函数时堆栈需要与 16 字节的倍数对齐。 You can ensure this alignment by pushing a qword of data on the stack at the beginning of each of your functions (remember to pop it back off at the end).您可以通过在每个函数的开头将一个 qword 数据推送到堆栈上来确保此 alignment(请记住在最后将其弹出)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM