X86 汇编/X86 架构
x86 架构
编辑x86 架构就如一数据加工厂, 内有各种大小的暂存器, 8 个通用暂存器(通用Register GPR), 6 个段暂存器, 1 个标志暂存器和一个命令指针(装了存储区地址的暂存器和存储器统称指针). 64-位 x86 有更多暂存器.
16-位通用暂存器(寄存器) (通存器 GPR)名称
编辑8个通存器:
- 累加(Accumulator) 暂存器 (AX,加存器). 用于算术运算.
- 计数(Counter) 暂存器 (CX,计存器). 用于移/环指令及循环.
- 数据(Data) 暂存器 (DX,数存器). 用于算术运算及I/O操作.
- 基(Base) 暂存器 (BX,基存器). 指向数据块的基址(段模式中存于段暂存器 DS).
- 叠(栈)(Stack) 指针 暂存器 (SP,叠存器). 指向叠顶.
- 源号(Source Index) 暂存器 (SI,源存器). 指向流操作中的源.
- 靶号(Destination Index) 暂存器 (DI,靶存器). 指向流操作中的靶.
上述8个通存器的列举顺序与他们的入叠顺序相同, 以16-位模式存取. 前缀以'E' (extended)时以32-位模式操作. 例如'EAX'是累加暂存器的32-位名. 前缀以'R'则为64-位模式, 例如'RAX'.
前4个暂存器 (AX, CX, DX 及 BX), 每个还可以高(H)低(L)字节单独存取. 例如AX=AH || AL (||拼接符), AH表AX高字节, AL表AX低字节. 字节串表示如同数字串, 左高位右低位.
这8个通存器的存取模式可总结如下表:
暂存器 | 累加器 | 计数器 | 数据 | 基 | 叠指针 | 叠基指针 | 源 | 靶 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
64-位 | RAX | RCX | RDX | RBX | RSP | RBP | RSI | RDI | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
32-位 | EAX | ECX | EDX | EBX | ESP | EBP | ESI | EDI | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
16-位 | AX | CX | DX | BX | SP | BP | SI | DI | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
8-位 | AH | AL | CH | CL | DH | DL | BH | BL |
段存器
编辑6个段存器为:
- 叠段 (SS). 指向叠.
- 码段 (CS). 指向代码.
- 数段 (DS). 指向数据.
- 余段 (ES). 指向额外数据 ('E' 表 '额外').
- F段 (FS). 指向更额外数据 ('F' 后于 'E').
- G段 (GS). 指向更额外数据 ('G' 后于 'F').
现代操作系统采用内存分页模式, 把所有段存器指向同址来禁用内存分段模式.
然而FS和GS依然用于内存分段模式, 用于线程内数据存取.
EFLAGS 标志暂存器
编辑此32-位存标器存储运算结果状态和处理器状态的双值(0或1)标志集.
这些标志位为:
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ID | VIP | VIF | AC | VM | RF |
15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0 | NT | IOPL | OF | DF | IF | TF | SF | ZF | 0 | AF | 0 | PF | 1 | CF |
名字为0与1的标志为保留位不要操作.
The different use of these flags are: | |
---|---|
0. | CF (Carry Flag) : 搬位标, 进位或借位溢出时显1,否则显0. |
2. | PF (Parity Flag): 偶1标. 运算结果最低字节有偶数个1位时显1, 否则显0. |
4. | AF (Auxiliary Carry Flag): 副搬位标. BCD码算术运算中进借位溢出, 即运算结果第三位发生进借位时显1, 否则显0. |
6. | ZF (Zero Flag): 零标. 运算结果为0时显1否则显0. |
7. | SF (Sign Flag): 号标. 显运算结果最高位. |
8. | TF (Trap Flag): 阱位. 置1启用单步调试, 清0禁用. |
9. | IF (Interrupt Enable Flag): 允截标,或中断使能标. 置1允许响应可蔽中断, 清0时禁止. |
10. | DF (Direction Flag): 方向标. 控制串操作方向. 置1时从高址向低址行进, 清0反之. |
11. | OF (Overflow Flag): 溢出标. 有号算术运算结果溢出暂存器时显1, 否则显0. |
12-13. | IOPL (I/O Privilege Level field): I/O特权级域(2 位). 表示当前程序之I/O特权级. |
14. | NT (Nested Task flag): 任务链标. 当前任务链接了前一任务时置1, 否则清0. |
16. | RF (Resume Flag): 复标. 控制处理器对除障异常的响应. |
17. | VM (Virtual-8086 Mode Flag): 幻8086模式标. 置1入幻8086模式, 清0回保护模式. |
18. | AC (Alignment Check (or access control) Flag): 对齐检查或存取控制标. 置1 使能用户模式数据存取之对齐如AM位在CR0暂存器中为1. |
19. | VIF (Virtual Interrupt Flag): 幻截标. 允截标的虚像. |
20. | VIP (Virtual Interrupt Pending flag): 幻截挂标. 置1若有截挂焉. |
21. | ID (Identification Flag): 身份标. 置1支持CPUID指令. |
命令指针
编辑若无分支完成, 命令指针存有下一指令.
命令指针只能在 call
指令完后通过叠来读取.
内存
编辑x86内存为字节编址, 即每个字节有占用一个唯一地址, 址号小的为低址, 址号大的为高址. x86 架构数据放置为小尾式, 即多字节数据在内存中放置时, 字节权位高低对应其地址高低, 即权序与址序相同. 大尾模式中权序与址序相反.
寻址(供数)模式
编辑供数模式表示操作数的提供方式. (下文中的搬, 搬的是电子信号, 实为复制)
- 暂存器供数
- (暂存器提供操作数)
mov ax, bx ; 把 bx 中的值搬入 ax
- 立即数
- (操作数由处理器产生)
mov ax, 1 ; 把数1搬入ax
又如
mov ax, 010Ch ; 把数0x010C 搬入ax
- 直接内存供数
- (变量名实为内存地址, 变量值存储于该址中)
.数
变量名 dw 0abcdh ; 变量名 = 0xabcd
.码
mov ax, [变量名] ; 把变量值搬入ax (ax=0xabcd)
- 直接内号(offset)供数
- (可用算术改变地址)
字节表名 db 12,15,16,22,..... ; 字节表名实为基址
mov al,[字节表名+2] ; 将16搬入al
mov al,字节表名[2] ; 同上
- 暂存器间接供数
- (暂存器内容为某内存地址, 所供之数乃此内存地址中的数)
mov ax,[di]
- 此模式可用的暂存器 BX, BP, SI, DI
64-位通用暂存器
编辑64-位 x86 加了8个通用暂存器, R8至R15, 并对32-位暂存器更名以表64位:
- R0 为 RAX.
- R1 为 RCX.
- R2 为 RDX.
- R3 为 RBX.
- R4 为 RSP.
- R5 为 RBP.
- R6 为 RSI.
- R7 为 RDI.
- R8,R9,R10,R11,R12,R13,R14,R15 无别名.
- R0D~R15D 为这些暂存器的低词(双字,32位). 例, R0D 为 EAX.
- R0W~R15W 为这些暂存器的低字(16位). 例, R0W 为 AX.
- R0L~R15L 为这些暂存器的低符(字节,8位). 例, R0L 为 AL.
新增了8个控制寄存器(CR8 - CR15)和8个调试寄存器(DR8 - DR15),供系统使用。
此外, 64-位 x86 CPU 还新增了 8 个128位 SSE 暂存器,达到 16 个128-位暂存器 ( XMM0~XMM15). 新的Intel 与 AMD CPU支持AVX, 在这些 CPU 中,XMM 暂存器实为256-位 暂存器 ( YMM0~YMM15)的低128位。 YMM 暂存器和 XMM 暂存器均可被AVX指令整取做并行处理.
叠(栈)
编辑叠乃后入先出(LIFO) 数据结构; 数据顺序堆入叠而反序取出. 下面的程序片段描述了调用处理任务前后的暂存器保存(入叠)与恢复(出叠). 处理器乃一加工厂, 入叠出叠可看作加工现场的清场与恢复.
mov ax, 006Ah
mov bx, F79Ah
mov cx, 1124h
push ax
AX值堆入叠内, 叠内此时值为0x006A.
push bx
BX值堆入叠内, 叠内有值0x006A 和 0xF79A.
push cx
叠内有值0x006A, 0xF79A, 和 0x1124.
call 处理任务
调用处理任务.
pop cx
搬叠顶值入CX, 0x1124; 叠内剩值0x006A 和 0xF79A.
pop bx
搬叠顶值入BX, 0xF79A; 叠内剩值 0x006A.
pop ax
搬叠顶值入AX, 0x006A; 叠空.
叠用于函数和过程之参数传递, 也在call
调用中跟踪流程, 还可用于临时存储.
CPU 运行模式
编辑实模式
编辑x86启动或复位之后进入实模式, 自该模式可进入其他模式. 很多引导程序和BIOS程序通常运行于该模式, 此模式是Intel 8086的原生模式.
保护模式
编辑x86-32和x86-64的原生模式. 此模式的众多功能之一是可以直接在保护的多任务环境中直接执行实模式程序. 此任务级模式称幻8086模式, 非处理器模式.
系统管理模式
编辑此模式给操作系统或程序提供一个透明机制去实现电源管理和系统安全等平台相关的功能.
内存组织
编辑平内存模型
编辑该模型下代码, 数据 和 栈全处于统一地址空间. 现代操作系统(如Linux, Windows)中的编程基本上是本模式. 所有32-位暂存器都可用于寻址整个空间.
分段内存模型
编辑一个程序的代码, 数据和栈可出处于不同的内存段中, 这可由分段内存模型提供. 程序采用逻辑地址存取段中的字节. 逻辑地址又称远指针, 由段选择器+偏移组成. 运行于IA-32中的程序可以用段选择器选择高达16283个内存段, 而每个段最长可达232字节. 从逻辑地址向线性地址的转换由处理器完成, 对应用程序透明. 用内存分段来隔离程序, 可提高程序和系统的可靠性.
实模式下的内存模型
编辑16-位的 Intel 8086 却用20-位地址空间. 基地址+偏移的方式用于存取此空间.
实模式中, 内存地址=基地址+偏移(通存器). 基地址=段存器x16 (或左移4位) , 此方式可存取 1 MB的空间. 因此段存器被用于内存分片, 甚至不同程序运行于不同的内存片中以实现程序的内存独立.
由于存偏移的通存器也只有16位(Intel 8086), 因此每段最大为64KB. DOS的.COM程序即运行于此模式中. 由于.COM程序含256B的程序信息, 因此只有65280B可供用户使用. 由此可见早期程序之小.