【问题标题】:Why does printf overwrite the ECX register? [duplicate]为什么 printf 会覆盖 ECX 寄存器? [复制]
【发布时间】:2023-12-26 21:15:01
【问题描述】:

我知道printf 返回EAX 中打印的字符数。为什么printf 将寄存器 ECX 更改为 0?我的代码sn-p:

push eax    
push intFormat
call printf 
add esp,8

我在 64 位 Linux 发行版上运行我的代码。

【问题讨论】:

  • 您的平台的 ABI 是什么?
  • 如果您在 Linux 上编写 32 位代码,那么 EAXECXEDX 可能会被函数破坏你打电话。如果在通话后需要它们,则需要由调用者(您)保留。请参阅CDECL calling convention。如果您在其他平台(Windows、OSX 等)上,请告诉我们。如果您使用的是 Linux,请告诉我们。
  • 我在linux64中使用nasm
  • 就目前而言,EAX 将具有来自 printf 的返回值,但函数遵循 CDECL 调用约定(C包括库)也可以破坏 ECXEDX。他们可能不会改变,但他们可能会改变,而且他们的价值观不能作为任何事情的依据。您必须使用不会被破坏的不同寄存器(如果不使用 PIC 代码,可以使用 EBX,也可以使用 ESI、EDI),或者您必须手动保留这些寄存器并在 printf 之后恢复它们跨度>
  • 看看x86 tag wiki's FAQ section。我刚刚在 FAQ 部分添加了一个调用约定条目。这将引导您了解您需要了解的详细信息。 (@MichaelPetch:理想情况下,这些常见问题解答条目将包含指向 SO 问题的链接,这些问题可以作为很好的重复目标。如果您知道要添加的任何好问题,请这样做,或者在聊天中给我留言,我会处理格式。我觉得标签wiki中有太多指向我自己的问题和答案的链接。我知道我可以搜索自己,我最终会......)

标签: linux assembly x86 nasm


【解决方案1】:

正如你所知,EAX 将具有来自 printf 的返回值,但是遵循 CDECL 调用约定(包括 C 库)的函数也可以破坏 ECX em> 和 EDX。他们可能不会改变,但他们可能会改变,而且他们的价值观不能作为任何事情的依据。您必须使用不会被破坏的不同寄存器(如果不使用 PIC 代码,EBX 可用,ESI,EDI 也可用),或者您必须手动保留这些寄存器并在 printf 之后恢复它们 – Michael佩奇

有关调用约定/ABI 的更多信息,请参阅 标签 wiki。甚至还有一个常见问题解答部分,其中包含涵盖此问题的条目。

【讨论】: