gpt4 book ai didi

c - 为什么在调用 printf 时会覆盖 EDX 的值?

转载 作者:太空狗 更新时间:2023-10-29 17:16:23 26 4
gpt4 key购买 nike

我写了一个简单的汇编程序:

section .data
str_out db "%d ",10,0
section .text
extern printf
extern exit
global main
main:

MOV EDX, ESP
MOV EAX, EDX
PUSH EAX
PUSH str_out
CALL printf
SUB ESP, 8 ; cleanup stack
MOV EAX, EDX
PUSH EAX
PUSH str_out
CALL printf
SUB ESP, 8 ; cleanup stack
CALL exit

我是 NASM 汇编器和 GCC,负责将目标文件链接到 linux 上的可执行文件。

本质上,该程序首先将堆栈指针的值放入寄存器 EDX,然后打印两次该寄存器的内容。但是,在第二次 printf 调用之后,打印到标准输出的值与第一次不匹配。

这种行为看起来很奇怪。当我用 EBX 替换此程序中对 EDX 的每次使用时,输出的整数与预期的相同。我只能推断 EDX 在 printf 函数调用期间的某个时刻被覆盖。

为什么会这样?以及如何确保我以后使用的寄存器不会与 C 库函数冲突?

最佳答案

根据x86 ABI , EBX, ESI, EDI, 和EBP 是callee-save 寄存器和EAXECXEDX 是调用者保存寄存器。

这意味着函数可以自由使用和销毁以前的值 EAXECXEDX。因此,如果您不想更改它们的值,请在调用函数之前保存 EAXECXEDX 的值。这就是“来电保存”的意思。

或者更好的是,将其他寄存器用于您在函数调用后仍然需要的值。在函数开始/结束时压入/弹出 EBX 比在进行函数调用的循环内压入/弹出 EDX 好得多。如果可能,对调用后不需要的临时寄存器使用调用破坏寄存器。已经在内存中的值,因此在重新读取之前不需要写入,溢出的成本也更低。


由于 EBXESIEDIEBP 是被调用者保存寄存器,函数必须恢复在返回之前,他们修改的任何值的原始值。

ESP 也是被调用者保存的,但除非您将返回地址复制到某处,否则您不能把它搞砸。

关于c - 为什么在调用 printf 时会覆盖 EDX 的值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34100466/

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