c - 32 位和 64 位汇编程序之间的区别?

标签 c linux assembly x86 x86-64

据我所知,32 位程序使用 FLAT 内存模型,64 位也使用。使用 32 位程序只有 4GB 可以寻址,而使用 64 位(例如 rcx)可以使现代 CPU 提供的 40 到 48 个地址位饱和并寻址更多。

所以除了这个和一些 32 位处理器没有的额外控制寄存器之外,我问自己是否有可能在 linux 中完美地运行 32 位代码。

我的意思是我执行的每个 C 代码都必须是 64 位的吗?

我可以理解,由于 C 构建在堆栈帧和基指针上,将 32 位基指针插入堆栈,因此我引入了堆栈指针为 64 位的问题,并且可能会以 32 位方式访问弹出和推送操作代码。

那么在运行 64 位 Linux 内核时有什么区别,是否有可能实际运行 32 位代码?

[更新]

为了清楚地说明场景,我正在运行一个 64 位程序并将一个 ELF64 文件加载到内存映射所有内容并直接调用该方法。这个想法是动态生成 asm 代码。

最佳答案

它们之间的主要区别在于不同的调用约定。在 32 位上有几种类型:__stdcall、__fastcall、...

在 64 位 (x64) 上只有一个(在 Windows® 平台上,关于其他我不知道)并且它有一些要求,这与 32 位非常不同。 更多关于 https://future2048.blogspot.com 请注意,ARM 和 IA64 (Itanium) 也是与 x64 (Intel64/AMD64) 不同的编码

还有 8 个通用寄存器 r8..r15,还有子寄存器 r8d..r15d, r8w..r15w, r8b..r15b 对于基于 SIMD 的代码,还存在 8 个附加寄存器 xmm8..xmm15。

异常处理是基于64bit数据的;在 32 位上,它是基于代码的。因此,在 64 位上,对于展开异常,不再使用指令来构建异常框架。异常处理完全基于数据,因此不需要额外的指令来尝试/捕获。

32 位应用程序的内存限制为 2GB(或在 32 位 Win 操作系统上的应用程序上使用/LARGEADDRESSAWARE 3GB,或在 64 位 Win 操作系统上为 4GB)现在要大得多 More on https://msdn.microsoft.com/en-us/library/windows/desktop/aa366778(v=vs.85).aspx

当然,通用寄存器有 64 位宽度而不是 32 位。因此,任何整数计算都可以处理大于 0..4294967296 的 32 位限制的值。 (签名-2147483648..+2147483647)

同样读写内存用一个简单的MOV指令可以一次读写一个QWORD(64bit);在 32 位上只能写入 DWORD(32 位)。

一些说明已被删除:PUSHA + POPA 消失了。 并且现在使用INC/DEC的一种编码形式作为REX-Byte前缀编码。

关于c - 32 位和 64 位汇编程序之间的区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29538742/

相关文章:

c - 循环链表中具有相同值的节点

将 `float` 变量转换为 C 中的字符串?

C++ 自定义全局新建/删除覆盖系统库

arrays - 汇编器数组最大元素搜索

c - scanf() 将换行符留在缓冲区中

c - 我什么时候在 scanf() 中使用 "&"?

c - 如何检测 C 中的文件写入错误?

regex - Find 命令中的正则表达式

assembly - 无法在 INT 10h/AH = 0Ch 的情况下在 Y 轴上绘制像素

assembly - Windows : "undefined reference to ` print_string'"中的 NASM 汇编程序错误