汇编语言基础之一 - CPU架构和寄存器种类简介
Intel x86 架构
Pentium i-386 是一种32-bit CISC (复杂指令计算机) 处理器, 然而APLHA 是基于RISC的(精简指令计算机). 这里不讨论十六位的代码,但是原则都差不多。
处理器有许多通用寄存器。寄存器是特殊用处的存储位置,他们在微处理器自身之中。访问寄存器比访问其他种类的存储器都要快的多得多。有些寄存器是通用的,而有些是具有特殊用处的。
通用寄存器被用来存放计算用的数值,并且存储内部的计算结果。寄存器总的说来操纵的是byte, word,或者是DWORD。
标志位寄存器是仅仅用来操纵bit的寄存器。任何指令都会根据计算的结果影响到标志位寄存器。比如说,经过一个减法操作,如果结果是0,那么zero flag就会被设置,如果不是0,其值会被清掉。
汇编指令可以有0个,1个,2个操作数。操作数可以使立即数,寄存器中的值,或者是一个指向内存中某个地址的指针。大致上说,Intel汇编语言的语法如下:
Prefix Instruction [operand 1],[operand 2] ; comment
其中
Prefix | - An address label or instruction modifier | 前缀。标识地址或者操作修改符 |
Instruction | - Instruction being executed | 指令名 |
Operand 1 | - Typically the destination operand, but it can be the source operand (one argument instruction), or it can be both the source and destination operands (INC instruction) | 操作数1.一般来说,这个操作数是目的操作数。 |
Operand 2 | - Source operand for two argument instructions | 操作数2 |
所以,对于MOV EAX,[12345678]指令来说,源操作数是在地址12345678中,而目的操作数是EAX寄存器。这个指令会降存储在12345678中的值,拷贝到EAX寄存器中。
Intel CPU的寄存器
Intel386以上的处理器包含一系列的32位寄存器。i386家族的处理器被看作是non-orthogonal的,意思是寄存器和指令集不能完全互换。也就是说,有些指令只能用在特定的寄存器上。比如说,IN和OUT指令是硬件固定的只能用在累加器(EAX)寄存器上,ECX被用来做循环的计数器,EDI和ESI被用来做索引指令和字符串指令。另外的寻址模式只能被用在特定寄存器上。
i-386家族有六个通用寄存器,EAX, EBX, ECX, EDX, EDI, ESI. 每一个寄存器都是用字母E开头,代表Extended,意思是扩展到了32位,而不是十六位。
使用方式
AL | lower 8 bits of the EAX register | EAX的低八位 |
AH | high order byte of lower order word of the EAX register | EAX的高八位 |
AX | lower 16 bits of the EAX register | EAX的低十六位 |
EAX | the full 32 bits of the register | 整个EAX寄存器 |
EBX,ECX和EDX的方式一样。
注意,ESI和EDI是不能用在byte级上使用的。
寄存器的种类
通用寄存器
1. EAX被用作累加器。它是寄存器中被使用的最多的,而且用来保存许多指令的结果。通常编译过的代码只用EAX寄存器来存放返回值。
2. ECX被用作计数器。
3. EBX和EDX是通用寄存器,一般被用来做为指针来进行内存寻址,或者被用来做算术操作,逻辑操作的操作数,和保存指令的运行结果。EAX,ECX也可以像EBX和EDX这样用。
索引寄存器
EDI,ESI是专门用来indexing的通用寄存器。字符串操作使用EDI作为目的指针,ESI作为源指针。所以,如果要拷贝一块内存从一个地方到另一个,ESI应该被作为源块,EDI作为目的块。ECX应该加载需要拷贝的字节数,方向标志位(direction flag)会被设置为增加或减少,然后REP MOVS命令来拷贝字节。
栈寄存器
ESP和EBP主要是用来操纵控制站的。ESP是栈顶指针,用来指向当前栈顶的位置。EBP寄存器对于一个给定的routine(函数),被用来指向栈frame,也就是栈底。在routine(函数)的入口,EBP寄存器一般会先存储到栈上(将EBP压栈),然后设置EBP为当前栈的栈顶指针(ESP)。EBP被用来引用参数或者局部变量。局部变量的引用可以通过EBP,[EBP-4],[EBP-8]等等方式获得。参数也可以通过EBP获得,比如[EBP+8]。一般局部变量在EBP负的位移上,而函数的参数在EBP正的位移上。
注意,ESP指向的是栈中当前有值的地址,也就是说ESP指向的是栈的最顶部的有效字节。结合压栈操作来解释吧。下面表格中的操作时等效的。
push 0x1234H; ESP <- ESP – 4 ; 减小栈指针的位置
SS:[ESP] <- 0x1234H ; 将操作数拷贝到栈顶之中
下面的代码很具有参考价值
void SomeProcedure (int anArgument) { int aVariable; aVariable = anArgument; } SomeProcedure: PUSH EBP ;save original value of EBP on stack MOV EBP, ESP ;store top of stack address in EBP SUB ESP, 4 ;allocate space for aVariable on stack MOV EAX, [EBP+8] ;fetch anArgument into EAX, which is ;8 bytes below the stored top of stack MOV [EBP-4], EAX ;store EAX into aVariable, which is ;4 bytes above the stored top of stack MOV ESP, EBP ;free space allocated for aVariable POP EBP ;restore original value of EBP RET ;return to the caller
标志位寄存器
由一系列的单个bit位组成。许多指令修改这些二进制位来描述指令的结果。这些标志位可以被条件跳转jmp语句来使用。
详细的信息请看下表
Intel x86 FLAGS Register | |||
---|---|---|---|
Bit # | Abbreviation | Description | Category[1] |
FLAGS | |||
0 | CF | Carry flag | S |
1 | 1 | Reserved | |
2 | PF | Parity flag | S |
3 | 0 | Reserved | |
4 | AF | Adjust flag | S |
5 | 0 | Reserved | |
6 | ZF | Zero flag | S |
7 | SF | Sign flag | S |
8 | TF | Trap flag (single step) | X |
9 | IF | Interrupt enable flag | X |
10 | DF | Direction flag | C |
11 | OF | Overflow flag | S |
12, 13 | IOPL | I/O privilege level (286+ only) | X |
14 | NT | Nested task flag (286+ only) | X |
15 | 0 | Reserved | |
EFLAGS | |||
16 | RF | Resume flag (386+ only) | X |
17 | VM | Virtual 8086 mode flag (386+ only) | X |
18 | AC | Alignment check (486SX+ only) | X |
19 | VIF | Virtual interrupt flag (Pentium+) | X |
20 | VIP | Virtual interrupt pending (Pentium+) | X |
21 | ID | Identification (Pentium+) | X |
22 | 0 | Reserved | |
23 | 0 | Reserved | |
24 | 0 | Reserved | |
25 | 0 | Reserved | |
26 | 0 | Reserved | |
27 | 0 | Reserved | |
28 | 0 | Reserved | |
29 | 0 | Reserved | |
30 | 0 | Reserved | |
31 | 0 | Reserved | |
RFLAGS | |||
32-63 | 0 | Reserved |
表注:
S: Status flag
C: Control flag
X: System flag
特殊目的寄存器
EIP是指令指针,它指向下一条将要被执行的指令。EIP会被指令RET,RETI,JMP,CALL和INT改变。这个寄存器可能是CPU中最重要的寄存器了,因为他指导着CPU下一条该执行的指令。
段寄存器
在32位系统中,段寄存器通常不会被修改或者显式的使用。Win32使用平面内存寻址模式。这样的原因请看文章《Windows背景知识之一》中,《Windows的内存安排》一段的描述。
额外的寄存器
Intel家族中还有一些其他的寄存器,但是它们并不适用于用户态的debugging。简单列出他们如下:
Protected Mode Registers
Control Registers
Debug and Test Registers
Floating Point Unit Register Set
MMX Registers
SIMD Floating Point Registers
练习:
1. EAX寄存器主要是做什么用的?
答:EAX被用作累加器。它是寄存器中被使用的最多的,而且用来保存许多指令的结果。通常编译过的代码只用EAX寄存器来存放返回值。
2. ECX寄存器主要是做什么用的?
答:计数器
帮助记忆的小窍门
寄存器 | 全称 | 说明 |
EAX | Extended Accumulator X | 累加寄存器。A代表Accumulator |
ECX | Extended Counting X | 计数寄存器。C代表counting |
EDI | Extended Destination Indexing | 目的索引寄存器。D代表destnation,I代表Indexing |
ESI | Extended Source Indexing | 源索引寄存器。S代表Source,I代表Indexing |
ESP | Extended Stack Pointer | 栈指针寄存器。S代表Stack |
EBP | Extended (Stack) Base Pointer | 栈基指针寄存器。B代表Base |
EIP | Extended Instructions Pointer | 指令寄存器。I代表Instruction |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律