通用数据传送指令
MOV 传送字或字节
mov al,10h
MOVSX 先符号扩展,再传送
movsx eax,ax;先进行全零扩展,前16位为F
MOVZX 先零扩展,再传送
movzx eax,ax;先进行全零扩展,前16位为0
PUSH 把字压入堆栈
push reg/nem16 32
push imm32
POP 把字弹出堆栈
pop reg/nem16 32
PUSHFD 把32EFLAGS寄存器内容压入堆栈
pushfd;保存标志寄存器内容
POPFD 把32EFLAGS寄存器内容弹出堆栈
popfd;恢复标志寄存器内容
PUSHA 把AX,CX,DX,BX,SP,BP,SI,DI依次压入堆栈
pusha;保存16通用寄存器内容
POPA 把DI,SI,BP,SP,BX,DX,CX,AX依次弹出堆栈
popa;恢复16通用寄存器内存
PUSHAD 把EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI依次压入堆栈
pushad;保存32通用寄存器内容
POPAD 把EDI,ESI,EBP,ESP,EBX,EDX,ECX,EAX依次弹出堆栈
popad;恢复32通用寄存器内存
BSWAP 交换32位寄存器里字节的顺序
;EAX=96688368H
BSWAP EAX;EAX=68836896H
XCHG 交换字或字节( 至少有一个操作数为寄存器,段寄存器不可作为操作数)
xchg ax,hx
xchg ah,al
xchg eax,ebx
xchg var,ax;var16位
CMPXCHG 比较并交换操作数( 第二个操作数必须为累加器AL/AX/EAX )
CMPXCHG CX,DX
;如果指令执行前 (AX)=2300H,(CX)=2300H.(DX)=2400H
;则指令执行后 因(CX)=(AX),故(CX)=2400H,ZF=1
;如果指令执行前(AX)=2500H,(CX)=2300H,(DX)=2400H
;则指令执行后因(CX)!=(AX),故(AX)=2300H,ZF=0
XADD 先交换再累加( 结果在第一个操作数里 )
xadd eax,ecx
;相当于:
先执行:
xchg eax,ecx
然后执行:
add eax,ecx
XLAT 字节查表转换
X DW 1122h,3344h,5566h,7788h
lea bx,X
mov al,03h
xlat
BX 指向一张 256 字节的表的起点, AL 为表的索引值 (0-255,即 0-FFH); 返回 AL 为查表结果 ( [BX+AL]->AL )
输入输出端口传送指令
IN I/O端口输入
语法: IN 累加器, {端口号│DX}
OUT I/O端口输出
语法: OUT {端口号│DX},累加器
输入输出端口由立即方式指定时, 其范围是 0-255; 由寄存器 DX 指定时,其范围是 0-65535
目的地址传送指令
LEA 装入有效地址
LEA DX,string ;把偏移地址存到DX
LDS 传送目标指针,把指针内容装入DS
LDS SI,string ;把段地址:偏移地址存到DS:SI
LES 传送目标指针,把指针内容装入ES
LES DI,string ;把段地址:偏移地址存到ESDI
LFS 传送目标指针,把指针内容装入FS
LFS DI,string ;把段地址:偏移地址存到FSD
LGS 传送目标指针,把指针内容装入GS
LGS DI,string ;把段地址:偏移地址存到GSDI
LSS 传送目标指针,把指针内容装入SS
LSS DI,string ;把段地址:偏移地址存到SSDI
标志传送指令
LAHF 标志寄存器传送,把标志装入AH
.data
saveflags byte ?
.code
lahf
mov saveflags,ah
SAHF 标志寄存器传送,把AH内容装入标志寄存器
mov ah,saveflags
sahf
PUSHF 标志入栈
pushf;保存标志寄存器内容
POPF 标志出栈
popf;恢复标志寄存器内容
PUSHD 32位标志入栈
pushd;保存32通用寄存器内容
POPD 32位标志出栈
popd;恢复32通用寄存器内存
算术运算指令
ADD 加法
mov eax,1
add eax,12
ADC 带进位加法
mov dl,0
mov al,0FFh
add al,0FFh;AL=FEh
adc dl,0;DL/AL=01FEh
INC 加 1
mov ax,1
inc ax
AAA 加法的ASCII码调整
mov ah,0
mov al,'8';AX=0038h
add al,'2';AX=006Ah
aaa;AX=0100h(结果进行ASCII转换)
or ax,3030h;AX=3130h='10'(转换为ASCII码)
DAA 加法的十进制调整
mov al,35h
add al,48h;AL=7Dh
daa;AL=83h(调整后结果)
SUB 减法
mov al,23
sub al,3
SBB 带借位减法
mov edx,7;高32位
mov eax,1;低32位
sub eax,2
sbb edx,0;高32位减法
DEC 减 1
dec al
NEC 求反(以 0 减之)
nec al
CMP 比较.(两操作数作减法,仅修改标志位,不回送结果)
mov ax,5
cmp ax,10;ZF=0 and CF=1
AAS 减法的ASCII码调整
mov ah,0
mov al,'8';AX=0038h
sub al,'9';AX=00FFh
aas;AX=FF09h
pushf
or al,30h;AX=FF39h
popf
DAS 减法的十进制调整
mov bl,48h
mov al,85h
sub al,bl;AL=3Dh
das;AL=37h(调整后结果)
MUL 无符号乘法
var word 0100h
mov ax,2000h;AX=2000h;AX存储结果
mul 0100h/var;DX:AX=00200000h,CF=1;32位EDX:EAX
IMUL 整数乘法
mov ax,48
mov bx,4
imul bx;DX:AX=000000C0h,OF=0
以上两条,结果回送AH和AL(字节运算),或DX和AX(字运算)
AAM 乘法的ASCII码调整
var byte 05h,06h
mov bl,var;第一个操作数
mov bl,[var+1];第二个操作数
mul bl;AX=001Eh
aam;AX=0300h
DIV 无符号除法
mov ax,0083h;被除数
mov bl,2;除数
div bl;AL=41h,AH=01h
IDIV 整数除法
var sword -101;009Bh
mov dx,0
mov ax,var;DX:AX=0000009Bh(+155)
mov bx,2;BX是除数
idiv bx;DX:AX除以BX
var sword -48
mov al,var;被除数低字节
cbw;AL扩展到AH
mov bl,+5;除数
idiv bl;AL=-9,AH=-3
以上两条,结果回送:
商回送AL,余数回送AH, (字节运算);或商回送AX,余数回送DX, (字运算)
AAD 除法的ASCII码调整
var byte ?
var2 byte ?
mov ax,0307h;被除数
aad;AX=0025h
mov bl,5;除数
div bl;AX=0207h
mov var,al
mov var2,ah
CBW 字节转换为字. (把AL中字节的符号扩展到AH中去)
var sword -101;9Bh
mov al,var;AL=9Bh
cbw;AL=FF9Bh
CWD 字转换为双字. (把AX中的字的符号扩展到DX中去)
var sword -101;FF9Bh
mov ax,var;AX=FF9Bh
cwd;DX:AX=FFFFFF9Bh
CWDE 字转换为双字. (把AX中的字符号扩展到EAX中去)
NULL
CDQ 双字扩展. (把EAX中的字的符号扩展到EDX中去)
var sword -101;FFFFFF9Bh
mov eax,var;EDX:EAX=FFFFFFFFFFFFFF9Bh
cdq
逻辑运算指令
AND 与运算
mov al,10101110b
and al,11110110b;消除位0,3
OR 或运算
mov al,11100011b
or al,00000100b;位2置1
XOR 异或运算
mov al,10110101b
xor al,0;异或
NOT 取反
mov al,10101110b
not al;补集
TEST 测试(两操作数作与运算,仅修改标志位,不回送结果)
test al,00001001b;测试0,3位
SHL 逻辑左移,位元乘法
mov bl,8Fh;BL=10001111b
shl bl,1;CF=1,BL=00011110b
SAL 算术左移(=SHL)
sal/shl
SHR 逻辑右移,位元除法
mov al,0D0h;AL=11010000b
shr al,1;AL=01101000b,CF=0
SAR 算术右移(=SHR)
sar/shr
ROL 循环左移
mov al,40h;AL=01000000b
rol al,1;AL=10000000b
rol al,3;AL=00000100b
ROR 循环右移
mov al,01h;AL=00000001b
ror al,1;AL=10000000b
ror al,3;AL=00010000b
RCL 通过进位的循环左移
clc;CF=0
mov bl,88h;CF,BL=0 10001000b
rcl bl,1;CF,BL=1 00010000b
rcl bl,1;CF,BL=0 00100010b
RCR 通过进位的循环右移
stc ;CF=1
mov ah,10h;AH,CF=00010000 1
rcr ah,1;AH,CF=10001000 0
以上八种移位指令,其移位次数可达255次
移位一次时, 可直接用操作码. 如 SHL AX,1
移位>1次时, 则由寄存器CL给出移位次数
如 MOV CL,04 SHL AX,CL
SHLD 双精度左移
wval word 9BA6h
mov ax,0AC36h
shld wval,ax,4;wval=BA6Ah,将wval左移4位,并把AX的高4位插入wval的低4位
SHRD 双精度右移
mov ax,234Bh
mov dx,7654h
shrd ax,dx,4;AX右移4位,并把DX的低4位插入AX的高4位
串指令
DS:SI 源串段寄存器 :源串变址
NULL
ESI 目标串段寄存器:目标串变址
NULL
CX 重复次数计数器
NULL
AL/AX 扫描值
NULL
D标志 0表示重复操作中SI和DI应自动增量; 1表示应自动减量
NULL
Z标志 用来控制扫描或比较操作的结束
NULL
MOVS 串传送 ( MOVSB 传送字符 MOVSW 传送字 MOVSD 传送双字 )
;传送字符串数据:将ESI寻址的内存数据复制到EDI寻址的内存位置
;复制双字数值
source dword 20 dup(0FFFFFFFh)
target dword 20 dup(?)
.code
cld;方向为正
mov ecx,lengthof source;设置REP计数器
mov esi,offset source;ESI指向source
mov edi,offset target;EDI指向target
rep movsd;复制双字
CMPS 串比较 ( CMPSB 比较字符 CMPSW 比较字 )
;比较字符串:比较分别由ESI和EDI寻址的内存数据
;比较双字
mov esi OFFSET source
mov edi ,OFFSET target
cld;方向为正向
mov ecx, LENGTHOF source;设置重复计数器
repe cmpsd;相等则重复
SCAS 串扫描 把AL或AX的内容与目标串作比较,比较结果反映在标志位
;扫描字符串:比较累加器(AL、AX和EAX)与EDI寻址的内存数据
;扫描是否有匹配字符
alpha BYTE "ABCDEFGH",0
.code
mov edi,OFFSET alpha;EDI指向字符串
mov al,'F';检索字符F
mov ecx,LENGTHOF alpha;设置检索计数器
cld;方向为正向
repne scasb;不相等则重复
jnz quit;若未发现字符则退出
dec edi;发现字符: EDI减1
LODS 装入串 把源串中的元素(字或字节)逐一装入AL或AX中( LODSB 传送字符 LODSW 传送字 LODSD 传送双字 )
;从字符串加载到累加器:将ESI寻址的内存数据加载到累加器
;数组乘法
:本程序将一个32位整数数组中的每个元素都乘以一个常数。
INCLUDE Irvine32. inc
.data
array DWORD 1,2,3,4,5,6,7,8,9,10;测试数据
multiplier DWORD 10;测试数据
.code
main PROC
cld;方向为正向
mov esi,OFFSET array;源数组索引
mov edi,esi;目标数组索引
mov ecx,LENGTHOF array;循环计数器
Ll: lodsd;将[ESI]加载到EAX
mul multiplier;与常数相乘
stosd;将EAX保存到[EDI]
loop Ll
exit
main ENDP
END main
STOS 保存串 是LODS的逆过程
;保存字符串数据L:将累加器内容保存到EDI寻址的内存位置
.data
Count = 100
string1 BYTE Count DUP(?)
.code
mov al,OFFh;要保存的数值
mov edi,OFFSET string1;EDI指向目标字符串
mov ecx,Count;字符计数器
cld;方向为正向
rep stosb;用AL的内容实现填充
REP 当CX/ECX<>0时重复(单个指令处理整个字符串)
rep movsb
REPE/REPZ 当ZF=1或比较结果相等,且CX/ECX<>0时重复
repe cmpsd
REPNE/REPNZ 当ZF=0或比较结果不相等,且CX/ECX<>0时重复
repne scasb
REPC 当CF=1且CX/ECX<>0时重复
repc movsb
REPNC 当CF=0且CX/ECX<>0时重复
repnc movsb
程序转移指令
简单的条件转移指令
JZ(或jE) OPR—————结果为零转移, 测试条件ZF=1;相等跳转
cmp eax,0
jz/je L1;如果ZF=1则跳转
JNZ(或jNE) OPR ————–结果不为零转移,测试条件ZF=0;不等跳转
and dl,10110000b
jnz/jne L2;ZF=0跳转
JS OPR———————-结果为负转移, 测试条件SF=1
SF=1
JNS OPR———————结果为正转移, 测试条件SF=0
SF=0
JO OPR——————— 溢出转移, 测试条件OF=1
OF=1
JNO OPR ——————–不溢出转移 , 测试条件OF=0
OF=0
JP OPR ———————结果为偶转移, 测试条件PF=1
PF=1
JNP OPR ——————–结果为奇转移 , 测试条件PF=0
PF=0
JC OPR ——————– 有进位转移 , 测试条件CF=1
CF=1
JNC OPR ——————–无进位转移, 测试条件CF=0
CF=0
无符号比较条件转移指令(以下指令经常是CMP OPD,OPS后面的指令根据比较结果来实现转移)
JB(或JNAE) opd ————–小于或者不大于等于则转移
小于跳转
JNB(或JAE) opd—————不小于或者大于等于则转移
不小于跳转
JA(或NJBE) OPD—————大于或者不小于等于则转移
mov al,+127
cmp al,-128
ja/njbe L1;不跳转
JNA(或JBE) OPD—————不大于或者小于等于则转移
mov al,+127
cmp al,-128
jna/jbe L1;跳转
带符号比较条件转移指令
JL(或JNGE) ————–小于或者不大于等于则转移
mov ax,5
mov ax,6
jl/jnge L1;跳转
JNL(或JGE)————–不小于或者大于等于则转移
mov edx,-1
cmp edx,0
jnl/jge L1;不跳转
JG(或NJLE)—————大于或者不小于等于则转移
mov ax,5
cmp ax,4
jp/njle L1;大于则跳转
JNG(或JLE)—————不大于或者小于等于则转移
mov ecx,0
cmp ecx,0
jng/jle;跳转
JCXZ
CX=0跳转
JECXZ
ECX=0跳转
JRCXZ
RCX=0跳转
调用子程序与返回指令
CALL 子程序调用指令
call SumOf;调用SumOf过程
RET 子程序返回指令
SumOf proc
.
.
ret
SumOf endp
条件循环指令
LOOP———-按ECX计算器循环
mov ax,0
mov ecx,5
L1:
inc ax
loop L1;每次循环ax加一,循环5次
LOOPZ————为零跳转
loopz L1
LOOPNZ————–非零跳转
loopnz L1
LOOPE——————-相等跳转
loope L1
LOOPNE——————-不等跳转
loopne L1
.IF .ELSE .ELSEIF .ENDIF
.IF conditionl
statements
[.ELSELF condition2
statements]
[ELSE
statements]
.ENDIF
.REPEAT .WHILE
.REPEAT
statements
.UNTIL condition
.WHILE condition
statements
.ENDW
其它指令
OFFSET ——————– 返回偏移地址
mov esi,offset var1; esi=00404000h
mov esi,offset var2; esi=00404000h
SEG ——————– 返回段地址
mov esi,seg var1
mov esi,seg var2
EQU(=) ——————– 等值语句
name EQU expression
name EQU symbol
name EQU <text>
pressKey EQU <"Press any key to continue...", 0>
matrix1 EQU 10 * 10
matrix2 EQU <10 * 10>
PURGE ——————– 解除语句
PURGE,标识符1,标识符2,...,标识符n
DUP ——————– 操作数字段用复制操作符
db x dup();x是重复的次数,()里是要重复的数逗号分隔
str1 db 10 dup ('!@#') ;这就是十个!@#
格式:db 重复的次数 dup (重复的内容)
buf1 db 100 dup(?);开辟100个字节的内存区
SEGMENT,ENDS ——————– 段定义指令
segment_name SEGMENT 【定位类型】 【组合类型】 【类别名】
···;here is your code
segment ends
ASSUME ——————– 段地址分配指令
.data
........
.code
........
assume cs:code,ds:data
start: .......
mov ax,data
mov ds,ax
...
ends
end start
ORG ——————– 起始偏移地址设置指令
ORG 0000H
AJMP MAIN
ORG 0030H
$ ——————–地址计数器的当前值
例如JNE+6,能引用地址计数器的值,每次引用会使地址计数器的值发生改变,地址计数器即当前指令的偏移地址。该指令的转向地址即JNE指令的首地址加6。
PROC,ENDP ——————– 过程定义语句
SumOf proc
.
.
.
ret
SumOf endp;这是一个过程
NAME,TITLE,END ——————– 程序开始结束语句
NULL
MACRO,ENDM ——————–宏定义指令
mPutchar MACRO char
push eax
mov al,char
call WriteChar
pop eax
ENDM
XLAT (TRANSLATE) ——————– 换码指令—-
X DW 1122h,3344h,5566h,7788h
lea bx,X
mov al,03h
xlat
ALIGN ———————伪指令
var byte ?; 00404000h
ALIGN 2
var2 byte ?; 00404002
PTR ———————-运算符
var dword 12345678h
mov ax,word ptr var; 将低16位(5678)送入ax
TYPE
var word ?
var2 byte ?; word,byte都是type,分别代表2,1
LENGTHOF ————–运算符
var1 byte 10,20,30;3
var2 word 30 DUP(?),0,0;32
var3 word 5 DUP(3 dup(?));3*5
var4 byte "1234",0;5
SIZFEOF————-运算符
var word 32 dup(0)
mov eax,sizeof var;eax=32*2=64
LABEL —————伪指令
var1 label word
var2 dword 12345678h;公用一个内存位置,var2未分配空间
mov ax,var1;5678h
mov dx,[var+2];1234h
TYPEDEF————–运算符
var typedef ptr byte;(指针)
.data
array byte 10h,20h,30h
ptr1 var ?
ptr2 var array;指向一个数组
JMP ————无条件跳转到目标地址
top:
.
.
jmp top;不断循环
USES—————等于 push+pop
ArraySum proc uses esi ecx
mov eax,0
L1:
add eax,[esi]
add esi,type dword
loop L1
ArraySum endp
CLC
clc;清除标识位
STC
进位标志置1
ENTER——————-被调用过程自动创建堆栈帧
Mysub proc
enter 8,0
;等效于
Mysub proc
push ebp
mov ebp,esp
sub esp,8
LEAVE——————指令结束一个过程的堆栈帧
Mysub proc
enter 8,0
.
.
leave
ret
Mysub endp
;等效于
Mysub proc
push ebp
mov ebp,esp
sub esp,8
.
.
mov esp,ebp
pop ebp
ret
Mysub endp
LOCAL—————局部变量
Mysub proc
local var:dword;这是一个局部变量
INVOKE—————–CALL替代品,一行调用多个参数
invoke Dumparray,offset array,lengthof array,type array
ADDR——–只能和INVOKE一起
array dword 20 dup(?)
invoke swap
addr array
addr [array+4]
条件标志
ZF 零标志
当结果为负时,SF=1,否则,SF=0
AF 辅助进位标志
运算过程中第三位有进位值,置AF=1,否则,AF=0
PF 奇偶标志
当结果操作数中偶数个"1",置PF=1,否则,PF=0
SF 符号标志
当结果为负时,SF=1;否则,SF=0.溢出时情形例外
CF 进位标志
最高有效位产生进位值,例如,执行加法指令时,MSB有进位,置CF=1;否则,CF=0
OF 溢出标志
若操作数结果超出了机器能表示的范围,则产生溢出,置OF=1,否则,OF=0