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

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

相关推荐
浩浩测试一下14 小时前
汇编常用的(JCC 串 判断)指令 通用寄存器 标志寄存器 段寄存器(逆向分析)
汇编·通用寄存器·逆向二进制·标志寄存器·段寄存器·串 jcc 常用指令
浩浩测试一下1 天前
汇编 标志位寄存器 (逆向分析 )
c语言·汇编·逆向·windows编程·标志寄存器
浩浩测试一下1 天前
汇编 数组与串指令(逆向分析)
汇编·逆向·二进制·免杀·串指令·汇编数组
浩浩测试一下2 天前
汇编 内联汇编与混合编程 (逆向分析)
汇编·混合编程·windows编程·内联汇编·二进制逆向·c语言混合汇编
浩浩测试一下2 天前
汇编 结构体与宏
汇编··免杀·结构体·windows编程·逆向二进制
浩浩测试一下2 天前
汇编中的JCC指令 (逆向分析)
汇编·逆向·标志位·jcc指令·跳转指令·标志位寄存器
浩浩测试一下2 天前
汇编中的段与段寄存器(大小)段序 (逆向分析)
汇编·逆向·二进制·字节序·windows编程·内存地址排序
浩浩测试一下3 天前
汇编 call与ret 函数与堆栈 (逆向分析)
汇编·push·函数·pop·call·ret·堆栈逆向
山屿落星辰4 天前
昇腾NPU算子开发:从“手写汇编“到“搭积木“
汇编
浩浩测试一下4 天前
汇编 汇编寻址 (逆向分析)
汇编·寻址·windows编程·二进制逆向·机器码