gpt4 book ai didi

程序集重定位被截断以适合

转载 作者:行者123 更新时间:2023-12-04 08:26:15 25 4
gpt4 key购买 nike

您好,我一直在尝试用汇编编写一个简单的 hello world 程序,并将其编译成一个 .o 文件,然后将其与标准 C 库链接以创建一个 .exe,以便我可以查看“puts”的反汇编' 在我的系统上使用 gdb -tui。我将 Cygwin 与以下实用程序版本一起使用(使用 as --version && ld --version 获取这些版本)。我正在尝试在 Windows 8 x64 上执行所有这些操作。

作为 2.25 版

ld 版本 2.25

测试.asm

在学习x86汇编的过程中,在网上看到了好几种汇编标准。我认为我在这里写的是 GAS。

.extern puts
_start:
mov $msg, %rdi
call puts
xor %rax, %rax
ret
msg:
.ascii "hello world"

汇编程序

我可以毫无问题地组装上面的文件,as 实用程序没有给我警告或任何错误,这是我调用 as 实用程序的方式。

作为 test.asm -o test.o

链接器

这是我遇到问题的地方,以下命令是我认为我应该如何将目标文件与标准 c 库链接。

ld test.o -o test.exe -lc

此命令会产生以下错误,我一直被这些错误难倒。我试图在其他帖子中和通过谷歌找到答案,但也许我遗漏了什么。

test.o:fake:(.text+0x3): relocation truncated to fit: R_X86_64_32S against `.text`
/usr/lib/libc.a(t-d000957.o):fake:(.text+0x2): undefined reference to `__imp_puts`
/usr/lib/libc.a(t-d000957.o):fake:(.text+0x2): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `__imp_puts`

最佳答案

带有一些注释的代码。您似乎通过在 RDI 中传递第一个参数来借鉴 Linux 64 位调用约定。在 Windows 上,您在 RCX 中传递第一个参数。查看64-bit calling convention适用于 Microsoft Windows。您需要使用 movabsq 将标签的 64 位地址移动到 64 位寄存器中。您还应该确保正确对齐堆栈(16 字节边界);为影子空间分配至少 32 个字节;并且我添加了一个堆栈框架。

.extern puts
.global main
.text
main:
push %rbp
mov %rsp, %rbp /* Setup stack frame */
subq $0x20, %rsp /* Allocate space for 32 bytes shadow space
no additional bytes to align stack are needed
since return address and rbp on stack maintain
16 byte alignment */
movabsq $msg, %rcx /* Loads a 64 bit register with a label's address
Windows 64-bit calling convention
passes param 1 in rcx */
call puts
xor %rax, %rax /* Return value */
mov %rbp, %rsp
pop %rbp /* Remove current stackframe */
ret

.data
msg:
.asciz "hello world" /* Remember to zero terminate the string */

使用 .s 扩展名而不是 .asm 重命名您的汇编程序文件,并使用以下方式进行汇编和链接:

gcc -o test.exe test.s

如果不将 .asm 重命名为 .s,您可能会发现 Cygwin 上的 GCC 会将您的汇编程序文件与链接描述文件混淆。


没有堆栈框架的版本

此代码与上面的代码类似,但移除了栈帧。 RBP/RSP 序言和结尾代码已在此版本中删除。我们仍然需要对齐堆栈。由于我们不再将 RBP 压入堆栈,因此我们需要在堆栈上分配 32 字节的影子空间和额外的 8 字节以将堆栈放回 16 字节对齐。这种对齐和阴影空间分配需要在我们的函数调用其他函数(如 Win32 API 和 C 库)之前完成。未能正确设置堆栈可能会导致对其他函数的调用神秘地出现段错误或出现意外行为。 64 位 Windows 调用约定在我之前在此答案开头提供的链接中涵盖了这一点。

修改后的代码:

.extern puts
.global main
.text
main:
subq $0x28, %rsp /* Allocate space for 32 bytes shadow space
Additional 8 bytes to align stack are needed
since 8 byte return address on stack no longer
makes the stack 16 byte aligned. 32+8=0x28 */
movabsq $msg, %rcx /* Loads a 64 bit register with a label's address
Windows 64-bit calling convention
passes param 1 in rcx */
call puts
xor %rax, %rax /* Return value */
addq $0x28, %rsp /* Restore stack pointer to state it was in prior
to executing this function so that `ret` won't fail */
ret

.data
msg:
.asciz "hello world" /* Remember to zero terminate the string */

关于程序集重定位被截断以适合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34521061/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com