x86与x64寄存器

N0va7
2025-09-06 / 0 评论 / 1 阅读 / 正在检测是否收录...
温馨提示:
本文最后更新于2025年09月06日,已超过270天没有更新,若内容或图片失效,请留言反馈。

x86和x86_64架构的区别

32位最大寻址空间

  1. x86是32位的架构,地址总线宽度为32位
  2. 理论可访问的最大寻址空间为2^32字节,约等于4GB
  3. 实际中,操作系统通常将其中一部分用于内核空间,用户态程序可用空间为2GB或者3GB
  4. 超过该限制的应用将无法在纯32位的系统中运行

但是渐渐的32位的架构不够我们的需求,所以64位就应运而生

64位最大寻址空间

  1. x86_64是64位架构,地址总线宽度为64位
  2. 理论可以访问的最大寻址空间为2^64字节,约等于16EB(Exabytes)
  3. 当前主流的CPU实际支持48位至52位的虚拟地址,即最大寻址能力在256TB至4PB之间
  4. 用户进程可使用更大内存空间,适用于虚拟化、数据库、AI等高内存应用场景

x86下的寄存器

通用寄存器

  1. EAX:累加器,用于算术和逻辑运算
  2. EBX:基址寄存器,可用于访问内存中的变量
  3. ECX:计数器,常用于循环和字符串操作
  4. EDX:数据寄存器,用于乘除法指令中作为拓展位使用
  5. ESI:源索引,用于字符串复制、数组访问等场景
  6. EDI:目的索引,与ESI搭配使用
  7. ESP:栈指针,始终指向栈顶
  8. EBP:基址指针,用于建立函数的栈帧结构

分段寄存器

  1. CS:代码段寄存器
  2. DS:数据段寄存器
  3. SS:栈段寄存器
  4. ES、FS、GS:扩展段寄存器,用于额外访问内存或线程本地存储

分段机制在实模式和保护模式下意义不同,在现代系统中多数用于兼容目的或线程本地数据访问

特殊用途寄存器

  1. EIP:指令指针寄存器,指向下一条将要执行的指令地址
  2. EFLAGS:标志寄存器,用于记录算术、逻辑操作结果状态
  3. ZF:零标志,结果是否为零
  4. CF:进位标志,是否产生进位
  5. OF:溢出标志,是否产生有符号溢出
  6. SF:符号标志,结果是否为负

子寄存器

所有32位通用寄存器都可以拆分访问其低位部分

例如:

  • AX是EAX的低16位,AH是AX的高8位,AL是AX的低8位
  • 同理BX->BH/BL,...

子寄存器常用于字节级别的数据处理,例如处理ASCII字符、I/O操作、传感器数据采集等

简单代码分析x86寄存器

#include <stdio.h>

int main() {
    int a = 10;
    int b = 20;
    int c = a + b;
    
    int arr[3] = {1, 2, 3};
    int i;
    
    for(i = 0; i < 3; i++)
        printf("arr[%d] = %d\n", i, arr[i]);
    return 0;
}
gcc -m32 -g -fno-pie -no-pie -o x86_test x86_test.c
layout regs

此时eax清空

EIP:指令指针寄存器,指向下一条将要执行的指令地址

EAX:累加器,用于算术和逻辑运算(计算结果存储在eax)

数组和i

此处ebp-0x18为基地址,eax为下标,4为数据类型int的大小

在调试的过程中可以发现每当push一个值,esp基本都会减少4,正印证了栈是从高往低增长,然后esp永远指向栈顶,ebp永远指向栈底

x86_64下的寄存器

寄存器数量扩展

除了保留所有x86兼容寄存器外,x86_64架构新增以下64位寄存器:

  • RAX、RBX、RCX、RDX、RSP、RBP、RSI、RDI
  • 新增:R8、R9、R10、R11、R12、R13、R14、R15

每个寄存器均支持64位运算,并可拆分为32位、16位、8位子寄存器访问

RIP会替代EIP,作为64位的指令指针

调用约定变化

在64位系统下,参数的传递改由寄存器优先完成

System V(Linux、macOS):

  • 参数依次放入RDI、RSI、RDX、RCX、R8、R9
    Windows x64:
  • 参数依次放入RCX、RDX、R8、R9

超过参数寄存器数量后,继续使用栈传递,返回值通常存储在RAX寄存器

兼容模式:运行32位程序

64位处理器支持在兼容模式下运行32位程序

Windows使用WOW64(Windows on Windows 64)子系统完成兼容

Linux可以安装32位动态链接库或运行在兼容模式内核下完成支持

CPU在进入兼容模式时,将只启用前32位寄存器位宽和寻址

简单代码分析x86_64寄存器

#include <stdio.h>
long add(long a, long b, long c, long d, long e, long f) {
    return a+b+c+d+e+f;
}
int main() {
    long result = add(1,2,3,4,5,6);
    printf("Result:%ld",result);
    return 0;
}

编译指令:

gcc -g x64_test.c -o x64_test

调试:

  • 在add函数中查看RDI、RSI、RDX、RCX、R8、R9的值
  • 使用layout reg或info reg可以实时查看寄存器变化

可以看到这边的x64位的程序传递参数先传递到寄存器的地位R9、R8、RCX、RDX、RSI、RDI,途中显示的r9d、r8d、ecx、edx、esi、edi都是32位的子寄存器

此外rip替代eip,一直指示着下一段要执行代码的地址

进行两两相加,值存放到RDX中

最终结果传递到RAX中

接下来就是在调用printf的时候将两个参数放入RSI和RDI了

0

评论 (0)

取消