根据我所能找到的,在Linux和Windows之间有两种常见的调用约定:函数调用的参数要么加载到寄存器中,要么放在堆栈中.

例如,对于printf函数,据说Linux使用printf所需的参数加载寄存器.对于Windows上的printf,我看到这两种约定都使用了.在我的课上,他们让我们把参数放在堆栈上,但在在线代码示例中,参数放在寄存器中.

Basile Starynkevitch的This answer,让我认为Windows只使用堆栈作为参数,而Linux使用寄存器. Jester的This answer显示Windows使用printf个参数的寄存器.

接下来,我为我的类编写的一小部分代码显示,在Windows上,我一直在使用堆栈作为参数:

section .data
msg:  db "my message", 0ah, 0

section .text
_main:
        
    push   msg
    call   _printf
    add    esp, 4
  • 那么,Windows是否能够同时使用这两种调用约定呢?
  • 你怎么知道应该用哪种呢?
  • 32位和64位x86程序有区别吗?

我还看到人们可以在Windows汇编中使用printf而不使用下划线.我知道这对Linux汇编代码来说是正常的,但在Windows上,如果我不使用下划线,就会出错.Windows上的其他人似乎没有这个问题.

In the original question that Jester answers (link above), it doesn't seem as though the user asking the question uses any special NASM instruction that would allow for that, unless it is something in the linker command they're using.
C. K. Young only explains how you can use printf without an underscore if you use a certain NASM option.

  • 那么,为什么一些Windows汇编程序在不使用NASM选项的情况下可以使用printf而不使用下划线呢?

我找了很多,但没有找到任何对这些奇怪案件的解释.

推荐答案

32位x86CPU没有那么多的寄存器可用,所以最初为它们设计的大多数调用约定主要使用堆栈.

这显然不如使用寄存器快,因此,一旦64位x86CPU变得更加常见,参数就会尽可能地存储在寄存器中.

要生成完全正常工作的应用程序,您需要将代码链接到"libc";Windows的SDK中至少提供了其中的两个;还有一些独立的实现,如MinGW-W64所使用的实现;它们中的每一个都将使用您应该匹配的特定调用约定导出它们的函数,在名称中使用前导"_"通常是防止冲突调用成功链接的方法.

Linux相关问答推荐

创建守护进程时打开0,1,2描述符

如何检测文件系统是否支持权限?

AWK+向AWK导出值未传递

如何在Linux下使用正则表达式更改文件名

如何添加Linux格式的时间输出

为什么当凭证助手设置为存储 SSH 远程存储库时 git pull 不使用 .git-credentials

X86 程序集 - struct 点 - 存储/返回不正确?

可以用openmp并行化内存分配删除吗? (c++)

bind(): "无法分配请求的地址"

如何使用 shell 脚本查找具有最大上下文长度的行号?

根据文件名对目录中的文件进行 chgrp

如何从linux调度程序中屏蔽一个cpu(防止它调度线程到那个cpu上)?

如何使用 sed debug调试正则表达式?

如何分析内存使用情况?

zsh/bash 上不区分大小写的 Glob

crt1.o:在函数_start中:-Linux 中未定义对main的引用

UNIX `time` 命令对于基准测试是否足够准确?

Linux如何确定下一个PID?

如何使用cp从不同目录复制多个文件?

Linux cmd 在 jar 中搜索类文件,而不考虑 jar 路径