x86 64架构汇编语言

1、汇编的概念与常用寄存器

1、课程目标

  • 理解汇编语言的基本概念
  • 掌握x86/x64架构的寄存器体系
  • 理解通用寄存器的用途
  • 了解特殊寄存器的功能

2、名词解释

术语 说明
汇编语言 机器码的助记符表示
x86 32位Intel架构
x64/AMD64 64位扩展架构
寄存器 CPU内部的高速存储单元
通用寄存器 可存储任意数据的寄存器
指令指针 指向当前执行指令的寄存器(EIP/RIP)
栈指针 指向栈顶的寄存器(ESP/RSP)
基址指针 指向栈帧基址的寄存器(EBP/RBP)

3、使用工具

工具 用途
MASM 微软官方汇编器
NASM 跨平台汇编器
x64dbg Windows 64位调试器
OllyDbg Windows 32位调试器
WinDbg 内核调试器
IDA Pro 反汇编分析工具

4、技术原理

4.1、x86通用寄存器 (32位)

31            16 15     8 7      0
+----------------+--------+--------+
|                |   AH   |   AL   |  <- 8位
+----------------+--------+--------+
|                |        AX       |  <- 16位
+----------------+------------------+
|               EAX                 |  <- 32位
+-----------------------------------+

寄存器       传统用途               Windows调用约定
------      --------               ----------------
EAX         索引器/返回值           函数返回值
EBX         基址寄存器             被调用者保存
ECX         计数器                 函数参数
EDX         数据寄存器             函数参数
ESI         源索引                 被调用者保存
EDI         目标索引               被调用者保存
EBP         栈帧基址指针           被调用者保存
ESP         栈指针                 栈指针
EIP         指令指针               不可直接访问

4.2、x64寄存器扩展 (64位)

63                              32 31               0
+--------------------------------+------------------+
|                                |       EAX        |
+--------------------------------+------------------+
|                     RAX                           |  <- 64位
+--------------------------------------------------+

新增寄存器: R8, R9, R10, R11, R12, R13, R14, R15

Windows x64调用约定:
- 参数: RCX, RDX, R8, R9 (前4个)
- 返回值: RAX
- 保存: RBX, RBP, RDI, RSI, R12-R15
- 易失: RAX, RCX, RDX, R8-R11

5、代码实现

1. 查看寄存器(内联汇编)

#include <stdio.h>
#include <windows.h>

void PrintRegisters() {
    DWORD eax, ebx, ecx, edx;
    DWORD esi, edi, ebp, esp;
    
    __asm {
        mov eax, eax
        mov ebx, ebx
        mov ecx, ecx
        mov edx, edx
        mov [eax], eax
        mov [ebx], ebx
        mov [ecx], ecx
        mov [edx], edx
        mov [esi], esi
        mov [edi], edi
        mov [ebp], ebp
        mov [esp], esp
    }
    
    printf("【寄存器值】\n");
    printf("EAX = 0x%08X\n", eax);
    printf("EBX = 0x%08X\n", ebx);
    printf("ECX = 0x%08X\n", ecx);
    printf("EDX = 0x%08X\n", edx);
    printf("ESI = 0x%08X\n", esi);
    printf("EDI = 0x%08X\n", edi);
    printf("EBP = 0x%08X\n", ebp);
    printf("ESP = 0x%08X\n", esp);
}

int main() {
    printf("=== 寄存器演示 ===\n\n");
    
    // 通过GetThreadContext获取寄存器
    CONTEXT ctx = {0};
    ctx.ContextFlags = CONTEXT_ALL;
    GetThreadContext(GetCurrentThread(), &ctx);
    
    printf("【通过API获取】\n");
    #ifdef _WIN64
    printf("RAX = 0x%016llX\n", ctx.Rax);
    printf("RBX = 0x%016llX\n", ctx.Rbx);
    printf("RCX = 0x%016llX\n", ctx.Rcx);
    printf("RDX = 0x%016llX\n", ctx.Rdx);
    printf("RSP = 0x%016llX\n", ctx.Rsp);
    printf("RBP = 0x%016llX\n", ctx.Rbp);
    printf("RIP = 0x%016llX\n", ctx.Rip);
    #else
    printf("EAX = 0x%08lX\n", ctx.Eax);
    printf("EBX = 0x%08lX\n", ctx.Ebx);
    printf("ECX = 0x%08lX\n", ctx.Ecx);
    printf("EDX = 0x%08lX\n", ctx.Edx);
    printf("ESP = 0x%08lX\n", ctx.Esp);
    printf("EBP = 0x%08lX\n", ctx.Ebp);
    printf("EIP = 0x%08lX\n", ctx.Eip);
    #endif
    
    return 0;
}

2. 寄存器的子寄存器访问

; MASM语法示例
.code
main PROC
    ; RAX 的各部分
    mov rax, 0123456789ABCDEFh
    ; 现在:
    ; RAX = 0123456789ABCDEF
    ; EAX = 89ABCDEF (低32位)
    ; AX  = CDEF (低16位)
    ; AH  = CD (高8位 of AX)
    ; AL  = EF (低8位)
    
    ; 修改AL不影响AH
    mov al, 0
    ; RAX = 0123456789ABCD00
    
    ; 但修改EAX会清除高32位!
    mov eax, 12345678h
    ; RAX = 0000000012345678 (x64特性)
    
    ret
main ENDP
END

3、课后作业

3.1、作业1:寄存器记忆

背诵所有通用寄存器的名称和传统用途。

3.2、作业2:调试器观察

使用x64dbg观察计算器程序的寄存器变化。

3.3、作业3:调用约定

编写一个程序,在函数调用前后打印寄存器变化。