7

我需要弄乱这些架构上的堆栈,我真的是一个 n00b。我可以做的任何阅读主题/谷歌搜索的指针。我正在寻找这些架构如何从根本上不同。不仅仅是关于这个主题的维基百科文章http://en.wikipedia.org/wiki/X64

4

9 回答 9

9

在 x86 中有 8 个 32 位寄存器,在 x64 中,每个寄存器都是 64 位,并且还有 8 个。128 位 SSE 寄存器在两者中都是 128 位,但在 x86 上有 8 个,而在 x64 中有 16 个。在 x64 中也削减了一些指令。

在 x64 模式下,您仍然可以通过使用它们的 32 位名称(以“e”开头)而不是它们的 64 位名称(以“r”开头)来将寄存器用作 32 位,并且程序集大致相同。

http://en.wikipedia.org/wiki/X86#x86_registers

或者,如果您想要一些非常繁重的阅读(例如 1000 页...)

http://www.intel.com/products/processor/manuals/index.htm 我通读了几百页这些手册,学到了很多,非常好的东西。

于 2009-11-23T18:02:30.797 回答
8

这里的所有答案都提到了寄存器集中的变化,为了完整起见,我将在这里列出:

  • 所有现有的 32 位通用寄存器都扩展为 64 位(EAX扩展为RAX等等)
  • 8 个新的 64 位通用寄存器(R8通过R15
  • 8 个新的 128 位 SSE 寄存器(XMM8通过XMM15

寻址模式也有变化:

  • CS、DS、ES 和 SS 持平。也就是说,它们的基数是0x0,极限是0xffffffffffffffff。FS 和 GS 的基数可以超过 32 位。
  • GDT、LDT 和 IDT 中的描述符已更改。它们在 64 位模式下有 8 个字节
  • 一个不连续的地址空间。在 32 位模式下,线性地址空间是从0x00xfffffff。在 64 位模式下,线性地址空间从0x0to0x00007ffffffff和 from 0xffff800000000000to分离0xffffffffffffffff。基本上,地址只有 48 位,并且地址被符号扩展为 64 位。
  • 一种新的分页模式。

删除了各种说明:

  • 带编码的一字节INC指令和. 字节成为前缀。40+rw40+rd4xREX
  • 加载现在平坦的段寄存器的指令:LDS, LDS, LSS.

还有更多的差异,我可以简单地记住我的头顶。如果我能想到更多,我会添加它们。

于 2009-11-23T20:02:21.303 回答
3

我相信您链接到的维基百科文章提供了合理数量的介绍性信息。如果您对长模式差异的具体细节感兴趣,可以查阅官方参考资料之一:Intel® 64 and IA-32 Architectures Software Developer's Manuals

于 2009-11-23T17:59:48.757 回答
2

嗯,栈?你的意思是物理的(E ​​/ RSP堆栈)?如果是这样,那么我的回答是相关的:

在 x86 上,几乎每个 C 编译器都使用cdecl调用标准。我不记得它的细节,但它在编译器和操作系统之间是一致的。基本上,参数被推入堆栈(从右到左),然后将返回值放入 eax 并由调用者负责清理。

不过,在 x86-64 上,一切都搞砸了。windows 调用约定与 linux 不同(大多数非 linux 类 unix 的操作系统都保留了原始的 C 调用标准,但这会导致更多的混乱)。我不记得它们有何不同,但确实如此。在 google 中查找“不同的调用约定 x86-64”,您会找到它的详细信息。

见:http ://en.wikipedia.org/wiki/X86_calling_conventions#Microsoft_x64_calling_convention

于 2009-11-23T18:44:01.150 回答
1

对于初学者来说,指针的大小是 8 个字节而不是 4 个。

寄存器也可以保存 64 位值。

在操作系统级别也经常存在许多差异。例如,在 Windows 上,当在 64 位 Windows 操作系统上运行 32 位应用程序时,您会遇到文件系统重定向和注册表重定向 (WOW64) 等内容。

于 2009-11-23T17:59:41.817 回答
1

人们没有提到的一件事是寻址,在 32 位保护模式下,段寄存器有意义,SS DS 和 CS 可以各自处于不同的偏移量。在 64 位保护模式下是不可能发生的。唯一可以有偏移量(但没有限制)的寄存器是 FS 和 GS。这意味着在 32 位模式下 ds:[ebx] 和 cs:[ebx] 可以有不同的值,这会带来一些麻烦。但通常操作系统不会这样做。

人们在这里没有提到的另一件事是,如果您在 64 位模式下修改 32 位寄存器,它将清除上半部分,但前提是您修改了 32 位。例如 mov eax,0 将导致 rax 为 0,而 mov ax,0 不会触及上半部分。所以在查看组装时有点棘手。

至于堆栈,更多的是操作系统的问题,而不是 CPU 的问题。x64 的 Windows ABI 不同于其他所有人(linux、mac ...)使用的 ABI。您可能需要更深入地了解“调用约定”和 ABI(应用程序二进制接口)。但是,在 x64 上,RSP 需要在函数入口处对齐 16 字节,这就是为什么您经常会看到虚拟 rsp 递减的原因。这是为了确保堆栈上的 16 字节值始终对齐。但是在 CPU 级别上都是一样的,RSP 递减,push 仍然是“sp-=word_size ; ram[sp]=value”。哦,在 x64 上,RSP 没有限制,在 x32 上,您可以告诉 CPU 堆栈指针不能低于某个地址,因此堆栈访问较低地址会导致错误。

我不确定你到底在问什么。也许一个更具体的问题将允许一个更具体的答案。

于 2014-01-22T00:42:11.207 回答
0

虽然我认为这不是 x86 与 x64 的具体答案,但它可能是相关的。

在 Linux 上,在 x86 下堆栈为 4k 或 8k,而在 x64 下为 16k。

于 2009-11-23T18:31:37.073 回答
0

x86 CPU 中的所有寄存器都是 32 位的,而对于 64 位,它的 64 位 :)

如果您使用指针算术,则 sizeof() 将产生不同的结果,增量操作也会产生不同的结果。

我觉得您可以在英特尔网站上获得有关这两种架构的详细信息,甚至还可以通过 64 位处理器获得突出显示新指令的指令集。

于 2009-11-23T17:59:33.003 回答
0

除了通用寄存器现在是 64 位而不是 32 位这一事实之外,还有新的寄存器:r8、r9、r10、r11、r12、r13、r14 和 r15。有更多寄存器的事实也导致大多数编译器对函数调用使用按寄存器传递的调用约定(带有可变参数的那些除外),而在 x86 中,大多数编译器将所有参数推入堆栈。

x87 FPU 也被弃用,更喜欢 SSE。

于 2009-11-23T18:08:01.347 回答