x64(一)

一、从 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 文件只会被当成普通文本

  • 编译时根本不会进入汇编流程

相关推荐
ThornArmor16 天前
【工具篇·番外】跨语言生态的主权回收:基于 ISA 说明书的 4-bit 双向汇编系统全线封顶
c语言·开发语言·汇编·c++·重构·架构
是星辰吖~17 天前
WIN32_线程(下)
汇编
是星辰吖~17 天前
WIN32_线程(上)
汇编
AI科技星18 天前
数术工坊 · 第四卷 橡皮泥江湖(拓扑学)【完整定稿】
c语言·开发语言·汇编·electron·概率论·拓扑学
iCxhust18 天前
C# 生成命令行程序 将hex格式烧录程序转换成bin烧录格式
开发语言·汇编·单片机·嵌入式硬件·c#·微机原理
iCxhust19 天前
C#进程管理程序
开发语言·汇编·stm32·单片机·c#·微机原理
hhcgchpspk19 天前
汇编语言传递数据和地址的误区
汇编·笔记·nasm·masm
iCxhust19 天前
MTK8088单板机制作(一)时钟电路
汇编·单片机·嵌入式硬件·微机原理·8088单板机
iCxhust19 天前
8086 汇编位测试使用方法
汇编·单片机·嵌入式硬件·微机原理·8088单板机
iCxhust19 天前
用汇编在8088单板机上创建一个进程
汇编·微机原理