汇编中常用寄存器介绍

X86-32位寄存器

4个数据寄存器:EAX、EBX、ECX和EDX;
2个变址和指针寄存器:ESI和EDI;
2个指针寄存器:ESP和EBP;
1个指令指针寄存器:EIP;
6个段寄存器:ES、CS、SS、DS、FS和GS;
1个标志寄存器:EFlags。
在X86-64寄存器中,所有寄存器都是64位,相对32位的x86寄存器来说,标识符发生了变化,比如从原来的ebp变成了rbp。为了保持
兼容性,32位寄存器都可以继续使用,比如ebp寄存器,不过指向了rbp的低32位。

X86-64的64位寄存器:

16个寄存器:raX、rbx、rcX、rdX、esi、edi、rbp、rsp、r8、r9、r10、r11、r12、r13、r14、r15.
6个传参寄存器:rdi、rsi、rdx、rcX、rB、r9.

EAX (​​扩展累加器寄存器​​-Extended Accumulator Register)

核心作用包括:
​​算术运算​​:作为乘除法(MUL/DIV)的默认操作数,存储运算结果。例如,32位乘法结果的高32位存于EDX,低32位存于EAX。
​​I/O操作​​:与输入输出指令(如IN/OUT)绑定,传递端口地址和数据。
​​位宽灵活性​​:支持8位(AL/AH)、16位(AX)、32位(EAX)访问,便于处理不同尺寸数据。
存储函数返回值​​:当函数执行完毕返回时,返回值默认存放在 EAX 寄存器中(32位模式下)。

例如:C 语言函数 int add() { return 10; }编译后,MOV EAX, 10会出现在返回前。

ECX(Extended Counter Register,扩展计数寄存器)​​

1.​​循环计数器​​
​​LOOP指令依赖​​:ECX 存储循环次数,每执行一次 LOOP指令,ECX 自动减 1,直到为 0 时跳出循环。

MOV ECX, 10      ; 设置循环10次
start:; 循环体代码LOOP start   ; ECX -= 1,若 ECX ≠ 0 则跳回 start

2.字符串/数据块操作​
搭配 REP(Repeat Prefix)指令前缀处理重复操作:

​​REP MOVSB​​:复制字节串(源地址 ESI→ 目标地址 EDI,次数=ECX)。
​​REP STOSB​​:将 AL的值填充到 EDI指向的内存(长度=ECX)。

MOV ESI, source_addr ; 源地址
MOV EDI, dest_addr   ; 目标地址
MOV ECX, 100         ; 复制 100 字节
REP MOVSB            ; 按字节循环复制

在 ​​x86 架构​​下调用实例方法时,​​ECX 默认存储当前对象的引用(this)​​
在C++类的成员函数中都掩藏一个保存当前C++对象地址的this指针,成员函数中访问所属C++对象的成员变量时,都是通过ths指针
问对应C++对象的成员变量的。
在C++汇编代码中,在调用C+成员函数时会使用ECX寄存器用来传递C++对象地址,即C++对象中的this指针。
下面是C#例子

public class MyClass {public void MyMethod() { }
}
// 编译后调用过程(伪汇编):
MOV ECX, objAddress  // ECX = 对象地址
CALL MyClass.MyMethod

x64过渡​​:
现代 .NET 程序多为 64 位,参数传递主要通过 ​​RCX/RDX/R8/R9​​,ECX 已较少出现。

​​ESI(Source Index)​​ 和 ​​EDI(Destination Index)ESI​​

​​源地址指针​​ ,指向需要读取的内存数据起始地址(如字符串、数组、缓冲区),指令LODSB, MOVS, REP MOVSB。
EDI​​

MOV ESI, source_addr  ; 源地址 → ESI
MOV EDI, dest_addr    ; 目标地址 → EDI
MOV ECX, 100          ; 复制 100 字节 → ECX
REP MOVSB             ; 按字节循环复制

​​目标地址指针​​,指向需要写入的内存数据起始地址(如复制、填充操作的目标位置),指令STOSB, MOVS, REP STOSB

MOV EDI, buffer_addr  ; 待扫描内存 → EDI
MOV AL, 'A'           ; 目标字符 'A' → AL
MOV ECX, 50           ; 扫描 50 字节
REPNE SCASB           ; 扫描直到找到 'A' 或 ECX=0

这两个是变址寄存器,ESl是源地址寄存器,ED1是目的地址寄存器,主要用于内存拷贝的串操作指令中,比如memcpy的汇编实现
中。它们也可以作为通用寄存器来使用。
在 C# 中的底层表现​​:
​​1.内存复制​​(如 Buffer.BlockCopy())
若运行在 x86 环境,JIT 编译器可能生成 REP MOVSD指令(效率远超逐字节复制)。
2.字符串操作​​(如 string.Concat())
内部可能用 EDI指向新字符串内存,ESI指向原字符串,批量复制数据。

3.​​不安全代码​​(unsafe块)
固定指针操作时,fixed语句可能触发 ESI/EDI 的寄存器分配:

unsafe {fixed (byte* src = sourceArray, dest = targetArray) {// JIT 可能将 src → ESI, dest → EDIfor (int i = 0; i < count; i++) dest[i] = src[i]; // 可能被优化为 MOVSB 指令}
}

ESI/EDI 的核心价值​​:
1.​​高效内存操作​​:硬件支持自动索引,大幅减少循环指令开销。
2.​​数据流处理​​:在字符串、数组操作中显著提升性能(尤其在旧 x86 架构中)。

​​ESP(Stack Pointer)​​ 和 ​​EBP(Base Pointer)

这两者是​​管理函数调用栈的核心寄存器​​,直接关联函数的执行流程、参数传递、局部变量存储等关键操作。
函数调用时,操作系统通过​​栈(Stack)​​ 管理临时数据:

  1. ​​调用函数时​​:参数、返回地址压入栈。
  2. ​​函数执行时​​:在栈上分配局部变量,保存寄存器状态。
  3. ​​函数返回时​​:清理栈数据,恢复原始状态。
    ESP 和 EBP 正是协调这一过程的核心寄存器。

ESP(Stack Pointer)的核心作用​​

​ 指向栈顶的实时位置​​(32位模式中为32位地址),相当于栈的“读写指针”。
**压栈(PUSH)**​​:ESP​​自动减 4​​(因为栈从高地址向低地址增长),写入数据。

PUSH EAX        ; 等效于: SUB ESP, 4 + MOV [ESP], EAX

弹栈(POP)​​:ESP​​自动加 4​​,读出数据。

POP EBX         ; 等效于: MOV EBX, [ESP] + ADD ESP, 4

动态响应操作​​:

​操作​​ESP 变化地址变化
PUSH regESP -= 4栈顶向低地址移动
POP regESP += 4栈顶向高地址回退
CALL funcESP -= 4存入返回地址
RETESP += 4清理返回地址

EBP(Base Pointer)的核心作用​​

指向当前栈帧的基地址​​(固定位置),是栈内存的“锚点”,用于​​定位参数和局部变量​​。
栈帧(Stack Frame)结构​​:
在这里插入图片描述函数调用栈分布

; 函数入口(Prologue)
PUSH EBP         ; 保存调用者的EBP
MOV EBP, ESP     ; 新栈帧起点 = 当前ESP
SUB ESP, 8       ; 分配8字节局部变量空间(ESP移动); 访问参数和局部变量:
MOV EAX, [EBP + 8]   ; 获取第一个参数
MOV [EBP - 4], EAX   ; 写入第一个局部变量; 函数出口(Epilogue)
MOV ESP, EBP     ; 释放局部变量(ESP回退)
POP EBP          ; 恢复调用者的EBP
RET              ; 返回到调用者

 ​​ESP vs EBP 核心差异​​
在 C# 中的体现​​:
1.​​栈帧自动管理​​:

C# 函数中的​​参数和局部变量​​在编译后由 CLR 自动通过 ESP/EBP(或 x64 中的 RSP/RBP)管理:

void Calculate(int x) {int a = x * 2;  // 局部变量 a 在栈上分配(EBP - N)Console.WriteLine(a);
}

2.​​调试观察​​:

在 Visual Studio 中:
启用 ​​Debug → Windows → Registers​​ 查看 ESP/EBP。
使用 ​​Debug → Windows → Disassembly​​ 观察栈帧操作指令(如 MOV EBP, ESP)。
3.​​不安全代码中的直接操作​​:
在 unsafe块中可通过指针间接操作栈地址(但需谨慎!):

unsafe {int val = 10;int* p = &val;  // p 实际指向栈内存地址(EBP - 偏移)
}

EIP(Extended Instruction Pointer,扩展指令指针寄存器)

EIP寄存器是用来存放即将要执行的汇编指令地址的。这里讲的汇编地址,是代码段的地址,和我们平时说的变量占用的内存(数据
段地址)是两个概念,要注意区分一下,不要混淆。
当CPU从EIP寄存器中将汇编指令地址载入到CPU中时,EIP寄存器中的地址会自动累加,累加的值正好就是被取走的那条汇编指令
的长度,这样EP寄存器中的地址就是即将要执行的下一条汇编指令的地址了。
程序流程控制​​:
存储当前或下一条指令的内存地址(32位模式),CPU 按 EIP 指向的位置取指令执行
​​自动递增​​:
每条指令执行后,EIP ​​自动增加​​字节长度(如 MOV EAX, 1占用 5 字节 → EIP+=5)
​​跳转机制:​​
JMP、CALL、RET、中断等指令会​​主动修改 EIP​​,改变程序流向
​​只读性:​​
​​普通指令无法直接修改 EIP​​(如 MOV EIP, 0x1234是非法的),必须通过控制流指令间接修改

关键应用场景​​

  1. ​​函数调用与返回(核心流程)​​
    1.调用函数时(CALL)​​:
    当前 EIP(即返回地址)​​被压入栈​​(ESP -= 4 → [ESP] = EIP)。
    EIP被修改为​​目标函数的入口地址​​,跳转执行。
CALL 0x400000      ; 压入返回地址 → 更新 EIP=0x400000

​​函数返回时(RET)​​:
从栈顶弹出返回地址到 EIP,恢复原流程:

RET               ; POP EIP → 恢复调用点下一条指令地址

2.​​条件分支与跳转​​
​​条件跳转​​(如 JE/ JNE): 根据标志位(ZF)判断是否修改 EIP:

CMP EAX, 10       ; 比较 EAX 与 10
JE  label_equal   ; 若相等,则 EIP = label_equal 的地址

无条件跳转​​(JMP):强制修改 EIP 至目标地址:

JMP 0x5000  ; EIP = 0x5000
  1. ​​中断与异常处理​​
    发生中断/异常时:
    1.当前 EIP​​自动压栈保存​​(进入内核态)。
    2.EIP被设置为​​中断处理程序的入口地址​​(从 IDT 表中查询)。
    3.处理完成后,通过 IRET指令恢复原 EIP继续执行。

​​在 C# 中的体现
​​1.调试与反编译​​:
在 Visual Studio 调试器中:
寄存器窗口显示 ​​EIP/RIP​​,指向当前执行的指令地址。
调用栈(Call Stack)本质是​​连续压入栈的 EIP 序列​​。
反汇编窗口(Debug → Windows → Disassembly)显示的指令地址即 EIP的实时指向。
2.​​不安全代码行为​​
在 unsafe块中,指针操作错误可能导致 EIP 被意外篡改(需开启安全编译选项防御):

unsafe {int* ptr = ...;void* target = ptr + 10;// 错误操作可能使函数返回地址被覆盖
}

段寄存器(Segment Registers)

常用的段寄存器有CS、SS、DS、ES、FS和GS 。
​CS​​:​​Code Segment​​,代码段:定义当前执行的指令所在内存区域(EIP 从该段中取值)。
​​DS​​:​​Data Segment​​;数据段:默认的变量读写、内存操作区域。
​​SS​​:Stack Segment​​;栈段:存放函数调用栈(ESP/EBP 在此段内工作)。
​​ES​​:​​Extra Segment​​;附加数据段:通常用于字符串操作中的​​目标地址​​(如 REP MOVSB中的 EDI)。
​​FS​​;​​Extra Segment2​​;额外段:​​操作系统专用​​(如 Windows 存​​线程信息块 TIB​​,Linux 存​​线程局部存储 TLS​​)。
​​GS​​:​​Extra Segment 3​​;额外段:用途与 FS 类似(64位系统中更常用)。

标志寄存器(FLAGS / EFLAGS / RFLAGS)

存储 ​​CPU 状态和控制位​​的核心寄存器,直接影响程序执行流程、逻辑判断和系统行为。其每一位都表示特定的状态或控制开关(如运算是否溢出、是否允许中断)
在这里插入图片描述
16位FLAGS​​-16位基础状态标志(CF/PF/AF/ZF/SF/TF/IF/DF/OF)
32位​​EFLAGS​​-32位新增系统标志(如 IOPL、NT、ID)
64位​​RFLAGS​​-64位高32位保留未使用,仅低32位有效
在这里插入图片描述MOV AL, 0xFF ; AL = 255 (无符号) 或 -1 (有符号) ADD AL, 0x01 ; 结果 = 0x00 (256 或 0)

    ​​CF=1​​(无符号加法溢出:255+1=256 > 255)​​ZF=1​​(结果为0)​​SF=0​​(最高位0)​​OF=0​​(有符号运算无溢出:-1+1=0,结果正确)

控制标志位

标志寄存器的关键作用​​

  1. ​​条件跳转(Jcc指令依赖标志位)​​
CMP EAX, 100     ; 比较 EAX-100,自动设置 ZF/CF/OF/SF
JZ  equal_label  ; 若 ZF=1(EAX=100)则跳转
JG  above_label  ; 若 ZF=0 AND SF=OF(有符号 EAX>100)则跳转
  1. 系统行为控制​​
    ​​关中断保护关键代码​​:
CLI              ; 禁止中断(IF=0)
MOV [CriticalData], EAX  ; 安全更新共享数据
STI              ; 恢复中断(IF=1

高效字符串操作​​:

CLD              ; DF=0(正向操作)
MOV ESI, src_addr
MOV EDI, dst_addr
REP MOVSB         ; 从 ESI→EDI 按字节复制(地址自动递增)
  1. ​​程序调试​​

    调试器设置 ​​TF=1​​,每步触发 ​​INT 1​​ 中断 → 执行观察/记录。
    通过 ​​Trap Flag​​ 实现源码级单步跟踪。
    ​​在 C# 中的观察​​
    ​​1.条件分支编译结果​

if (value > 100) { ... } 
// 编译为:CMP + JG(依赖 ZF/SF/OF)

2.不安全代码的溢出检查​

checked { int x = int.MaxValue + 1; // 溢出触发 OverflowException(CPU 检测到 OF=1)
}

​​3.调试中查看标志​​
在 Visual Studio 调试器(反汇编窗口)的寄存器视图中可查看 ​​EFLAGS​​ 各标志位。

参考文章:

分析C++软件异常需要掌握的汇编知识汇总

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/92689.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/92689.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SOMGAN:用自组织映射改善GAN的模式探索能力

论文信息 论文题目:Improving mode exploring capability ofgenerative adversarial nets by self-organizing map(利用自组织映射提高生成对抗网络的模式探索能力) 期刊:Neurocomputing 摘要:生成对抗网络(GANs)的出现将生成模型的研究推向了一个新的高潮。支持这一进步…

《汇编语言:基于X86处理器》第12章 复习题和练习

本篇记录了《汇编语言&#xff1a;基于X86处理器》第12章 复习题和练习的笔记。12.6复习题和练习12.6.1 简答题1.假设有二进制浮点数1101.01101&#xff0c;如何将其表示为十进制分数之和?答&#xff1a;1101.01101(1x)(1x)(0x)(1x)(0x)(1x)(1x)(1x)(1x) 13.406252.为什么十进…

ApacheCon Asia 2025 中国开源年度报告:Apache Doris 国内第一

上周刚落下帷幕的 ApacheCon Asia 2025 中&#xff0c;一个数据让所有人都为之震撼&#xff1a;全球 Apache 基金会项目 OpenRank 排行榜中&#xff0c;Apache Doris 位居第二&#xff0c;在中国 Apache 项目中更是稳居第一。 这个排名意味着什么&#xff1f;在 Apache 基金会管…

Pytest中实现自动生成测试用例脚本代码

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快在Python的测试框架中&#xff0c;我们通常会针对某个系统进行测试用例的维护&#xff0c;在对庞大系统进行用例维护时&#xff0c;往往会发现很多测试用例是差不多…

一周学会Matplotlib3 Python 数据可视化-标注 (Annotations)

锋哥原创的Matplotlib3 Python数据可视化视频教程&#xff1a; 2026版 Matplotlib3 Python 数据可视化 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili 课程介绍 本课程讲解利用python进行数据可视化 科研绘图-Matplotlib&#xff0c;学习Matplotlib图形参数基本设置&…

安全合规1--实验:ARP欺骗、mac洪水攻击、ICMP攻击、TCP SYN Flood攻击

一、实验环境 (思科的云实验平台)攻击机&#xff1a;Kali Linux&#xff08;IP&#xff1a;192.168.234.128&#xff0c;MAC&#xff1a;00:00:29:35:64:EC&#xff09;目标1&#xff1a;网关&#xff08;IP&#xff1a;192.168.234.2&#xff0c;MAC&#xff1a;00:50:56:ED:D…

Linux下GCC的C++实现Hive到Snowflake数据迁移

程序结构 ├── main.cpp ├── config.json ├── hive_export/ ├── parquet_data/ ├── sql_scripts/ └── logs/核心代码实现 (main.cpp) #include <iostream> #include <fstream> #include <vector> #include <thread> #include <mut…

drippingblues靶机教程

一、信息搜集首先将其在VirtualBOX中安装&#xff0c;并将kali与靶机都设置为桥接模式紧接着我们扫描IP&#xff0c;来发现靶机地址&#xff0c;经过搜集&#xff0c;发现IP是192.168.1.9&#xff0c;我们去访问一下紧接着我们扫一下开放了哪些端口。发现开放了21、22以及80端口…

39.【.NET8 实战--孢子记账--从单体到微服务--转向微服务】--扩展功能--调整发布脚本

这篇文章&#xff0c;我们要调整发布脚本。之所以要调整发布脚本&#xff0c;是因为现在我们的项目有三个环境&#xff1a;本地&#xff08;Local&#xff09;、开发&#xff08;Development&#xff09;、生产&#xff08;Production&#xff09;。Tip&#xff1a;我们的项目虽…

商品、股指及ETF期权五档盘口Tick级与分钟级历史行情数据多维解析

在金融数据分析领域&#xff0c;本地CSV文件是存储高频与低频数据的常用载体。本文以期权市场数据为例&#xff0c;探讨如何基于CSV格式处理分钟级行情、高频Tick数据、日频数据、逐笔委托记录、五档订单簿及历史行情数据&#xff0c;并提供专业的技术实现方案。以下将从数据预…

云端软件工程智能代理:任务委托与自动化实践全解

云端软件工程智能代理&#xff1a;任务委托与自动化实践全解 背景与未来趋势 随着软件工程复杂度不断提升&#xff0c;开发者对自动化工具的依赖也日益增强。我们正进入一个“人机协作”的新时代&#xff0c;开发者可以专注于核心创新&#xff0c;将重复性、繁琐的任务委托给智…

making stb style lib(1): do color print in console

col.h: see origin repo // origin repo: https://github.com/resyfer/libcol #ifndef _COL_HOL_H_ #define _COL_HOL_H_#include <stdlib.h> #include <stdio.h> #include <stdbool.h> #include <string.h> #include <math.h> // 新增&#xf…

llm本地部署+web访问+交互

要实现基于llm的web访问和交互&#xff0c;需支持对llm的访问和对网络搜索的调用。 这里使用ollama llm兼容openai sdk访问&#xff1b;使用proxyless-llm-websearch模拟网络搜索。 1 ollama本地部署 假设ollama已经部署&#xff0c;具体过程参考 在mac m1基于ollama运行dee…

自动驾驶数据闭环

自动驾驶的数据闭环是支撑算法持续迭代的核心机制&#xff0c;其本质是通过“数据采集-处理-训练-部署-反馈”的循环&#xff0c;不断优化模型对复杂场景的适应性。由于自动驾驶数据量极大&#xff08;单车日均TB级&#xff09;、场景多样&#xff08;从常规道路到极端边缘场景…

二十、MySQL-DQL-条件查询

DQL-条件查询代码&#xff1a; DQL-条件查询 -- 1.查询 姓名 为 杨逍 的员工 select * from tb_emp where name 杨逍; -- 2.查询 id小于等于5 的员工信息 select * from tb_emp where id < 5; -- 3.查询 没有分配职位 的员工信息 select * from tb_emp where job is null; …

Mac下安装Conda虚拟环境管理器

Conda 是一个开源的包、环境管理器&#xff0c;可以用于在同一个机器上创建不同的虚拟环境&#xff0c;安装不同Python 版本的软件包及其依赖&#xff0c;并能够在不同的虚拟环境之间切换 Conda常通过安装Anaconda/Miniconda来进行使用。一般使用Miniconda就够了。Miniconda 是…

Android 中解决 Button 按钮背景色设置无效的问题

1、问题描述 在布局文件中有两个 Button 按钮&#xff0c;为每个按钮设置不同的背景色&#xff0c;但是显示出来的效果都是紫色的&#xff0c;跟设置的颜色不同&#xff0c;布局文件如下所示&#xff1a;<Buttonandroid:id"id/button_cancel"android:layout_width…

云服务器--阿里云OSS(2)【Springboot使用阿里云OSS】

&#x1f4d2; 阿里云 OSS Spring Boot 异步任务&#xff08;直接存 OSS&#xff09; 1. 项目结构 src/main/java/com/example/demo├── controller│ └── UploadController.java // 接收上传请求├── service│ ├── AsyncUploadService.java // 异步上传…

get请求中文字符参数乱码问题

第一种方法 服务器默认的传参编码格式是ISO8859-1,所以前端直接原样字符串请求&#xff0c;到后端解析一下就得到正确字符 String fileName request.getParameter("fileName"); fileName new String(fileName.getBytes("ISO8859-1"),"UTF-8");…

C语言(10)——结构体、联合体、枚举

关于C语言零基础学习知识&#xff0c;小编有话说&#xff0c;各位看官敬请入下面的专栏世界&#xff1a;打怪升级之路——C语言之路_ankleless的博客-CSDN博客 Hi&#xff01;冒险者&#x1f60e;&#xff0c;欢迎闯入 C 语言的奇幻异世界&#x1f30c;&#xff01; 我是 Ankle…