linux – 使用GNU汇编程序在x86_64中调用printf

linux – 使用GNU汇编程序在x86_64中调用printf,第1张

概述我用AT& T语法编写了一个程序,用于GNU汇编程序: .dataformat: .ascii "%d\n" .text .global main main: mov $format, %rbx mov (%rbx), %rdi mov $1, 我用AT& T语法编写了一个程序,用于GNU汇编程序:
.dataformat:   .ascii "%d\n"              .text            .global main  main:            mov    $format,%rbx            mov    (%rbx),%rdi            mov    ,%rsi            call     printf            ret

我使用GCC来组装和链接:@H_403_5@

gcc -o main main.s @H_403_5@

我用这个命令运行它:@H_403_5@

./main@H_403_5@

当我运行程序时,我得到一个seg错误.通过使用gdb,它说找不到printf.我试过“.extern printf”,这不起作用.有人建议我应该在调用printf之前存储堆栈指针并在RET之前恢复,我该怎么做?@H_403_5@解决方法 此代码存在许多问题. linux使用的 AMD64 System V ABI调用约定需要一些东西.它要求在CALL之前堆栈至少为16字节(或32字节)对齐:

The end of the input argument area shall be aligned on a 16 (32,if __m256 is
passed on stack) byte boundary.@H_403_5@

在C运行时调用主函数之后,堆栈未对齐8,因为返回指针被CALL放在堆栈上.要重新对齐到16字节边界,您可以简单地将任何通用寄存器推入堆栈并在最后将其POP关闭.@H_403_5@

调用约定还要求AL包含用于变量参数函数的向量寄存器的数量:@H_403_5@

%al is used to indicate the number of vector arguments passed to a function requiring a variable number of arguments@H_403_5@

printf是一个可变参数函数,因此需要设置AL.在这种情况下,您不会在向量寄存器中传递任何参数,因此您可以将AL设置为0.@H_403_5@

当$format指针已经是地址时,你也取消引用它.所以这是错的:@H_403_5@

mov  $format,%rbxmov  (%rbx),%rdi

这将获取格式的地址并将其放在RBX中.然后在RBX中获取该地址的8个字节并将它们放在RDI中. RDI需要是指向字符串的指针,而不是字符本身.这两行可以替换为:@H_403_5@

lea  format(%rip),%rdi

这使用RIP相对寻址.@H_403_5@

你也应该Nul终止你的字符串.您可以在x86平台上使用.asciz,而不是使用.ascii.@H_403_5@

您的程序的工作版本可能如下所示:@H_403_5@

# global data  #    .dataformat: .asciz "%d\n".text    .global mainmain:  push %rbx  lea  format(%rip),%rdi  mov  ,%esi           # Writing to ESI zero extends to RSI.  xor %eax,%eax          # Zeroing EAX is efficIEnt way to clear AL.  call printf  pop %rbx  ret

其他建议/建议@H_403_5@

您还应该从64位linux ABI中了解到,调用约定还需要您编写的函数以保护某些寄存器.登记册清单及是否应予保留如下:@H_403_5@

@H_403_5@

任何在Preserved中说“是”的寄存器
注册列是您必须确保在您的功能中保留的列.函数main与任何其他C函数一样.@H_403_5@

如果你有你知道的字符串/数据只读,你可以用.section .rodata而不是.data将它们放在.rodata部分.@H_403_5@

在64位模式下:如果您的目标 *** 作数是32位寄存器,则cpu将在整个64位寄存器中对寄存器进行零扩展.这可以节省指令编码上的字节.@H_403_5@

您的可执行文件可能被编译为与位置无关的代码.您可能会收到类似于以下错误:@H_403_5@

relocation R_X86_64_PC32 against symbol `printf@@GliBC_2.2.5′ can not be used when making a shared object; recompile with -fPIC@H_403_5@

要修复此问题,您必须以这种方式调用外部函数printf:@H_403_5@

call printf@plt

这通过Procedure Linkage Table (PLT)调用外部库函数@H_403_5@ 总结

以上是内存溢出为你收集整理的linux – 使用GNU汇编程序在x86_64中调用printf全部内容,希望文章能够帮你解决linux – 使用GNU汇编程序在x86_64中调用printf所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/yw/1045070.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-24
下一篇 2022-05-24

发表评论

登录后才能评论

评论列表(0条)

保存