终于把寄存器方面的初步整理完,可惜由于这是我学习时的比较古老的x86系列,好多都是16位/32位,现在的电脑标配基本都是64位,其中有好多新的东西,arm64位、AT&T和86系列的汇编指令集可能有很多差异,但是还是从最早的开始温习吧,后面再逐个整理分析差异,温故知新。
如MOV, SUB这些词分别表示传送, 减法. 汇编源程序时, 系统使用内部对照表将每条指令的助记符翻译成对应的机器码
>>>> 目的操作数
目的操作数一共有两个作用
1. 参与指令操作
2. 暂时储存操作结果
>>>> 源操作数
源操作数主要提供原始数据或操作对象, 面向所有寻址方式. 例如, 在指令SUB AX, BX 中 的值作为减数提供给指令SUB
>>>> 操作符
dup:表示定义重复的数据,和db、dw、dd配合使用,db 3 dup('A')相当于db 'AAA'。
>>>> 注释
这是对源程序的说明, 在汇编中用 ; 号, 后面的内容将被注释
介绍指令前, 先熟悉下这些在指令中的符号(必须要记得)
>>>> imme: 立即数
>>>> DST: 目的操作数
>>>> SRC: 源操作数
>>>> mem: 存储器操作数
>>>> OPR: 操作数
>>>> reg: 通用寄存器
>>>> EA: 偏移地址(偏移量)
>>>> Sreg: 段寄存器
>>>> Port: 端口地址
>>>> Label: 标号
指令集不外乎下面几种:
1. 数据传送指令
2. 算术运算指令
3. 逻辑运算与移位指令【整型 与 浮点型的处理】
4. 串操作指令
5. 程序控制指令
6. 处理器控制指令
7. 伪指令
1. 通用数据传送指令.
l MOV DST, SRC ;传送指令: 把源操作数的内容送入目的操作数 传送字或字节. 注意:
1. 立即数做源操作数时, 立即数的长度必须小于等于目的操作数的长度
2. 操作数DST, SRC分别为reg, reg或reg, Sreg或Sreg, reg时, 两者的长度必须保持一致
3. CS和IP寄存器不能做DST操作数, 不允许用立即数直接为段寄存器赋值
4. 立即数不能作为目的操作数
5. 不能将一个段寄存器的内容直接送到另一个段寄存器中, 可借助通用寄存器或PUSH, POP指令实现这一要求
l MOVSX 先符号扩展,再传送.
l MOVZX 先零扩展,再传送.
l PUSH 把字压入堆栈.
l POP 把字弹出堆栈.
l PUSHA 把AX,CX,DX,BX,SP,BP,SI,DI依次压入堆栈.
l POPA 把DI,SI,BP,SP,BX,DX,CX,AX依次弹出堆栈.
l PUSHAD 把EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI依次压入堆栈.
l POPAD 把EDI,ESI,EBP,ESP,EBX,EDX,ECX,EAX依次弹出堆栈.
l BSWAP 交换32位寄存器里字节的顺序
l XCHG 交换字或字节.( 至少有一个操作数为寄存器,段寄存器不可作为操作数)
l CMPXCHG 比较并交换操作数.( 第二个操作数必须为累加器AL/AX/EAX )
l XADD 先交换再累加.( 结果在第一个操作数里 )
l XLAT 字节查表转换.
── BX 指向一张 256 字节的表的起点, AL 为表的索引值 (0-255,即 0-FFH); 返回 AL
为查表结果. ( [BX+AL]->AL )
2. 输入输出端口传送指令.
l IN I/O端口输入. ( 语法: IN 累加器, {端口号│DX} )
l OUT I/O端口输出. ( 语法: OUT {端口号│DX},累加器 )
输入输出端口由立即方式指定时, 其范围是 0-255; 由寄存器 DX 指定时,
其范围是 0-65535.
----------------------- 目的地址传送指令-----------------------
l LEA 装入有效地址.
例: LEA DX,string ;把偏移地址存到DX.
l LDS 传送目标指针,把指针内容装入DS.
例: LDS SI,string ;把段地址:偏移地址存到DS:SI.
l LES 传送目标指针,把指针内容装入ES.
例: LES DI,string ;把段地址:偏移地址存到ES:DI.
l LFS 传送目标指针,把指针内容装入FS.
例: LFS DI,string ;把段地址:偏移地址存到FS:DI.
l LGS 传送目标指针,把指针内容装入GS.
例: LGS DI,string ;把段地址:偏移地址存到GS:DI.
l LSS 传送目标指针,把指针内容装入SS.
例: LSS DI,string ;把段地址:偏移地址存到SS:DI
加减乘除四种基本操作运算,复杂的是牵涉到 8位、16位、32位的运算【可能牵涉到的标志位为 进位标志、溢出标志】,总体原则是对应的被操作寄存器的位数不能超过最终结果存储器【AL、AX、EAX】的位数。
加法指令
l ADD DST, SRC ;DST+SRC的和存放到DST中去
l ADC DST, SRC ;带进位加法指令, DST+SRC+CF
l INC DPTR 数据指针寄存器值加1 (说明:将16位的DPTR加1,当DPTR的低字节(DPL)从FFH溢出至00H时,会使高字节(DPH)加1,不影响任何标志位)
减法指令
l SUB DST, RSC ;DST-SRC, 存放到DST中
l SBB DST, SRC ;带借位减法指令, DST-SRC-CF
l DEC ;减1指令
l NEG DST ;求补指令, 求补码 ;求反然后加1,假如NEG AL相当于Not AL; INC AL
l NEC 求反(以0减之).
l CMP 比较.(两操作数作减法,仅修改标志位,不回送结果).
乘法指令
l MUL DST, SRC ;无符号数乘指令 将累加器的值与SRC寄存器的值相乘,乘积的低位字节存回累加器,高位字节存回SRC寄存器(说明:将累加器DST和寄存器SRC内的无符号整数相乘,产生16位的积,低位字节存入DST,高位字节存入SRC寄存器.如果积大于FFH,则溢出标志位(O)被设定为1,而进位标志位CF为0)
l IMUL DST, SRC ;有符号数【整数】 以上两条,结果回送AH和AL(字节运算),或DX和AX(字运算)
除法指令
l DIV A B 将累加器的值除以B寄存器的值,结果的商存回累加器,余数存回B寄存器(说明:无符号的除法运算,
将累加器A除以B寄存器的值,商存入A,余数存入B。执行本指令后,进位位(C)及溢出位(OV)被清除为0)
l IDIV 整数除法. 以上两条,结果回送: 商回送AL,余数回送AH, (字节运算); 或 商回送AX,余数回送DX, (字运算).
AAA 加法的ASCII码调整.
DAA 加法的十进制调整.
AAS 减法的ASCII码调整.
DAS 减法的十进制调整.
AAM 乘法的ASCII码调整.
AAD 除法的ASCII码调整.
CBW 字节转换为字. (把AL中字节的符号扩展到AH中去)
CWD 字转换为双字. (把AX中的字的符号扩展到DX中去)
CWDE 字转换为双字. (把AX中的字符号扩展到EAX中去)
CDQ 双字扩展. (把EAX中的字的符号扩展到EDX中去)
逻辑运算指令:
l NOT OPR ;逻辑非指令
l AND OPR ;逻辑与指令
l OR OPR ;逻辑或指令
l XOR OPR ;逻辑异或指令
TEST 测试.(两操作数作与运算,仅修改标志位,不回送结果).
移位指令:
l SHL DST, CNT ;逻辑左移
l SHR DST, CNT ;逻辑右移
l SAL DST, CNT ;算术左移
l SAR DST, CNT ;算术右移(左移一样右移不同.逻辑右移补0,算术右移补最高位)
循环移位指令:
l ROL DST, CNT ;循环左移
l ROR DST, CNT ;循环右移
l RCL DST, CNT ;带进位循环左移
l RCR DST, CNT ;带进位循环右移
以上八种移位指令,其移位次数可达255次.
移位一次时, 可直接用操作码. 如 SHL AX,1.
移位>1次时, 则由寄存器CL给出移位次数.
如 MOV CL,04 ; SHL AX,CL
字符串操作指令的实质是对一片连续的存储单元进行处理,这片连续的存储单元由隐含指针DS:SI或ES:DI来指定;字符串操作指令可对内存单元按照字节、字、双字进行处理,并能根据操作对象的字节数使变址寄存器SI/DI增加或减少1、2、4字节。规定如下:
A.当DF=0时,变址寄存器SI/DI增加1、2、4字节;即:变址寄存器SI/DI递增的步长可以是1、2、4字节;
B.当DF=1时,变址寄存器SI/DI减少1、2、4字节;即:变址寄存器SI/DI递减的步长可以是1、2、4字节。
DS:SI 源串段寄存器 :串变址.
ES:DI 目标串段寄存器:串变址.
CX 重复次数计数器.
AL/AX 扫描值.
D标志 0表示重复操作中SI和DI应自动增量; 1表示应自动减量.
Z标志 用来控制扫描或比较操作的结束.
串操作指令主要有如下:
l CLD 将DF置为0
l STD 将DF置为1
l MOVS(Move String Instruction)串传送.
MOVSB 传送字符。将ds:si指向的内存单元中的字节送入es:di中,然后根据DF的标志将si和di的值增或减(0增1减)
MOVSW 传送字。 将ds:si指向的内存单元中的字节送入es:di中,然后根据DF的标志将si和di的值增或减(0增1减)
MOVSD 传送双字. ) 经常这么用rep movsb相当于s:movsb ; loop s
该指令的执行并不会影响任何标志位;
指令格式:
MOVS 地址表达式1,地址表达式2
MOVSB/MOVSW 地址表达式1,地址表达式2
MOVSD 地址表达式1,地址表达式2 ;80386+
l CMPS(Compare String Instruction)串比较(CMPSB比较字符.CMPSW比较字.)
受影响的标志位:AF、CF、OF、PF、SF、ZF
指令格式:
CMPS 地址表达式1,地址表达式2
CMPSB/CMPSW 地址表达式1,地址表达式2
CMPSD 地址表达式1,地址表达式2 ;80386+
l SCAS(Scan String Instruction)串扫描. 把AL或AX的内容与目标串作比较,比较结果反映在标志位.
受影响的标志位:AF、CF、OF、PF、SF、ZF
指令格式:
SCAS 地址表达式
SCASB/SCASW 地址表达式
SCASD 地址表达式 ;80386+
l LODS(Load String Instruction)装入串. 把源串中的元素(字或字节)逐一装入AL或AX中.
( LODSB 传送字符. LODSW 传送字. LODSD 传送双字. )
该指令的执行并不会影响任何标志位;
指令格式:
LODS 地址表达式
LODSB/LODSW 地址表达式
LODSD 地址表达式 ;80386
在指令LODS中,它会根据"地址表达式"的属性来决定读取一个字节、字或双字;即:当该地址表达式的属性为字节、字或双字时,将从指针DI:SI处读取一个字节到AL中,或读取一个字到AX中,或读取一个双字到EAX中,与此同时,SI还将分别增减1、2、4字节;
l STOS(Store String Instruction)保存串.是LODS的逆过程.
该指令的执行并不会影响任何标志位;
指令格式:
STOS 地址表达式
STOSB/STOSW 地址表达式
STOSD 地址表达式 ;80386+
l INS(Input String Instruction)输入字符串.
该指令是从某一指定端口接受一个字符串,并存入到一片连续的存储单元中;输入端口由寄存器DX指定,存储单元的首地址由指针ES:DI来确定,读入的数据个数由寄存器CX来确定;在指令的执行过程中,还要根据标志位DF的值来对寄存器DI做相应的增减;把存放字符串的连续存储区当做是数据的目的地;
与指令有关的操作数ES、DI、DX和CX等都是隐含操作数。
该指令的执行并不会影响任何标志位;
指令格式:
INS 地址表达式
INSB/INSW 地址表达式
INSD 地址表达式 ;80386+
l OUTS(Output String Instruction)输出字符串.
该指令是把一个给定的字符串输出到一个指定的端口中;输出端口由通用寄存器DX指定,输出数据的首地址由指针DS:SI确定,输出数据的个数由计数寄存器CX来确定;在指令执行的过程中,还要根据方向标志DF的值来对变址寄存器SI做相应的增减;
与指令有关的操作数ES、DI、DX和CX等都是隐含操作数。
该指令的执行并不会影响任何标志位;
指令格式:
OUTS 地址表达式
OUTSB/OUTSW 地址表达式
OUTSD 地址表达式 ;80386+
重复字符串操作指令对标志位的影响是由被重复的字符串操作指令来决定;
l REP(重复前缀指令) 当CX/ECX<>0时重复.
重复前缀指令是重复其后指定的字符串操作指令,重复的次数由计数寄存器CX来决定;
指令格式:
REP LODS/LODSB/LODSW/LODSD
REP STOS/STOSB/STOSW/STOSD
REP MOVS/MOVSB/MOVSW/MOVSD
REP INS/INSB/INSW/INSD
REP OUTS/OUTSB/OUTSW/OUTSD
重复前缀指令的执行步骤如下:
1:判断: CX=0
2:如果CX=0,则结束重复操作,执行程序中的下一条指令;
3:否则,CX=CX-1(不影响相关标志位),并执行重复前缀指令后面指定的字符串操作指令,在该指令执行完后,再转到步骤1;
l REPE/REPZ(相等重复前缀指令)当ZF=1或比较结果相等,且CX/ECX<>0时重复.
指令格式:
REPE/REPZ SCAS/SCASB/SCASW/SCASD
REPE/REPZ CMPS/CMPSB/CMPSW/CMPSD
该重复前缀指令的执行步骤如下:
1:判断条件: CX!=0 且 ZF=1
2:如果条件不成立,则结束重复操作,执行程序中的下一条指令;
3:否则,CX=CX-1(不影响任何标志位),并执行重复前缀指令后面指定的字符串操作指令,在该指令执行后,再转到步骤1;
l REPNE/REPNZ(不等重复前缀指令)当ZF=0或比较结果不相等,且CX/ECX<>0时重复.
指令格式:
REPNE/REPNZ SCAS/SCASB/SCASW/SCASD
REPNE/REPNZ CMPS/CMPSB/CMPSW/CMPSD
该重复前缀指令的执行步骤如下:
1:判断条件:CX!=0 且 ZF=0
2:如果条件不成立,则结束重复操作,执行程序中的下一条指令;
3:否则,CX=CX-1(不影响任何标志位),并执行重复前缀指令后面指定的字符串操作指令,在该指令执行完后,再转到步骤1;
l REPC 当CF=1且CX/ECX<>0时重复.
l REPNC 当CF=0且CX/ECX<>0时重复
转移指令:
l JMP ;无条件转移指令
l JX ;条件转移指令(JC/JNC, JZ/JNZ, JE/JNE, JS/JNS, JO/JNO…)
JA/JNBE 不小于或不等于时转移.
JAE/JNB 大于或等于转移.
JB/JNAE 小于转移.
JBE/JNA 小于或等于转移.
以上四条,测试无符号整数运算的结果(标志C和Z).
JG/JNLE 大于转移.
JGE/JNL 大于或等于转移.
JL/JNGE 小于转移.
JLE/JNG 小于或等于转移.
以上四条,测试带符号整数运算的结果(标志S,O和Z).
JE/JZ 等于转移.
JNE/JNZ 不等于时转移.
JC 有进位时转移.
JNC 无进位时转移.
JNO 不溢出时转移.
JNP/JPO 奇偶性为奇数时转移.
JNS 符号位为 "0" 时转移.
JO 溢出转移.
JP/JPE 奇偶性为偶数时转移.
JS 符号位为 "1" 时转移.
循环指令:
l LOOP 标号 ;该指令执行时, 技术寄存器CXX首先减1, 然后判断CX, 若为0, 跳出循环
l LOOPZ/LOOPE ;用于找到第一个不为0的事件
l LOOPNZ/LOOPNE ;用于找到第一个为0的事件
l JCXZ ;CX为零时转移
l JECXZ ;ECX为零时转移
子程序调用指令:
l CALL 子程序名 ;段内直接调用
l RET/RETF
中断指令:
l INT N(中断类型号) ;软中断指令
l IRET ;中断返回指令
l INTO ;溢出中断
标志处理指令:
l CLC ;进位标志CF置0
l CMC ;进位标志CF求反
l STC ;进位标志值1
l CLD ;方向标志置0
l STD ;方向标志置1
l CLI ;中断允许标志置0
l STI ;中断允许标志置1
其他处理器控制指令:
l NOP ;空操作
l HLT ;停机 处理器暂停, 直到出现中断或复位信号才继续.
l WAIT ;等待 当芯片引线TEST为高电平时使CPU进入等待状态.
l ESC ;换码
l LOCK ;封锁
1.assume:将段与某个段寄存器关联起来。
2.segment...ends:定义一个段,segment说明段的开始,ends说明结束,指令、数据、栈等可以单独定义为一个或多个段。
3.end:说明一个程序的结束,可以和start配合使用,start表示指令开始的地方。
4.db:db即define byte定义字节型数据, db 'A'表示定义1个字节型数据,大小为1B。
5.dw:dw即define word定义字型数据,dw 0123h表示定义一个字型数据,大小为2B。
6.dd: dd即double word定义双字型数据,dd 0123h表示定义一个双字型数据,大小为4B。
7.proc...endp: 定义一个过程,proc说明过程开始,endp说明过程结束。