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

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

相关推荐
xiaobuding_QAQ1 天前
51汇编仿真proteus8.15学习篇四(附源码)
汇编·单片机·学习·proteus
xiaobuding_QAQ1 天前
51汇编仿真proteus8.15学习篇三(附源码)
汇编·单片机·学习·proteus
188号安全攻城狮2 天前
【PWN】HappyNewYearCTF_2_栈上变量覆写1
linux·运维·汇编·安全·网络安全
草莓熊Lotso2 天前
Linux 进程创建与终止全解析:fork 原理 + 退出机制实战
linux·运维·服务器·开发语言·汇编·c++·人工智能
爱编码的小八嘎2 天前
汇编语言全接触-105.Natas 幽灵王病毒的分析
汇编
老鱼说AI3 天前
深入理解计算机系统1.5:抽象的重要性:操作系统与虚拟机
c语言·开发语言·汇编
猫猫的小茶馆4 天前
【Linux 驱动开发】一. 搭建开发环境
linux·汇编·arm开发·驱动开发·stm32·嵌入式硬件·mcu
猫猫的小茶馆4 天前
【Linux 驱动开发】二. linux内核模块
linux·汇编·arm开发·驱动开发·stm32·嵌入式硬件·架构
切糕师学AI5 天前
ARM 中的 SVC 监管调用(Supervisor Call)
linux·c语言·汇编·arm开发