一、从 8 个到 16 个:通用寄存器数量翻倍
1.1 x86:8 个通用寄存器
cpp
EAX EBX ECX EDX
ESI EDI
EBP ESP
1.2 x64:16 个通用寄存器
x64 在保留原有寄存器的同时,引入了 R8--R15:
cpp
RAX RBX RCX RDX
RSI RDI
RBP RSP
R8 R9 R10 R11
R12 R13 R14 R15
二、寄存器宽度的变化:从 32 位到 64 位
2.1 寄存器层级关系
以 RAX 为例:
cpp
RAX (64)
└── EAX (32)
└── AX (16)
├── AH (8)
└── AL (8)
⚠️ x64 中一个极其重要的规则:
写 EAX 会自动清零 RAX 的高 32 位
cpp
mov rax,0x6666666666666666
mov eax,0x12345678
;rax = 0x12345678
2.2 新增寄存器 R8--R15 的子寄存器
x64 不只是"加寄存器",还补全了子寄存器体系。
以 R8 为例:
| 位宽 | 名称 |
|---|---|
| 64 位 | R8 |
| 32 位 | R8D |
| 16 位 | R8W |
| 8 位 | R8B |
三、64 位并不等于 64 位地址:符号位与"规范地址(Canonical Address)
x64 的通用寄存器已经全部扩展到了 64 位。
但这并不意味着:
x64 处理器真的使用了完整的 64 位虚拟地址空间
事实上,x64 的地址是"受限制的 64 位"。
3.1 Intel x64 对"虚拟地址"的基本规定
从 Intel SDM 的角度来看,x64 虚拟地址并不是完整使用 64 位。
Intel 规定:
-
0--47 位:地址有效位
-
48--63 位:符号位(Sign Extension)

3.2 Canonical Address(规范地址)
规则只有一条,但极其重要:
位 48--63 必须全部等于第 47 位
换句话说:
-
如果 bit47 = 0
👉 bit48--63 必须全是 0
-
如果 bit47 = 1
👉 bit48--63 必须全是 1
否则,该地址是 非法地址。
3.3 Windows 的进一步限制:只使用 44 位地址
在 Intel 的规范之上,Windows 又加了一层限制。
在当前主流 Windows x64 实现中:
-
实际只使用 0--43 位 作为地址
-
高位同样要求符号扩展
四 、x64 与 x86 的全局变量差异
在反汇编工具中,x64 下对全局变量的访问表面上看起来和 x86 几乎一致,
但这是一个极具迷惑性的现象。
如果只停留在反汇编层面,很容易得出错误结论:
"x64 其实也在用硬编码的绝对地址访问全局变量。"
事实恰恰相反。
4.1 一段"看起来几乎一样"的反汇编
下面是同一段 C 代码:
cpp
#include<iostream>
using namespace std;
int i = 0;
int main()
{
i = 1;
return 0;
}
x86(32 位)反汇编:
cpp
C7 05 48 7F D1 00 01 00 00 00
mov dword ptr [00D17F48h],1
x64(64 位)反汇编:
cpp
C7 05 6B A9 00 00 01 00 00 00
mov dword ptr [00007FF6ED38C170h],1
从 反汇编显示 来看:
-
两者都像是在向一个"写死的地址"写值
-
x64 甚至直接显示成了 64 位地址
4.2 x64 中的全局变量访问方式:RIP-relative
在 x64 下,同样的 C 代码,生成的汇编通常是:
cpp
mov eax, dword ptr [rip + offset]
这就是 x64 中非常核心的一种寻址方式:
RIP-relative addressing(相对于指令指针寻址)
它的真实含义是:
cpp
全局变量地址 = 下一条指令的 RIP + 偏移量
而不是一个"写死的绝对地址"。
更细节部分参考《二进制转反汇编》
六、在 VS2019 的 C/C++ 项目中编写 x64 汇编(MASM)
在 x86 时代,我们可以直接使用 __asm 内联汇编;
但在 x64 下,MSVC 已经彻底移除了内联汇编支持。
也就是说:
在 VS2019 的 x64 项目中,写汇编只能使用"独立汇编文件 + MASM"
6.1启用 MASM 支持
默认情况下,VS2019 的 C/C++ 项目并不会编译 .asm 文件,
需要手动开启 MASM。
操作步骤:
-
右键项目
-
项目 → 生成自定义
-
勾选 masm (.targets, .props)
-
点击 确定
这一步的本质是:
告诉 MSBuild:
这个项目里可能包含 MASM 汇编文件
6.2 添加汇编文件并设置为 MASM
接下来添加你的汇编文件,例如:
cpp
test.asm
然后:
-
选中 .asm 文件
-
右键 → 属性
-
配置属性 → 常规
-
项类型 → 选择
👉 Microsoft Macro Assembler
否则:
-
.asm 文件只会被当成普通文本
-
编译时根本不会进入汇编流程