x64架构与x86有何不同

时间:2022-09-06 16:37:00

I need to mess around with the stacks on these architecture and am really a n00b here. Any pointers to reading topics/google searches that i can do. I am looking for how these architectures are fundamentally different from each other. something more than the wikipedia article on this topic http://en.wikipedia.org/wiki/X64

我需要弄乱这些建筑上的堆叠,我在这里真的是一个n00b。任何指向阅读主题/谷歌搜索的指针。我正在寻找这些体系结构之间的本质区别。比*关于这个主题的文章http://en.wikipedia.org/wiki/X64更有意义

9 个解决方案

#1


9  

In x86 there are 8 32 bit registers, in x64 the registers are 64 bits each and there are 8 more of them. The 128 bit SSE registers are 128 bits in both, but on x86 there are 8 of them while in x64 there are 16 of them. Also some instructions were cut in x64.

在x86系统中,有8个32位寄存器,在x64系统中,每个寄存器都是64位寄存器,还有8个。128位SSE寄存器都是128位,但是在x86上有8个,而在x64中有16个。还有一些指令在x64中被删除。

In x64 mode you can still use the registers as 32 bits by using their 32 bit name(starting with an 'e') instead of their 64 bit name(starting with an 'r'), and the assembly would be mostly the same.

在x64模式下,您仍然可以使用寄存器作为32位,方法是使用寄存器的32位名(以'e'开头),而不是使用寄存器的64位名(以'r'开头),并且程序集基本上是相同的。

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

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

Or if you want some really heavy reading(like 1000s of pages...)

或者如果你想读一些很重的书(比如1000页…)

http://www.intel.com/products/processor/manuals/index.htm I read through a few hundred pages of those manuals and learned a lot, really good stuff.

我阅读了几百页的手册,学到了很多非常好的东西。

#2


8  

All the answers here mention the changes in the register set, which I'll list here for completeness:

这里的所有答案都提到了寄存器集中的变化,我将在这里列出,以确保完整性:

  • All existing 32-bit general purpose registers are extended to 64 bits (EAX is extended to RAX and so on)
  • 所有现有的32位通用寄存器都扩展到64位(EAX扩展到RAX等)
  • 8 new 64-bit general purpose registers (R8 through R15)
  • 8个新的64位通用寄存器(R8到R15)
  • 8 new 128-bit SSE registers (XMM8 through XMM15)
  • 8个新的128位SSE寄存器(通过XMM15实现XMM8)

There are also changes in addressing modes:

寻址模式也有变化:

  • CS, DS, ES and SS are flat. That is, their base is 0x0 and their limit is 0xffffffffffffffff. FS and GS can have a base over 32 bits.
  • CS, DS, ES和SS是平的。也就是说,它们的基数是0x0,极限是0xffffffffffffffffffffffff。FS和GS的底数可以超过32位。
  • Descriptors in the GDT, LDT and IDT have changed. They have 8 bytes in 64-bit mode
  • GDT、LDT和IDT中的描述符已经改变。它们在64位模式下有8字节
  • A non-contiguous address space. In 32-bit mode the linear address space is from 0x0 to 0xfffffff. In 64-bit mode the linear address space is split from 0x0 to 0x00007ffffffff and from 0xffff800000000000 to 0xffffffffffffffff. Basically, there are only 48 bits of address, and the address is sign-extended to 64 bits.
  • 不连续的地址空间。在32位模式下,线性地址空间是从0x0到0xfffffffff。在64位模式下,线性地址空间从0x0到0x00007ffffffffff,从0xff800000000000到0xffffffffffffffffff。基本上,只有48位地址,地址扩展为64位。
  • A new paging mode.
  • 一个新的分页模式。

Various instructions were removed:

各种指令被移除:

  • One byte INC instructions with encoding 40+rw and 40+rd. The 4x byte became the REX prefix.
  • 一个字节INC指令编码40+rw和40+rd。4x字节变成了REX前缀。
  • instructions for loading the segment registers that are now flat: LDS, LDS, LSS.
  • 加载段寄存器的说明现在是平的:LDS、LDS、LSS。

There are more differences that I simply can remember off the top of my head. I'll add them if I can think of some more.

还有更多的不同之处,我能从我的脑海中清晰地记得。如果我能想到更多,我就把它们加起来。

#3


3  

I believe the Wikipedia article you linked to provides a reasonable amount of introductory information. If you are interested in the specific details of differences in Long Mode, you can consult one of the official references: Intel® 64 and IA-32 Architectures Software Developer's Manuals.

我相信你链接到的*文章提供了相当数量的介绍性信息。如果你有兴趣长模式的差异的具体细节,你可以咨询官方引用之一:英特尔®64和ia - 32架构软件开发人员的手册。

#4


2  

Um, stack? Do you mean the physical(E/RSP stack)? If so then my answer is relevant:

嗯,堆栈?你是说物理堆栈(E/RSP堆栈)吗?如果是的话,我的回答是相关的:

On x86, almost every C compiler uses the cdecl calling standard. I can't remember the details on it, but it was consistent among compilers and operating systems. Basically, arguments is pushed to the stack(right to left) and then the return value is put in eax and the caller is responsible for cleanup.

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

On x86-64 though, its all pretty screwed up. The windows calling convention is different from linux(most non-linux unix-like OSs have kept with the original C calling standard though which leads to more screwyness). I can't remember how they differ, but they do. Look up "different calling conventions x86-64" in google and you'll find the details of it.

但在x86-64上,这一切都变得一团糟。windows调用约定与linux不同(大多数非linux类unix的OSs都保留了原始的C调用标准,但这导致了更多的屏幕截图)。我不记得他们有什么不同,但他们有。在谷歌中查找“不同的调用约定x86-64”,您将找到它的详细信息。

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

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

#5


1  

For starters the size of a pointer is 8 bytes instead of 4.

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

Registers can hold 64-bit values as well.

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

Also there are often many differences at the OS level. For example on Windows you have things like filesystem redirection and registry redirection (WOW64) when running 32-bit apps on a 64-bit Windows OS.

此外,在操作系统级别上常常有许多不同之处。例如,在Windows上,在64位Windows操作系统上运行32位应用程序时,有文件系统重定向和注册表重定向(WOW64)。

#6


1  

One thing people didn't mention is the addressing, in 32 bit protected mode the segment registers have meaning and the SS DS and CS can each be at a different offset. In 64 bit protected mode that can't happen. The only registers that can have an offset (but no limit) are FS and GS. Which means that in 32 bit mode ds:[ebx] and cs:[ebx] can have a different value which allows some nastiness. But usually OSes don't do this.

人们没有提到的一件事是寻址,在32位保护模式中,段寄存器有意义,而SS和CS可以分别处于不同的偏移位置。在64位保护模式下不会发生。唯一可以有偏移量(但没有限制)的寄存器是FS和GS。这意味着在32位模式下,ds:[ebx]和cs:[ebx]可以有一个不同的值,这允许一些不愉快。但通常OSes不会这么做。

Another thing that people didn't mention here is that if you modify a 32 bit register in 64 bit mode it will clear the upper half, but only if you modify the 32bits. e.g. mov eax,0 will result in rax being 0, whereas mov ax,0 wouldn't touch the upper half. So it's a bit tricky when looking at assembly.

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

As for the stack, it is more a question of OS than the CPU. The windows ABI for x64 is different from the one used by everyone else (linux, mac ...). You probably need to look more deeply at "calling conventions" and ABIs (application binary interface). However, on x64 the RSP needs to be 16 byte aligned at the entry to a function, which is why you'll often see dummy rsp decrements. This is to make sure 16 byte values on the stack are always aligned. But at the CPU level it's all the same, RSP decrements, push is still "sp-=word_size ; ram[sp]=value". Oh, and on x64 RSP doesn't have a limit, on x32 you can tell the CPU that the stack pointer can't go below a certain address, so stack access to lower addresses will cause a fault.

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

I'm not sure what you're asking exactly. Maybe a more specific question would permit a more specific answer.

我不确定你到底在问什么。也许一个更具体的问题可以给出一个更具体的答案。

#7


0  

All the registers in CPU of x86 are 32-bit where as for 64-Bit its 64-Bit :)

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

If you using pointer arithematic then sizeof() will yeild different results and so would an incrment operation.

如果您使用指针arithematic,那么sizeof()将会得到不同的结果,而incrment操作也是如此。

I feel you can get detailed information on intel site about the two architecutures and also even the instruction set highlighting new instructions add with 64-Bit processors.

我觉得您可以在intel站点上获得关于这两种架构的详细信息,甚至还可以获得强调使用64位处理器添加新指令的指令集。

#8


0  

In addition to the fact that the general purpose registers are now 64-bits instead of 32, there are also new registers: r8, r9, r10, r11, r12, r13, r14, and r15. The fact that there are more registers also leads to the fact that most compilers use pass-by-register calling conventions for function calls (except those with varargs), whereas in x86 most compilers push all arguments to the stack.

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

The x87 FPU is also deprecated, preferring SSE.

x87 FPU也不赞成,更喜欢SSE。

#9


0  

While I don't think this is specifically an x86 vs. x64 answer it may be relevant.

虽然我不认为这是一个特定的x86和x64的答案,但它可能是相关的。

On Linux, under x86 the stack is either 4k or 8k, while under x64 it's 16k.

在Linux下,x86下的堆栈要么是4k要么是8k,而在x64下是16k。

#1


9  

In x86 there are 8 32 bit registers, in x64 the registers are 64 bits each and there are 8 more of them. The 128 bit SSE registers are 128 bits in both, but on x86 there are 8 of them while in x64 there are 16 of them. Also some instructions were cut in x64.

在x86系统中,有8个32位寄存器,在x64系统中,每个寄存器都是64位寄存器,还有8个。128位SSE寄存器都是128位,但是在x86上有8个,而在x64中有16个。还有一些指令在x64中被删除。

In x64 mode you can still use the registers as 32 bits by using their 32 bit name(starting with an 'e') instead of their 64 bit name(starting with an 'r'), and the assembly would be mostly the same.

在x64模式下,您仍然可以使用寄存器作为32位,方法是使用寄存器的32位名(以'e'开头),而不是使用寄存器的64位名(以'r'开头),并且程序集基本上是相同的。

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

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

Or if you want some really heavy reading(like 1000s of pages...)

或者如果你想读一些很重的书(比如1000页…)

http://www.intel.com/products/processor/manuals/index.htm I read through a few hundred pages of those manuals and learned a lot, really good stuff.

我阅读了几百页的手册,学到了很多非常好的东西。

#2


8  

All the answers here mention the changes in the register set, which I'll list here for completeness:

这里的所有答案都提到了寄存器集中的变化,我将在这里列出,以确保完整性:

  • All existing 32-bit general purpose registers are extended to 64 bits (EAX is extended to RAX and so on)
  • 所有现有的32位通用寄存器都扩展到64位(EAX扩展到RAX等)
  • 8 new 64-bit general purpose registers (R8 through R15)
  • 8个新的64位通用寄存器(R8到R15)
  • 8 new 128-bit SSE registers (XMM8 through XMM15)
  • 8个新的128位SSE寄存器(通过XMM15实现XMM8)

There are also changes in addressing modes:

寻址模式也有变化:

  • CS, DS, ES and SS are flat. That is, their base is 0x0 and their limit is 0xffffffffffffffff. FS and GS can have a base over 32 bits.
  • CS, DS, ES和SS是平的。也就是说,它们的基数是0x0,极限是0xffffffffffffffffffffffff。FS和GS的底数可以超过32位。
  • Descriptors in the GDT, LDT and IDT have changed. They have 8 bytes in 64-bit mode
  • GDT、LDT和IDT中的描述符已经改变。它们在64位模式下有8字节
  • A non-contiguous address space. In 32-bit mode the linear address space is from 0x0 to 0xfffffff. In 64-bit mode the linear address space is split from 0x0 to 0x00007ffffffff and from 0xffff800000000000 to 0xffffffffffffffff. Basically, there are only 48 bits of address, and the address is sign-extended to 64 bits.
  • 不连续的地址空间。在32位模式下,线性地址空间是从0x0到0xfffffffff。在64位模式下,线性地址空间从0x0到0x00007ffffffffff,从0xff800000000000到0xffffffffffffffffff。基本上,只有48位地址,地址扩展为64位。
  • A new paging mode.
  • 一个新的分页模式。

Various instructions were removed:

各种指令被移除:

  • One byte INC instructions with encoding 40+rw and 40+rd. The 4x byte became the REX prefix.
  • 一个字节INC指令编码40+rw和40+rd。4x字节变成了REX前缀。
  • instructions for loading the segment registers that are now flat: LDS, LDS, LSS.
  • 加载段寄存器的说明现在是平的:LDS、LDS、LSS。

There are more differences that I simply can remember off the top of my head. I'll add them if I can think of some more.

还有更多的不同之处,我能从我的脑海中清晰地记得。如果我能想到更多,我就把它们加起来。

#3


3  

I believe the Wikipedia article you linked to provides a reasonable amount of introductory information. If you are interested in the specific details of differences in Long Mode, you can consult one of the official references: Intel® 64 and IA-32 Architectures Software Developer's Manuals.

我相信你链接到的*文章提供了相当数量的介绍性信息。如果你有兴趣长模式的差异的具体细节,你可以咨询官方引用之一:英特尔®64和ia - 32架构软件开发人员的手册。

#4


2  

Um, stack? Do you mean the physical(E/RSP stack)? If so then my answer is relevant:

嗯,堆栈?你是说物理堆栈(E/RSP堆栈)吗?如果是的话,我的回答是相关的:

On x86, almost every C compiler uses the cdecl calling standard. I can't remember the details on it, but it was consistent among compilers and operating systems. Basically, arguments is pushed to the stack(right to left) and then the return value is put in eax and the caller is responsible for cleanup.

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

On x86-64 though, its all pretty screwed up. The windows calling convention is different from linux(most non-linux unix-like OSs have kept with the original C calling standard though which leads to more screwyness). I can't remember how they differ, but they do. Look up "different calling conventions x86-64" in google and you'll find the details of it.

但在x86-64上,这一切都变得一团糟。windows调用约定与linux不同(大多数非linux类unix的OSs都保留了原始的C调用标准,但这导致了更多的屏幕截图)。我不记得他们有什么不同,但他们有。在谷歌中查找“不同的调用约定x86-64”,您将找到它的详细信息。

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

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

#5


1  

For starters the size of a pointer is 8 bytes instead of 4.

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

Registers can hold 64-bit values as well.

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

Also there are often many differences at the OS level. For example on Windows you have things like filesystem redirection and registry redirection (WOW64) when running 32-bit apps on a 64-bit Windows OS.

此外,在操作系统级别上常常有许多不同之处。例如,在Windows上,在64位Windows操作系统上运行32位应用程序时,有文件系统重定向和注册表重定向(WOW64)。

#6


1  

One thing people didn't mention is the addressing, in 32 bit protected mode the segment registers have meaning and the SS DS and CS can each be at a different offset. In 64 bit protected mode that can't happen. The only registers that can have an offset (but no limit) are FS and GS. Which means that in 32 bit mode ds:[ebx] and cs:[ebx] can have a different value which allows some nastiness. But usually OSes don't do this.

人们没有提到的一件事是寻址,在32位保护模式中,段寄存器有意义,而SS和CS可以分别处于不同的偏移位置。在64位保护模式下不会发生。唯一可以有偏移量(但没有限制)的寄存器是FS和GS。这意味着在32位模式下,ds:[ebx]和cs:[ebx]可以有一个不同的值,这允许一些不愉快。但通常OSes不会这么做。

Another thing that people didn't mention here is that if you modify a 32 bit register in 64 bit mode it will clear the upper half, but only if you modify the 32bits. e.g. mov eax,0 will result in rax being 0, whereas mov ax,0 wouldn't touch the upper half. So it's a bit tricky when looking at assembly.

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

As for the stack, it is more a question of OS than the CPU. The windows ABI for x64 is different from the one used by everyone else (linux, mac ...). You probably need to look more deeply at "calling conventions" and ABIs (application binary interface). However, on x64 the RSP needs to be 16 byte aligned at the entry to a function, which is why you'll often see dummy rsp decrements. This is to make sure 16 byte values on the stack are always aligned. But at the CPU level it's all the same, RSP decrements, push is still "sp-=word_size ; ram[sp]=value". Oh, and on x64 RSP doesn't have a limit, on x32 you can tell the CPU that the stack pointer can't go below a certain address, so stack access to lower addresses will cause a fault.

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

I'm not sure what you're asking exactly. Maybe a more specific question would permit a more specific answer.

我不确定你到底在问什么。也许一个更具体的问题可以给出一个更具体的答案。

#7


0  

All the registers in CPU of x86 are 32-bit where as for 64-Bit its 64-Bit :)

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

If you using pointer arithematic then sizeof() will yeild different results and so would an incrment operation.

如果您使用指针arithematic,那么sizeof()将会得到不同的结果,而incrment操作也是如此。

I feel you can get detailed information on intel site about the two architecutures and also even the instruction set highlighting new instructions add with 64-Bit processors.

我觉得您可以在intel站点上获得关于这两种架构的详细信息,甚至还可以获得强调使用64位处理器添加新指令的指令集。

#8


0  

In addition to the fact that the general purpose registers are now 64-bits instead of 32, there are also new registers: r8, r9, r10, r11, r12, r13, r14, and r15. The fact that there are more registers also leads to the fact that most compilers use pass-by-register calling conventions for function calls (except those with varargs), whereas in x86 most compilers push all arguments to the stack.

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

The x87 FPU is also deprecated, preferring SSE.

x87 FPU也不赞成,更喜欢SSE。

#9


0  

While I don't think this is specifically an x86 vs. x64 answer it may be relevant.

虽然我不认为这是一个特定的x86和x64的答案,但它可能是相关的。

On Linux, under x86 the stack is either 4k or 8k, while under x64 it's 16k.

在Linux下,x86下的堆栈要么是4k要么是8k,而在x64下是16k。