在了解了寄存器和寻址方式后,汇编最吸引人的不就是指令么?
哈哈哈,我就是奔着指令来的其实。
指令分类:总共13种方法。
数据传送指令,标志位操作指令,算术运算指令,逻辑运算指令, (这些应该算是基本指令)
移位操作指令,位操作指令,比较运算指令,
印象:mov, xchg, lea, lds, les, push, pop, clc, cmc, stc, cld, std, cli, sti
sahf, lahf, pushf, popf, add, inc, adc, sub, sbb, dec, neg, mul, imul
div, idiv, cbw, cwd, cwde, cdq, and, or, not, xor, sal, sar, shl, shr, shld, shlr, rol, ror, rcl, rcr
bsf, bsr, bt, test
循环指令,转移指令,条件设置字节指令,
loop... jmp setnn ; 80386后新添加的指令
字符串操作指令,
比如movs, s是string的意思
ASCII-BCD码运算调整指令,处理器指令(这两种不常用)。
一,寄存器中的标志寄存器。
一、运算结果标志位
1、进位标志CF(Carry Flag)
进位标志CF主要用来反映运算是否产生进位或借位。如果运算结果的最高位产生了一个进位或借位,那么,其值为1,否则其值为0。
使用该标志位的情况有:多字(字节)数的加减运算,无符号数的大小比较运算,移位操作,字(字节)之间移位,专门改变CF值的指令等。
2、奇偶标志PF(Parity Flag)
奇偶标志PF用于反映运算结果中“1”的个数的奇偶性。如果“1”的个数为偶数,则PF的值为1,否则其值为0。
利用PF可进行奇偶校验检查,或产生奇偶校验位。在数据传送过程中,为了提供传送的可靠性,如果采用奇偶校验的方法,就可使用该标志位。
3、辅助进位标志AF(Auxiliary Carry Flag)
在发生下列情况时,辅助进位标志AF的值被置为1,否则其值为0:
(1)、在字操作时,发生低字节向高字节进位或借位时;
(2)、在字节操作时,发生低4位向高4位进位或借位时。
对以上6个运算结果标志位,在一般编程情况下,标志位CF、ZF、SF和OF的使用频率较高,而标志位PF和AF的使用频率较低。
4、零标志ZF(Zero Flag)
零标志ZF用来反映运算结果是否为0。如果运算结果为0,则其值为1,否则其值为0。在判断运算结果是否为0时,可使用此标志位。
5、符号标志SF(Sign Flag)
符号标志SF用来反映运算结果的符号位,它与运算结果的最高位相同。在微机系统中,有符号数采用补码表示法,所以,SF也就反映运算结果的正负号。运算结果为正数时,SF的值为0,否则其值为1。
6、溢出标志OF(Overflow Flag)
溢出标志OF用于反映有符号数加减运算所得结果是否溢出。如果运算结果超过当前运算位数所能表示的范围,则称为溢出,OF的值被置为1,否则,OF的值被清为0。
“溢出”和“进位”是两个不同含义的概念,不要混淆。如果不太清楚的话,请查阅《计算机组成原理》课程中的有关章节。
二、状态控制标志位
状态控制标志位是用来控制CPU操作的,它们要通过专门的指令才能使之发生改变。
1、追踪标志TF(Trap Flag)
当追踪标志TF被置为1时,CPU进入单步执行方式,即每执行一条指令,产生一个单步中断请求。这种方式主要用于程序的调试。
指令系统中没有专门的指令来改变标志位TF的值,但程序员可用其它办法来改变其值。
2、中断允许标志IF(Interrupt-enable Flag)
中断允许标志IF是用来决定CPU是否响应CPU外部的可屏蔽中断发出的中断请求。但不管该标志为何值,CPU都必须响应CPU外部的不可屏蔽中断所发出的中断请求,以及CPU内部产生的中断请求。具体规定如下:
(1)、当IF=1时,CPU可以响应CPU外部的可屏蔽中断发出的中断请求;
(2)、当IF=0时,CPU不响应CPU外部的可屏蔽中断发出的中断请求。
CPU的指令系统中也有专门的指令来改变标志位IF的值。
3、方向标志DF(Direction Flag)
方向标志DF用来决定在串操作指令执行时有关指针寄存器发生调整的方向。具体规定在第5.2.11节——字符串操作指令——中给出。在微机的指令系统中,还提供了专门的指令来改变标志位DF的值。
问题:
二,指令系统
指令格式:
指令助忆符 [操作数1 [, 操作数2 [, 操作数3]]] [;注释
遵守:指令助记符和操作数之间要有分隔符, 分隔符可以是空格和 tab键;
如果指令包含多个操作数,那么,操作数之间用逗号分开。
掌握:要求指令操作数的寻址方式。
指令对标志位的影响、标志位对指令的影响;
指令的执行时间,对可完成同样功能的指令,要选用执行时间短的指令。
(reg = register 寄存器。 mem = memory 存储器, imm = immediate 立即数)
1、数据传送指令(除标志位操作指令外,都不影响标志位)
1.1、传送指令
MOV Reg/Mem, Reg/Mem/Imm
指令的语法 |
举例 |
周期数 |
MOV reg,reg |
mov bp,sp |
1 |
MOV mem,reg |
mov array[di],bx |
1 |
MOV reg,mem |
mov bx,pointer |
1 |
MOV mem,immed |
mov [bx],15 |
1 |
MOV reg,immed |
mov cx,256 |
1 |
MOV mem,accum |
mov total,ax |
1 |
MOV accum,mem |
mov al,string |
1 |
MOV segreg,reg16 |
mov ds,ax |
2, 3 |
MOV segreg,mem16 |
mov es,psp |
2, 3 |
MOV reg16,segreg |
mov ax,ds |
1 |
MOV mem16,segreg |
mov stack_save,ss |
1 |
MOV reg32,controlreg |
mov eax,cr0 |
22 |
mov eax,cr2 |
12 |
|
mov eax,cr3 |
21, 46 |
|
mov eax,cr4 |
14 |
|
MOV controlreg,reg32 |
mov cr0,eax |
4 |
MOV reg32,debugreg |
mov edx,dr0 |
DR0-DR3, DR6,DR7=11 |
DR4,DR5=12 |
||
MOV debugreg,reg32 |
mov dr0,ecx |
DR0-DR3, |
DR4,DR5=12 DR6,DR7=11 |
要求:
1)、两个操作数的数据类型要相同,要同为8位、16位或32位;如:MOV BL, AX等是不正确的; |
2)、两个操作数不能同时为段寄存器,如:MOV ES, DS等; (实现方式:mov ax, dx mov es, ax) |
3)、代码段寄存器CS不能为目的操作数,但可作为源操作数,如:指令MOV CS, AX等不正确,但指令MOV AX, CS等是正确的; |
4)、立即数不能直接传给段寄存器,如:MOV DS, 100H等; (实现方式:mov ax, 100h mov ds, ax) |
5)、立即数不能作为目的操作数,如:MOV 100H, AX等; |
6)、指令指针IP,不能作为MOV指令的操作数; |
7)、两个操作数不能同时为存储单元,如:MOV VARA, VARB等,其中VARA和VARB是同数据类型的内存变量。 (实现方式:mov ax varb mov vara ax) |
1.2、传送-填充指令(80386 )
MOVSX(符号填充)/MOVZX(零填充) Reg/Mem, Reg/Mem/Imm ;80386+
MOVSX的填充方式是:用源操作数的符号位来填充目的操作数的高位数据位。
MOVZX的填充方式是:恒用0来填充目的操作数的高位数据位。
MOVSX reg,reg |
movsx bx,al |
3 |
MOVSX reg,mem |
movsx eax,bsign |
3 |
MOVZX reg,reg |
movzx bx,al |
3 |
MOVZX reg,mem |
movzx eax,bunsign |
3 |
1.3、交换指令
寄存器不能是段寄存器,两个操作数也不能同时为内存变量。
XCHG reg,reg |
xchg cx,dx |
3 |
XCHG reg,mem |
xchg bx,pointer |
3 |
XCHG mem,reg |
xchg [bx],ax |
3 |
XCHG accum,reg |
xchg ax,cx |
2 |
XCHG reg,accum |
xchg cx,ax |
2 |
1.4、取段地址和有效地址指令
lea(load effective address) 取有效地址
lds, les, 取段寄存器 根据d,e等判定哪个寄存器
lfs, lgs, lss (32bit)
lea该指令通常用来对指针或变址寄存器bx, di, si等设置初值用。
buffer db 100 dup(?)
lea bx, buffer ;把字节变量buffer在数据段内的偏移量送给bx。
LDS reg,mem |
lds si,fpointer |
4 |
LES reg,mem |
les di,fpointer |
4 |
LFS reg,mem |
lfs edi,fpointer |
4 |
LGS reg,mem |
lgs bx,fpointer |
4 |
LSS reg,mem |
lss bp, fpointer |
4, pm=8 |
LEA reg,mem |
lea bx,npointer |
1 |
1.5、进栈指令
push, 一个字进栈,系统自动完成两步操作: sp<--sp-2, (sp)<--操作数
一个双字进栈,系统自动完成 esp <-- esp-4, (esp) <----操作数
pusha,功能是依次把ax, cx, dx, bx, bp, si, di等压栈。
PUSH reg |
push dx |
1 |
PUSH mem |
push [di] |
2 |
PUSH segreg |
push es |
1 |
PUSH immed |
push 15000 |
1 |
PUSHA |
pusha ;+80286 |
5 |
PUSHAD |
pushad |
5 |
PUSHF 把16/32位标志寄存器进栈 |
pushf |
4, pm=3 |
PUSHFD |
pushfd |
4, pm=3 |
1.6、出栈指令
pop: 弹出一个字: 操作数<---(sp), sp<--sp-2;
弹出一个双字: 操作数<---(esp), esp<---esp-4;
POP reg |
pop cx |
1 |
POP mem |
pop param |
3 |
POP segreg |
pop es |
3 |
POPA |
popa |
5 |
POPAD |
popad |
5 |
POPF |
popf |
6, pm=4 |
POPFD |
popfd |
6, pm=4 |
1.7、转换指令
有两个隐含操作数bx 和 al
功能:把bx 的值作为内存字节数组首地址、下标为al的数组元素的值传送给al。 al<---bx[al].
XLAT [[segreg:]mem] |
xlat |
4 |
XLATB [[segreg:]mem] |
xlatb es:table |
4 |
2、标志位操作指令
2.1、标志位操作指令
指令的语法 |
举例 |
周期数 |
CLC 清进位指令 cf <--- 0 |
clc |
2 |
CMC 进位取反指令 cf<--not cf |
cmc |
2 |
STC 置进位指令 cf<----1 |
stc |
2 |
CLD 清方向位指令 if<--0 |
cld |
2 |
STD 置方向位指令 if<--1 |
std |
2 |
CLI 清中断允许指令 if <---0 |
cli |
7 |
STI 置中断允许位指令if <--1 |
sti |
7 |
2.2、标志位存取操作指令
SAHF flags的低8位<---ah |
Sahf |
2 |
LAHF ah<----flags的低8位 |
lahf |
2 |
2.3、标志位堆栈操作指令
PUSHF |
pushf |
4, pm=3 |
PUSHFD |
pushfd |
4, pm=3 |
POPF |
popf |
6, pm=4 |
POPFD |
popfd |
6, pm=4 |
3、算术运算指令
3.1、加法指令
add 加; 受影响的标志位:af ,cf, of, pf, sf, zf
adc 带进位加;受影响的标志位:af ,cf, of, pf, sf, zf
inc 加1指令;受影响的标志位:af , of, pf, sf, zf 不影响cf
xadd 交换加指令;受影响的标志位:af ,cf, of, pf, sf, zf ;80486+
指令的语法 |
举例 |
周期数 |
ADC reg,reg |
adc dx,cx |
1 |
ADC mem,reg |
adc word ptr m16[2],dx |
3 |
ADC reg,mem |
adc dx,dword ptr m32[2] |
2 |
ADD reg,reg |
add ax,bx |
1 |
ADD mem,reg |
add total, cx |
3 |
ADD reg,mem |
add cx,incr |
2 |
ADD reg,immed |
add bx,6 |
1 |
ADD mem,immed |
add pointers[bx][si],6 |
3 |
ADD accum,immed |
add ax,10 |
1 |
INC reg |
inc bx |
1 |
INC mem |
inc vpage |
3 |
XADD reg,reg |
xadd dl,al |
3 |
XADD mem,reg |
xadd string,bl |
4 |
3.2、减法指令
sub 减; AF、CF、OF、PF、SF和ZF
sbb 带错位减; AF、CF、OF、PF、SF和ZF,指令的功能是把源操作数和标志位CF的值从目的操作数中一起减去。
dec 减一指令 AF、OF、PF、SF和ZF,不影响CF
neg 求补指令 AF、CF、OF、PF、SF和ZF,指令的功能:操作数=0-操作数,即改变操作数的正负号。
SUB reg,reg |
sub ax,bx |
1 |
SUB mem,reg |
sub array[di],bi |
3 |
SUB reg,mem |
sub al,[bx] |
2 |
SUB reg,immed |
sub bl,7 |
1 |
SUB mem,immed |
sub total,4000 |
3 |
SUB accum,immed |
sub ax,32000 |
1 |
SBB accum,immed |
sbb ax,320 |
1 |
SBB reg,immed |
sbb dx,45 |
1 |
SBB mem,immed |
sbb word ptr m32[2],40 |
3 |
SBB reg,reg |
sbb dx,cx |
1 |
SBB mem,reg |
sbb word ptr m32[2],dx |
3 |
SBB reg,mem |
sbb dx,word ptr m32[2] |
2 |
DEC reg |
dec ax |
1 |
DEC mem |
dec counter |
3 |
NEG reg |
neg ax |
1 |
NEG mem |
neg balance |
3 |
3.3、乘法指令
乘法指令分为无符号乘法指令和有符号乘法指令,它们的唯一区别就在于:数据的最高位是作为“数值”参与运算,还是作为“符号位”参与运算。
乘法指令的被乘数都是隐含操作数,乘数在指令中显式地写出来。CPU会根据乘数是8位、16位,还是32位操作数,来自动选用被乘数:AL、AX或EAX。
指令的功能是把显式操作数和隐含操作数相乘,并把乘积存入相应的寄存器中。
无符号数乘法指令MUL(Unsigned Multiply Instruction)
指令的格式:MUL Reg/Mem
受影响的标志位:CF和OF(AF、PF、SF和ZF无定义)
指令的功能是把显式操作数和隐含操作数(都作为无符号数)相乘,所得的乘积按表5.2的对应关系存放。
表5.2 乘法指令中乘数、被乘数和乘积的对应关系
乘数位数 |
隐含的被乘数 |
乘积的存放位置 |
举例 |
8位 |
AL |
AX |
MUL BL |
16位 |
AX |
DX-AX |
MUL BX |
32位 |
EAX |
EDX-EAX |
MUL ECX |
有符号数乘法指令IMUL(Signed Integer Multiply Instruction)
指令的格式: | IMUL | Reg/Mem | |
IMUL | Reg, Imm | ;80286+ | |
IMUL | Reg, Reg, Imm | ;80286+ | |
IMUL | Reg, Reg/Mem | ;80386+ |
受影响的标志位:CF和OF(AF、PF、SF和ZF无定义)
1)、指令格式1——该指令的功能是把显式操作数和隐含操作数相乘,所得的乘积按表5.2的对应关系存放。
2)、指令格式2——其寄存器必须是16位/32位通用寄存器,其计算方式为:
Reg ← Reg × Imm
3)、指令格式3——其寄存器只能是16位通用寄存器,其计算方式为:
Reg1 ← Reg2×Imm 或 Reg1 ← Mem×Imm
4)、指令格式4——其寄存器必须是16位/32位通用寄存器,其计算方式为:
Reg1 ← Reg1×Reg2 或 Reg1 ← Reg1×Mem
在指令格式2~4中,各操作数的位数要一致。如果乘积超过目标寄存器所能存储的范围,则系统将置溢出标志OF为1。
MUL reg |
mul bx |
|
MUL memX |
mul word ptr [bx] |
8,16-bit=11 |
32-bit=10 |
||
IMUL reg |
imul dx |
11 |
IMUL mem |
imul factor |
11 |
IMUL reg,immed |
imul cx,25 |
10 |
IMUL reg,reg,immed |
imul dx,ax,18 |
10 |
IMUL reg,mem,immed |
imul bx,[si],60 |
10 |
IMUL reg,reg |
imul cx,ax |
10 |
IMUL reg,mem |
imul dx,[si] |
10 |
3.4、除法指令
除法指令功能是用显式操作数去除隐含操作数,可得到商和余数。当除数为0,或商超出数据类型所能表示的范围时,系统会自动产生0号中断。
无符号数除法指令DIV(Unsigned Divide Instruction)
指令的格式:DIV Reg/Mem
指令的功能是用显式操作数去除隐含操作数(都作为无符号数),
所得商和余数按表5.3的对应关系存放。指令对标志位的影响无定义。
有符号数除法指令IDIV(Signed Integer Divide Instruction)
指令的格式:IDIV Reg/Mem
受影响的标志位:AF、CF、OF、PF、SF和ZF
指令的功能是用显式操作数去除隐含操作数(都作为有符号数),所得商和余数的对应关系见表5.3。
表5.3 除法指令除数、被除数、商和余数的对应关系
除数位数 |
隐含的被除数 |
商 |
余数 |
举例 |
8位 |
AX |
AL |
AH |
DIV BH |
16位 |
DX-AX |
AX |
DX |
DIV BX |
32位 |
EDX-EAX |
EAX |
EDX |
DIV ECX |
DIV reg |
div cx |
byte=17 word=25 |
DIV mem |
div [bx] |
dword=41 |
IDIV reg |
idiv dl |
8-bit=22;16-bit=30 |
IDIV mem |
idiv itemp |
32-bit=46 |
3.5、类型转换指令
CBW 字节转换指令 |
cbw |
3 |
CWD 字转换位双字 |
cwd |
2 |
CWDE字转换位扩展的双字 80386+ |
cwde |
3 |
CDQ 字转换位4字节 80386+ |
cdq |
2 |
4、逻辑运算指令
CF(0)、OF(0)、PF、SF和ZF(AF无定义)
4.1、逻辑与操作指令
指令的语法 |
举例 |
周期数 |
AND reg,reg |
and dx,bx |
1 |
AND mem,reg |
and bitmask,bx |
3 |
AND reg,mem |
and bx,masker |
2 |
AND reg,immed |
and dx,0F7h |
1 |
AND mem,immed |
and masker,100lb |
3 |
AND accum,immed |
and ax,0B6h |
1 |
4.2、逻辑或操作指令
OR reg,reg |
or ax,dx |
1 |
OR mem,reg |
or bits,dx |
3 |
OR reg,mem |
or dx,color[di] |
2 |
OR reg,immed |
or dx,110110b |
1 |
OR mem,immed |
or flag_rec,8 |
3 |
OR accum,immed |
or ax,40h |
1 |
4.3、逻辑非操作指令
NOT reg |
not ax |
1 |
NOT mem |
not masker |
3 |
4.4、逻辑异或操作指令
XOR reg,reg |
xor cx,bx |
1 |
XOR reg,mem |
xor cx,flags |
2 |
XOR mem,reg |
xor [bp+10],cx |
3 |
XOR reg,immed |
xor bl,1 |
1 |
XOR mem,immed |
xor switches[bx],101b |
3 |
XOR accum,immed |
xor ax,01010101b |
1 |
5、移位操作指令
受影响的标志位:CF、OF、PF、SF和ZF(AF无定义)。
5.1、算术左移指令
算术左移SAL把目的操作数的低位向高位移,空出的低位补0;
指令的语法 |
举例 |
周期数 |
SAL reg,1 |
sal bx,1 |
1 |
SAL mem,1 |
sal word ptr m32[0],1 |
3 |
SAL reg,CL |
sal ah,cl |
4 |
SAL mem,CL |
sal BYTE PTR [di],cl |
4 |
SAL reg,immed |
sal cx,6 |
1 |
SAL mem,immed |
sal array[bx+di],14 |
3 |
5.2、算术右移指令
算术右移SAR把目的操作数的高位向低位移,空出的高位用最高位(符号位)填补。
SAR reg,1 |
sar di,1 |
1 |
SAR mem,1 |
sar count,1 |
3 |
SAR reg,CL |
sar bx,cl |
4 |
SAR mem,CL |
sar sign,cl |
4 |
SAR reg,immed |
sar bx,5 |
1 |
SAR mem,immed |
sar sign_count,3 |
3 |
5.3、逻辑左移指令
逻辑左移/右移指令只有它们的移位方向不同,移位后空出的位都补0。
SHL reg,1 |
shl si,1 |
1 |
SHL mem,1 |
shl index,1 |
3 |
SHL reg,CL |
shl di,cl |
4 |
SHL mem,CL |
shl index,cl |
4 |
SHL reg,immed |
shl di,2 |
1 |
SHL mem,immed |
shl unsign,4 |
3 |
5.4、逻辑右移指令
SHR reg,1 |
shr dh,1 |
1 |
SHR mem,1 |
shr unsign[di],1 |
3 |
SHR reg,CL |
shr dx,cl |
4 |
SHR mem,CL |
shr word ptr m32[2],cl |
4 |
SHR reg,immed |
shr bx,8 |
1 |
SHR mem,immed |
shr mem16,11 |
3 |
5.5、双精度左移指令
SHLD reg16,reg16,immed8 |
shld ax,dx,10 |
4 |
SHLD reg32,reg32,immed8 |
||
SHLD mem16,reg16,immed8 |
shld bits,cx,5 |
4 |
SHLD mem32,reg32,immed8 |
||
SHLD reg16,reg16,CL |
shld ax,dx,cl |
4 |
SHLD reg32,reg32,CL |
||
SHLD mem16,reg16,CL |
shld masker,ax,cl |
5 |
SHLD mem32,reg32,CL |
5.6、双精度右移指令 80386+
SHRD reg16,reg16,immed8 |
shrd cx,si,3 |
4 |
SHRD reg32,reg32,immed8 |
||
SHRD mem16,reg16,immed8 |
shrd [di],dx,5 |
4 |
SHRD mem32,reg32,immed8 |
||
SHRD reg16,reg16,CL |
shrd ax,dx,cl |
4 |
SHRD reg32,reg32,CL |
||
SHRD mem16,reg16,CL |
shrd [bx],ax,cl |
5 |
SHRD mem32,reg32,CL |
5.7、循环左移指令 (cf 和 of)
循环左移/右移指令只是移位方向不同,它们移出的位不仅要进入CF,而且还要填补空出的位
指令的语法 |
举例 |
周期数 |
ROL reg,1 |
rol ax,1 |
1 |
ROL mem,1 |
rol bits,1 |
3 |
ROL reg,CL |
rol ax,cl |
4 |
ROL mem,CL |
rol color,cl |
4 |
ROL reg,immed8 |
rol ax,13 |
1 |
ROL mem,immed8 |
rol byte ptr [bx],10 |
3 |
5.8、循环右移指令
ROR reg,1 |
ror ax,1 |
1 |
ROR mem,1 |
ror word ptr [bx],1 |
3 |
ROR reg,CL |
ror dx,cl |
4 |
ROR mem,CL |
ror color,cl |
5 |
ROR reg,immed8 |
ror bl,3 |
1 |
ROR mem,immed8 |
ror bits,6 |
3 |
5.9、带进位的循环左移指令
RCL reg,1 |
rcl dx,1 |
1 |
RCL mem,1 |
rcl WORD PTR [si],1 |
3 |
RCL reg,CL |
rcl dx,cl |
7-24 |
RCL mem,CL |
rcl masker,cl |
9-26 |
RCL reg,immed8 |
rcl bx,5 |
8-25 |
RCL mem,immed8 |
rcl word ptr [bp+8],3 |
10-27 |
5.10、带进位的循环右移指令
RCR reg,1 |
rcr bl,1 |
1 |
RCR mem,1 |
rcr word ptr m32[0],1 |
3 |
RCR reg,CL |
rcr bl,cl |
7-24 |
RCR mem,CL |
rcl word ptr [bx=di],cl |
9-26 |
RCR reg,immed8 |
rcr si,9 |
8-25 |
RCR mem,immed8 |
rcr masker,3 |
10-27 |
6、位操作指令
6.1、正向位扫描指令
指令的语法 |
举例 |
周期数 |
BSF reg16,reg16 |
bsf cx,bx |
6-34 |
BSF reg32,reg32 |
bsf cx,bx |
6-42 |
BSF reg16,mem16 |
bsf ecx,bitmask |
6-35 |
BSF reg32,mem32 |
bsf ecx,bitmask |
6-43 |
6.2、逆向位扫描指令
BSR reg16,reg16 |
bsr cx,dx |
7-39 |
BSR reg32,reg32 |
bsr ecx, edx |
7-71 |
BSR reg16,mem16 |
bsr ax,bitmask |
7-40 |
BSR reg32,mem32 |
bsr eax,bitmask |
7-72 |
6.3、位检测指令
BT reg16,immed8*(注) |
bt ax,4 |
4 |
BT mem16,immed8 |
bt [bx],4 |
4 |
BT reg16,reg16 |
bt ax,bx |
4 |
BT mem16,reg16 |
bt [bx],dx |
9 |
(注) 操作数也可以是32位数。
6.4、正向位扫描指令
BTC reg16,immed8* |
btc edi,4 |
7 |
BTC mem16,immed8* |
btc color[di],4 |
8 |
BTC reg16,reg16* |
btc eax,ebx |
7 |
BTC mem16,reg16* |
btc [bp+8],si |
13 |
6.5、正向位扫描指令
BTR reg16,immed8* |
btr bx,17 |
7 |
BTR mem16,immed8* |
btr [bx],27 |
8 |
BTR reg16,reg16* |
btr cx,di |
7 |
BTR mem16,reg16* |
btr rotate,cx |
13 |
6.6、正向位扫描指令
BTS reg16,immed8* |
bts ax,4 |
7 |
BTS mem16,immed8* |
bts maskit,4 |
8 |
BTS reg16,reg16* |
bts bx,ax |
7 |
BTS mem16,reg16* |
bts flags[bx],cx |
13 |
6.7、正向位扫描指令
TEST reg,reg |
test dx,bx |
1 |
TEST mem,reg |
test flags,dx |
2 |
TEST reg,immed |
test cx,30h |
1 |
TEST mem,immed |
test masker,1 |
2 |
TEST accum,immed |
test ax,90h |
1 |
7、比较运算指令
7.1、比较指令
指令的语法 |
举例 |
周期数 |
CMP reg,reg |
cmp dl,cl |
1 |
CMP mem,reg |
cmp array[si],bl |
2 |
CMP reg,mem |
cmp bh,array[si] |
2 |
CMP reg,immed |
cmp bx,24 |
1 |
CMP mem,immed |
cmp tester,4000 |
2 |
CMP accum,immed |
cmp ax,1000 |
1 |
7.2、比较交换指令
CMPXCHG mem,reg |
cmpxchg string,bl |
6 |
CMPXCHG reg,reg |
cmpxchg bx,cx |
6 |
CMPXCHG8B reg,mem64 |
cmpxchg8b ax,[bx] |
10 |
8、循环指令
循环结构是程序的三大结构之一。为了方便构成循环结构,汇编语言提供了多种循环指令,这些循环指令的循环次数都是保存在计数器CX或ECX中。除了CX或ECX可以决定循环是否结束外,有的循环指令还可由标志位ZF来决定是否结束循环。
在高级语言中,循环计数器可以递增,也可递减,但汇编语言中,CX或ECX只能递减,所以,循环计数器只能从大到小。在程序中,必须先把循环次数赋给循环计数器。
汇编语言的循环指令都是放在循环体的下面,在循环时,首先执行一次循环体,然后把循环计数器CX或ECX减1。当循环终止条件达到满足时,该循环指令下面的指令将是下一条被执行的指令,否则,程序将向上转到循环体的第一条指令。
在循环未终止,而向上转移时,规定:该转移只能是一个短转移,即偏移量不能超过128,也就是说循环体中所有指令码的字节数之和不能超过128
8.1、循环指令
LOOP label |
loop wend |
5, 6 |
LOOPE label |
loope again |
7, 8 |
LOOPZ label |
loopz again |
7, 8 |
LOOPNE label |
loopne for_next |
7, 8 |
LOOPNZ label |
loopnz for_next |
7, 8 |
8.2、循环指令
JCXZ label |
jcxz notfound |
6,5 |
JECXZ label |
jecxz notfound |
6,5 |
9、转移指令
9.1、无条件转移指令
jmp
包括:JMP、子程序的调用和返回指令、中断的调用和返回指令等。
JMP 标号/Reg/Mem
JMP指令是从程序当前执行的地方无条件转移到另一个地方执行。这种转移可以是一个短(short)转移(偏移量在[-128, 127]范围内),近(near)转移(偏移量在[-32K, 32K]范围内)或远(far)转移(在不同的代码段之间转移)。
短和近转移是段内转移,JMP指令只把目标指令位置的偏移量赋值指令指针寄存器IP,从而实现转移功能。但远转移是段间转移,JMP指令不仅会改变指令指针寄存器IP的值,而且还会改变代码段寄存器CS的值。
指令的语法 |
举例 |
周期数 |
JMP label |
jmp NEAR PTR distant |
1 |
jmp distant |
3 |
|
JMP reg16 |
jmp ax |
2 |
JMP mem16 |
jmp table[di] |
2 |
JMP reg32 |
jmp eax |
3 |
JMP mem32 |
jmp fpointer[si] |
2 |
JMP mem48 |
jmp FWORD PTR [di] |
4 |
9.2、条件转移指令
条件转移指令是一组极其重要的转移指令,它根据标志寄存器中的一个(或多个)标志位来决定是否需要转移,这就为实现多功能程序提供了必要的手段。微机的指令系统提供了丰富的条件转移指令来满足各种不同的转移需要,在编程序时,要对它们灵活运用。
条件转移指令又分三大类:基于无符号数的条件转移指令、基于有符号数的条件转移指令和基于特殊算术标志位的条件转移指令
无符号数的条件转移指令(Jumps Based on Unsigned (Logic) Data)
指令的助忆符 |
检测的转移条件 | 功能描述 |
JE/JZ |
ZF=1 | Jump Equal or Jump Zero |
JNE/JNZ |
ZF=0 | Jump Not Equal or Jump Not Zero |
JA/JNBE |
CF=0 and ZF=0 | Jump Above or Jump Not Below or Equal |
JAE/JNB |
CF=0 | Jump Above or Equal or Jump Not Below |
JB/JNAE |
CF=1 | Jump Below or Jump Not Above or Equal |
JBE/JNA |
CF=1 or AF=1 | Jump Below or Equal or Jump Not Above |
有符号数的条件转移指令(Jumps Based on Signed (Arithmetic) Data)
指令的助忆符 |
检测的转移条件 | 功能描述 |
JE/JZ |
ZF=1 | Jump Equal or Jump Zero |
JNE/JNZ |
ZF=0 | Jump Not Equal or Jump Not Zero |
JG/JNLE |
ZF=0 and SF=OF | Jump Greater or Jump Not Less or Equal |
JGE/JNL |
SF=OF | Jump Greater or Equal or Jump Not Less |
JL/JNGE |
SF≠OF | Jump Less or Jump Not Greater or Equal |
JLE/JNG |
ZF=1 or SF≠OF | Jump Less or Equal or Jump Not Greater |
特殊算术标志位的条件转移指令(Jumps Based on Special Arithmetic Tests)
指令的助忆符 |
检测的转移条件 | 功能描述 |
JC |
CF=1 | Jump Carry |
JNC |
CF=0 | Jump Not Carry |
JO |
OF=1 | Jump Overflow |
JNO |
OF=0 | Jump Not Overflow |
JP/JPE |
PF=1 | Jump Parity or Jump Parity Even |
JNP/JPO |
PF=0 | Jump Not Parity or Jump Parity Odd |
JS |
SF=1 | Jump Sign (negative) |
JNS |
SF=0 | Jump No Sign (positive) |
9.3、子程序调用指令
CALL label |
call upcase |
1 |
call distant |
4 |
|
CALL reg |
call ax |
2 |
CALL mem32 |
call [bx] |
2 |
CALL mem32 |
call dword ptr [bx] |
5 |
9.4、子程序返回指令
RETN |
retn |
2 |
RETN immed16 |
retn 8 |
3 |
RETF |
retf |
4, 23 |
RETF immed16 |
retf 32 |
4, 23 |
9.5、中断指令
INT immed8 |
int 25h |
16, pm=31, 48*(注) |
INT 3 |
int 3 |
13, pm=27, 44* |
INTO |
Into |
13, pm=27, 44* |
注:第一时间是同等优先级的中断时间,第二时间为高优先级的中断时间。
9.6、中断返回指令
IRET |
Iret |
8*(注),10, pm=27 |
IRETD |
Iretd |
10, pm=27 |
IRETF |
Iretf |
|
IRETDF |
Iretdf |
注:实方式或虚拟8086方式。
10、条件设置字节指令
setnn
不影响任何标志位
条件设置字节指令(Set Byte Conditionally)是80386及其以后CPU所具有的一组指令。它们在测试条件方面与条件转移是一致的,但在功能方面,它们不是转移,而是根据测试条件的值来设置其字节操作数的内容为1或0。
SETcondition reg8 |
setc dh |
1 |
SETcondition mem8 |
setle flag |
2 |
11、字符串操作指令
字符串操作指令的实质是对一片连续存储单元进行处理,这片存储单元是由隐含指针DS:SI或ES:DI来指定的。字符串操作指令可对内存单元按字节、字或双字进行处理,并能根据操作对象的字节数使变址寄存器SI(和DI)增减1、2或4。
(1)、当DF=0时,变址寄存器SI(和DI)增加1、2或4;
(2)、当DF=1时,变址寄存器SI(和DI)减少1、2或4。
11.1、取字符串数据指令
lods (load string instruction )
指令的语法 |
举例 |
周期数 |
LODS [segreg:]src |
lods es:source |
2 |
LODSB [[segreg:]src] |
Lodsb |
2 |
LODSW [[segreg:]src] |
Lodsw |
2 |
LODSD [[segreg:]src] |
Lodsd |
2 |
11.2、置字符串数据指令 df
stos
STOS [ES:]dest |
stor es:dstring |
3 |
STOSB [[ES:]dest] |
stosb |
3 |
STOSW [[ES:]dest] |
stosw |
3 |
STOSD [[ES:]dest] |
stosd |
3 |
11.3、字符串传送指令 df
movs
MOVS [es:]dest, [segreg:]src |
movs dest,es:source |
4 |
MOVSB [[es:]dest, [segreg:]src] |
movsb |
4 |
MOVSW [[es:]dest, [segreg:]src] |
movsw |
4 |
MOVSD [[es:]dest, [segreg:]src] |
movsd |
4 |
11.4、输入字符串指令
ins
该指令是从某一指定的端口接受一个字符串,并存入一片存储单元之中。输入端口由DX指定,存储单元的首地址和读入数据的个数分别由ES:DI和CX来确定。在指令的执行过程中,还根据标志位DF对寄存器DI作相应增减。
该指令不影响任何标志位。
INS [ES:]dest, DX |
ins es:instr,dx |
9, pm=6,24*, vm=22 |
INSB |
Insb |
9, pm=6,24*, vm=22 |
INSW |
Insw |
9, pm=6,24*, vm=22 |
INSD |
Insd |
9, pm=6,24*, vm=22 |
11.5、输出字符串指令
outs
该指令是把一个字符串输入到指定的输出端口中。输出端口由DX指定,其输出数据的首地址和个数分别由DS:SI和CX来确定。在指令的执行过程中,还根据标志位DF对寄存器SI作相应增减。
该指令的执行不影响任何标志位。
OUTS DX,[segreg:]src |
outs dx,buffer |
13, pm=10,27, VM=24 |
OUTSB [DX,[segreg:]src] |
outsb |
13, pm=10,27, VM=24 |
OUTSW [DX,[segreg:]src] |
outsw |
13, pm=10,27, VM=24 |
OUTSD [DX,[segreg:]src] |
outsd |
13, pm=10,27, VM=24 |
11.6、字符串比较指令 af, cf, of, pf, sf, zf
cmps
该指令是把一个字符串输入到指定的输出端口中。
输出端口由DX指定,其输出数据的首地址和个数分别由DS:SI和CX来确定。
在指令的执行过程中,还根据标志位DF对寄存器SI作相应增减。该指令的执行不影响任何标志位。
CMPS [segreg:] src, [ES:]dest |
cmps source,es:dest |
5 |
CMPSB [[segreg:[src,] ES:] dest] |
cmpsb |
5 |
CMPSW [[segreg:[src,] ES:]dest] |
cmpsw |
5 |
CMPSD [[segreg:[src,] ES:] dest] |
cmpsd |
5 |
11.7、字符串扫描指令 af, cf, of, pf, sf, zf
scas (scan string instruction)
该指令是用指针 es: di 所指向字节,字,或双字的值与相应的al、ax、eax的值相减,
用所得到的差来设置有关标志位。
与此同时,变址寄存器di还将根据标志位df的值来进行增减。
SCAS [ES]:dest |
scas es:destin |
4 |
SCASB |
Scasb |
4 |
SCASW |
Scasw |
4 |
SCASD |
Scasd |
4 |
11.8、重复前缀指令
rep(repeat string instruction)
但我们知道:每个字符串通常会有多个字符的,所以,就需要重复执行这些字符串操作指令。为了满足这种需求,指令系统提供了一组重复前缀指令。
重复字符串操作指令对标志位的影响是由被重复的字符串操作指令来决定。
重复前缀指令的执行步骤如下:
(1)、判断:CX=0;
(2)、如果CX=0,则结束重复操作,执行程序中的下一条指令;
(3)、否则,CX=CX-1(不影响有关标志位),并执行其后的字符串操作指令,在该指令执行完后,再转到步骤(1)。
重复前缀指令是重复其后的字符串操作指令,重复的次数由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
注:当CPL≤IOPL时,执行时间是第一个时钟周期,否则是第二个时钟周期。
11.9、相等重复前缀指令 zf
repe(repeat string conditionaly)
条件重复前缀指令与前面的重复前缀指令功能相类似,
所不同的是:其重复次数不仅由CX来决定,而且还会由标志位ZF来决定。
根据ZF所起的作用又分为二种:相等重复前缀指令REPE/REPZ和不等重复前缀指令REPE/REPZ。
该重复前缀指令的执行步骤如下:
(1)、判断条件:CX≠0 且 ZF=1;
(2)、如果条件不成立,则结束重复操作,执行程序中的下一条指令;
(3)、否则,CX=CX-1(不影响有关标志位),并执行其后的字符串操作指令,在该指令执行完后,再转到步骤(1)。
REPE CMPS src,dest |
repe cmps src,dest |
7, 9+4n |
REPE SCAS dest |
repe scas dest |
7, 9+4n |
11.10、不相等重复前缀指令 zf
repne
该重复前缀指令的执行步骤如下:
(1)、判断条件:CX≠0 且 ZF=0;
(2)、如果条件不成立,则结束重复操作,执行程序中的下一条指令;
(3)、否则,CX=CX-1(不影响有关标志位),并执行其后的字符串操作指令,在该指令执行完后,再转到步骤(1)。
REPNE CMPS src,dest |
repne cmps src,dest |
7, 8+4n |
REPNE SCAS dest |
repne scas dest |
7, 9+4n |
12、ASCII-BCD码运算调整指令 很少运用到实际程序中
指令的语法 |
举例 |
周期数 |
AAA 加调整 af cf |
aaa |
3 |
AAD 除调整 pf sf zf |
aad |
10 |
AAM 乘调整 pf sf zf |
aam |
18 |
AAS 减调整 af cf |
aas |
3 |
DAA 十进制数加调整 |
daa |
3 |
DAS 十进制数减调整 |
das |
3 |
用法:aaa
aas
aam 和 aad
daa 和 das
13、处理器指令 使用率不高
HLT |
Hlt |
12 |
NOP |
nop |
1 |
WAIT |
wait |
1 |
LOCK |
lock |
1 |
14、协处理器指令 使用率不高
指令的语法 |
举例 |
周期数 |
FBLD membcd | fbld packbck | 48-58 |
FBSTP membcd | fbstp bcds[bx] | 148-154 |
FLD reg | fld st(3) | 1 |
FLD mem32real | fld longreal | 1 |
FLD mem64real | 1 | |
FLD mem80real | 3 | |
FST reg | fst st | 1 |
FST memreal | fst longs[bx] | 2 |
FSTP reg | fstp st(3) | 1 |
FSTP mem32real | fstp longreal | 2 |
FSTP mem64real | 2 | |
FSTP mem80real | 3 | |
FXCH [reg] | fxchg st(3) | 1 |
FILD memint | fild quads[si] | 3, 1 |
FIST memint | fist doubles[8] | 6 |
FISTP memint | fistp longint | 6 |