汇编基础之寄存器及汇编指令
参考链接:
http://www.cnblogs.com/technology/archive/2010/05/16/1736782.html
http://anonymalias.github.io/2017/01/09/ucontext-theory/
最近在学习协程方面的知识,在协程的一种实现方式中有一种是用汇编实现的,所以这里再把汇编知识复习一下。
寄存器
寄存器按照其用途可分为以下4类:
- 数据寄存器
- 指针及变址寄存器
- 段寄存器
- 控制寄存器
数据寄存器
数据寄存器包括4个16位的寄存器(AX,BX,CX,DX)或者8个8位的寄存器(AH,AL,BH,BL,CH,CL,DH,DL),这些寄存器都是用来暂时存放操作数,运算结果或者其他信息,但同时又具有某些专门的用途。
- AX(累加寄存器):算术运算中的主要寄存器,在乘除运算中用来指定除数和被除数,也是乘除运算后积和商的默认存储单元。,另外IO指令均使用该寄存器与IO设备传送信息
- BX(基址寄存器):指令寻址时常用作基址寄存器,存入偏移量或者偏移量的构成部分。
- CX(计数寄存器):在循环指令操作或者串处理指令中隐含计数
- DX(数据寄存器):在双字节运算中,与AX构成32位操作数,DX为高16位。在某些IO指令中,DX被用来存放端口地址
指针及变址寄存器
这些寄存器都是16位的寄存器,用来存放16为的操作数或者中间结果,但是更常见的是存放偏移量或者位移量
- SP(堆栈指针寄存器):指向栈顶的位置,与SS寄存器一起组成栈顶数据的物理地址
- BP(基址指针寄存器):系统默认其指向堆栈中的某一单元,即提供栈中该单元偏移量,加段前缀后,BP可作为非堆栈段的地址指针。一般用于识别栈帧的起始位置。
- SI(源变址寄存器):与DS联用, 指示数据段中某操作的偏移量. 在做串处理时, SI指示源操作数地址, 并有自动增量或自动减量的功能. 变址寻址时, SI与某一位移量共同构成操作数的偏移量
- DI(目的变址寄存器):与DS联用, 指示数据段中某操作数的偏移量, 或与某一位移量共同构成操作数的偏移量. 串处理操作时, DI指示附加段中目的地址, 并有自动增量或减量的功能
段寄存器
- CS(代码段):存放当前程序的指令代码
- DS(数据段):存放程序所涉及的源数据以及结果
- SS(堆栈段):以先进后出原则的数据区
- ES(附加段):辅助数据区,存放串或者其他数据
控制寄存器
- IP(指令寄存器): 存放下一条要执行的指令的偏移量
- FR(控制标志位):
- CF(进位标识位):进行加减运算时, 如果最高二进制位产生进位或错位, CF则为1, 否则为0. 程序设计中, 常用条件转移指令JC, JNC指令据此标志位实现转移
- PF(奇偶标志位):操作结果中二进制位1的个数为偶数是, PF为1, 某则为0
- AF(辅助进位标志位):运算时半字节产生进位或借位时, AF为1, 某则为0. 主要用于BCD码的调整
- ZF(零标志位):运算结果为0时, ZF为1, 否则为0
- SF(符号标志位):当运算结果的最高位为1时, SF为1, 否则为0. 最高位表示符号数的正和负
- TF(跟踪标志位):用于调试程序时进入单步方式工作. TF=1时, 每条指令执行完后产生一个内部中断, 让用户检查指令运行后寄存器, 存储器和各标志位的内容. TF=0时, CPU工作正常, 不产生内部中断
- IF(中断允许标志位):IF=1同时中断屏蔽寄存器的相应位为0, 允许系统响应可屏蔽中断, 反之, 不接收外部发出的中断请求
- DF(方向位标志位):用于控制串操作时地址指针位移方向. 当DF=1时, 指针向高地址方向移动
- OF(溢出标志位):算术运算时结果超出系统所能表示的数的范围. 溢出时, OF=1
注意:上述为16位处理其器中的寄存器的名字,在32和64位系统中,寄存器中名字有相应的变化,具体看下面(32位在前面加E,64在前面加R,64位系统的中含有16个64位的通用寄存器):
i386常用的16个寄存器
- EAX、EBX、ECX、EDX这四个寄存器,主要就是用来暂时存放计算过程中所用的操作数、结果或其它信息。
- ESP为堆栈指针寄存,它和堆栈段寄存器SS共同决定了当前的栈指针,每当执行push,pull操作时,或者因为某些原因(如中断),CPU自动将数据入栈时,就会使用该指针来找到堆栈栈顶(或栈底)的位置,然后执行压栈、出栈的操作。系统管理软件,如操作系统会根据其分配的栈空间地址来设定这两个寄存器的值。
- EBP称为基址指针寄存器,它和ESP都可以与堆栈段寄存器SS联用来确定堆栈中的某一存储单元的地址,ESP用来指示段顶的偏移地址,而EBP可作为堆栈区中的一个基地址以便访问堆栈中的信息。
- ESI(源变址寄存器)和EDI(目的变址寄存器)一般与数据段寄存器DS联用,用来确定数据段中某一存储单元的地址。这两个变址寄存器有自动增量和自动减量的功能,可以很方便地用于变址。在串处理指令中,ESI和EDI作为隐含的源变址和目的变址寄存器时,ESI和DS联用,EDI和附加段ES联用,分别达到在数据段和附加段中寻址的目的。
- EIP指令指针寄存器,它用来存放代码段中的偏移地址。在程序运行的过程中,它始终指向下一条指令的首地址。它与段寄存器CS联用确定下一条指令的物理地址。当这一地址送到存储器后,控制器可以取得下一条要执行的指令,而控制器一旦取得这条指令就马上修改EIP的内容,使它始终指向下一条指令的首地址。那些跳转指令,就是通过修改EIP的值来达到相应的目的的
- FLAGS标志寄存器,又称PSW(program status word),即程序状态寄存器。这一个是存放条件标志码、控制标志和系统标志的寄存器。
- 段寄存器:一共六个,分别是CS代码段,DS数据段,ES附加段,SS堆栈段,FS以及GS这两个还是附加段。
EFLAGS寄存器中的IF位表示是否允许中断,为1允许,否则不允许。 - TR寄存器:用来指向当前任务的TSS段
- IDTR寄存器:用来指向当前IDT(中断表述符表或者说是中断向量表),因为在保护模式下,IDT的起始地址可以在任何位置,而不仅限于地址0。
- GDT和LDT : 前者是全局描述符表,位置由GDTR寄存器确定,后者是局部描述符表,位置由LDTR寄存器确定,具体使用哪一个,取决于段选择码中的TI位。
汇编指令
汇编指令格式
汇编指令的格式如下:1[标号:] 指令助记符[[目的操作数][,源操作数]][;注释]
- 指令助记符:如MOV,ADD之类标识传送,加法。不区分大小写
- 目的操作数:作用有两个,1.参与指令操作2,暂时存储操作结果
- 源操作数:主要提供原始数据或操作对象。面向所有寻址方式
- 注释:用分号隔开
汇编指令中常见的符号:
- imme:立即数
- DST:目的操作数
- SRC:源操作数
- mem:存储器操作数
- OPR:操作数
- reg:通用寄存器
- EA:偏移地址
- Sreg:段寄存器
- Port:端口地址
- Lable:标号
汇编指令可以分成六类:
- 数据传送指令
- 算数运算指
- 逻辑运算与移位指令
- 串操作指令
- 程序控制指令
- 处理器控制指令
数据传送指令
数据传送指令
- MOV DST,SRC(传送指令):把源操作数的内容送入目的操作数
- 立即数做源操作数时,立即数的长度必须小于等于目的操作数的长度
- 操作数分别为reg,reg或reg,sreg或sreg,sreg或reg,sreg时,两者的长度必须保持一致
- 立即数不能作为目的操作数
- CS和IP寄存器不能做目的操作数,不允许用立即数为段寄存器赋值
- 不能将一个段寄存器的内容直接送到另一个段寄存器中, 可借助通用寄存器或PUSH, POP指令实现这一要求
- PUSH SRC(压栈指令): 将一个字数据压入当前栈顶, 位移量disp=-2的地址单元. 数据进栈时, 栈指针SP首先向低地址方向移动两个字节位置, 接着数据进栈, 形成新的栈顶
- POP DST(出栈指令):弹出栈顶元素, 后将栈顶指针向栈底方向移动一个字
- XCHG OPR1, OPR2(交换指令):交换指令: 将这两个操作数交换
地址传送指令
- LEA DST, SRC(装载有效指令):该指令将源操作数的偏移量OA装载到目的操作数中
- LDS DST, SRC(装载数据段指针指令):将当前数据段中的一个双字数据装入到一个通用寄存器SI(双字数据的低字)和数据段寄存器DS(双字数据的高字)中
- LES DST,SRC(装载附加段指针指令):将附加数据段中的一个32位地址数据指针(附加段指针)送到DI(低字)和ES(高字)寄存器中
标志传送指令
- LAHF(标志寄存器送AH指令): 将标志寄存器的低字节送入AH中
- SAHF(AH送标志寄存器指令): 将AH寄存器内容送标志寄存器FR的低字节
- PUSHF(标志进栈指令): 标志寄存器进栈
- POPF (标志出栈指令): 标志寄存器出栈
累加器专用传送指令
- IN AL, Port:从端口读入数据, 存放在AL中
- OUT PORT,AL:传送AL中的数据到端口
- XLAT OPR或XLAT:用于将AL中当前内容转换为一种代码
算术运算指令
加法指令
- ADD DST, SRC:DST+SRC的和存放到DST中去
- ADC DST, SRC:带进位加法指令, DST+SRC+CF
- INC DST:增1指令
减法指令
- SUB DST, RSC:DST-SRC, 存放到DST中
- SBB DST, SRC:带借位减法指令, DST-SRC-CF
- DEC DST :减1指令
- NEG DST:求补指令, 求补码
- CMP OPR1, OPR2:比较指令
乘法指令
- MUL SRC:无符号数乘指令, AL*SRC, 结果放入AX中
- IMUL SRC:有符号数乘指令, AL*SRC, 结果放入AX中
除法指令
- DIV SRC :无符号数除指令, AX/SRC, 商放入AL中, 余数放在AH中
- IDIV SRC:符号数除指令, AX/SRC, 上放入AL中, 余数放在AH中
- CBW, CWD:都是符号扩展指令. 将AL的符号扩到AX中; 将AX的符号扩到DX
逻辑运算与移位指令
逻辑运算指令
- NOT OPR:逻辑非指令
- AND OPR:逻辑与指令
- OR OPR:逻辑或指令
- XOR OPR :逻辑异或指令
移位指令:
- SHL DST, CNT:逻辑左移
- SHR DST, CNT:逻辑右移
- SAL DST, CNT:算术左移
- SAR DST, CNT:算术右移
循环移位指令
- ROL DST, CNT:循环左移
- ROR DST, CNT:循环右移
- RCL DST, CNT:带进位循环左移
- RCR DST, CNT:带进位循环右移
串操作指令
- MOVS:串传送指令
- CMPS:串比较指令
- SCAS:串扫描指令
- LODS:装入串指令
- STOS:存储串指令
控制转移指令
转移指令:
- JMP:无条件转移指令
- JX:条件转移指令(JC/JNC, JZ/JNZ, JE/JNE, JS/JNS, JO/JNO, JP/JNP…)
循环指令
- LOOP 标号:该指令执行时, 技术寄存器CXX首先减1, 然后判断CX, 若为0, 跳出循环
条件循环指令
- LOOPZ/LOOPE, LOOPNZ/LOOPNE:前者用于找到第一个不为0的事件, 后者用于找到第一个为0的事件
子程序调用指令
- CALL 子程序名:段内直接调用
- RET
中断指令
- INT N(中断类型号):软中断指令
- IRET:中断返回指令
处理器控制指令
标志处理指令:
- CLC:进位标志CF置0
- CMC:进位标志CF求反
- STC:进位标志值1
- CLD:方向标志置0
- STD:方向标志置1
- CLI:中断允许标志置0
- STI:中断允许标志置1
其他处理器控制指令:
- NOP:空操作
- HLT:停机
- WAIT:等待
- ESC:换码
- LOCK:封锁