1、通用数据传送指令
mov DST,SRC
push
pop
xchg 交换
注意:段寄存器不能直接用Mov 传送,要先给通用寄存器,后给段寄存器 mov ds, xxx 但是不可以给段寄存器CS赋值 mov cs,** 错误
mov AL ‘E’ ;把立即数(字符E的ASCII码送到AL寄存器中) mov BX OFFSET TABLE ;把TABLE的偏移地址(不是内容送到BX寄存器中),其中OFFSET为属性操作符。 mov AX Y[BI][SI] ;把(BI)+(SI)+ 位移量Y 的存储单元的内容送到AX寄存器中
2、push SRC
3、pop DST
push pop 在16位指令中,必须是字的方式存取
8086 push,pop 不能用立即数寻址方式,切pop不允许使用CS寄存器。
286及其后继允许立即数进栈
push pop不影响标志位
PUSHA(16) 所有寄存器进栈 AX,BX,CX,DX 指令执行前的 SP,BP,SI,DI SP=SP-16
PUSHAD(32) 所有寄存器进栈 EAX,EBX,ECX,EDX 指令执行前的 ESP,EBP,ESI,EDI SP=SP-32
POPA
POPAD
XCHG指令不允许的情况有以下四种:
1. 不能同时都为内存操作数
2. 任何一个操作数都不能为段寄存器 重要 凡是S结尾的都不行
3. 任何一个操作数不能为立即数 凡是有立即数 都不对
4. 两个操作数的长度必须相等 长度必须相当
IN 输入
OUT 输出
XLAT 换码
2、用法:
(1)IN AX/AL, I/O端口地址 表示从外部设备输入数据给累加器
IN AX,80H MOV DATA_WORD,AX ;这两条指令把端口28H的内容经过AX传送到存储单元DATA_WORD中
mov DX,3FCH IN EAX,DX
(2)OUT I/O端口地址,AX/AL 表示将累加器的数据输出给外部设备
OUT 5,AL ;从AL中输出一个字节到5端口中
说明:当I/O端口地址不超过8位时,则直接放在指令中,若超过8位,则用DX间址。比如:
MOV DX,8080H IN AL,DX
XLAT指令: DS:【BX+AL】为地址 , 取出表中一个字节送到AL中
查表指令不影响标志位。
三、地址传送指令
LEA 有效地址传送器
LDS 指针送寄存器和DS
LES 指针送寄存器和ES
LEA REG,SRC 只是交换REG,SRC的值。没有处理段寄存器。下面的指令需要处理段寄存器
LEA BX,LIST MOV BX,OFFSET LIST ;这两条指令时相同的,使用第二条速度更快,但是这条指令不能和诸如 LIST[SI]或[SI]等复杂的操作数相连
LDS reg,mem REG <-- mem SREG <-- SRC+2
四、标志寄存器传送指令
LAHF 标志入送AH 用于将标志寄存器的低八位送入AH,即将标志寄存器FLAGS中的SF、ZF、AF、PF、CF五个标志位分别传送到累加器AH的对应位(八位中有三位是无效的)
SAHF AH送标志寄存器
PUSHF/PUSHFD 标志入栈
POPF/POPFD 标志出栈
五、类型转换指令
CBW (convert byte to word)
CWD/CWDE (convert word to double)
CDQ (convert double to quad) 双字转换为4字
BSWAP(byte swap) 字节交换
1.CBW
该指令的隐含操作数为AH和AL。其功能是用AL的符号位去填充AH,即:当AL为正数,也就是最高位为0 ,则AH=0,否则,AH=0FFH。指令的执行不影响任何标志位。
2.CWD
该指令的隐含操作数为DX和AX,其功能是用AX的符号位去填充DX,形成DX:AX双字,即如果(AX)的最高有效位为0,则(DX)为0,否则为0FFFFH。指令的执行不影响任何标志位。
CWDE ;80386+
该指令的隐含操作数为EAX和AX,其功能是用AX的符号位填充EAX的高字位。指令的执行不影响任何标志位。
3.CDQ ;80386+
该指令的隐含操作数为EDX和EAX,指令的功能是用EAX的符号位填充EDX。指令的执行不影响任何标志位。
(EAX)=9668 8368H BSWAP EAX -->(EAX)=6883 6896H
SUB(subduction) 减法
SBB 带借位减法 -CF
DEC 自减1
NEG 求补 求反求反指令时NOT 加1
CMP 比较 和sub一样,但是并不保存结果,只是根据结果设置条件标志位。指令后往往跟一条条件转移指令,根据比较结果产生不同的程序分支。
减法中OF 设置方法:若两个数符号不同,且结果和减数符号相同,则OF=1.除这个情况,OF=0。OF=1说明带符号数的减法溢出。结果是错误的。0
neg是求补指令,举几个例子(以下数据均为16进制):
D8 求补之后是28 28+D8=100
14 求补之后是EC EC+14=100
1234求补之后是EDCC EDCC+1234=10000
1111求补之后是EEEF 1111+EEEF=10000
取反指令是not,也就是“非”指令,举几个例子:
1:MUL SRC 无符号数的乘法
SRC是一个乘数,不能是立即数
2:IMUL SRC 有符号数乘法,与MUL SRC相同
MUL 如果高一半为0,则CF和OF都为0,否则为都为1 --这样可以检测相称的结果是字节还是字
IMUL 如果高一半世低一半的符号扩展,则CF和OF都为0,否则为1
除法指令DIV
无符号除法IDIV
整数除法
jcc指令是根据标志位工作的。jcc的具体行为在于它前面一条或者多条指令具体怎么影响标志位的。
结果为0,则ZF=1。JZ指令是在ZF=1时跳转,ZF=0时不跳转。
表一:测试单个标志位的Jcc指令:
Jcc指令 |
描述 |
转移条件 |
JC,JB,JNAE |
有进位时转移 |
CF=1 |
JNC,JNB,JAE |
无进位时转移 |
CF=0 |
JZ,JE |
为零(相等)时转移 |
ZF=1 |
JNZ,JNE |
非零(不等)时转移 |
ZF=0 |
JS |
为负时转移 |
SF=1 |
JNS |
为正时转移 |
SF=0 |
JO |
溢出时转移 |
OF=1 |
JON |
不溢出时转移 |
OF=0 |
JP,JPE |
‘1’的个数为偶数时转移 |
PF=1 |
JNP,JPO |
‘1’的个数为奇数时转移 |
PF=0 |
表二:用于带符号数比较的Jcc指令(常用在CMP指令之后,以判断带符号数的大小)
Jcc指令 |
描述 |
转移条件 |
JG,JNLE |
大于(不小于等于)时转移 |
SF=OF且ZF=0 |
JGE,JNL |
大于等于(不小于)时转移 |
SF=OF |
JL,LNGE |
小于(不大于等于)时转移 |
SF<>OF |
JLE,LNG |
小于等于(不大于)时转移 |
SF<>OF或ZF=1 |
表三:用于无符号数比较的Jcc指令(常用在CNO指令之后,以判断无符号数的大小)
Jcc指令 |
描述 |
转移条件 |
JA,JNBE |
大于(不小于等于)时转移 |
CF=0且ZF=0 |
JAE,JNB,JNC |
大于等于(不小于)时转移 |
CF=0 |
JB,LNAE,JC |
小于(不大于等于)时转移 |
CF=1 |
JBE,LNA |
小于等于(不大于)时转移 |
ZF=1或CF=1
|
28、位测试指令
BT(位测试)
写法:BT REG16/MEM16,REG16/IMM8;或BT REG32/MEM32,REG32/IMM8;
作用:CF=DEST的第index位,dest不变。
BTS(位测试并置位)
写法:BTS REG16/MEM16,REG16/IMM8;或BTS REG32/MEM32,REG32/IMM8;
作用:CF=DEST的第index位,dest的第index位=1;
BTR(位测试并复位)
写法:BTR REG16/MEM16,REG16/IMM8;或BTR REG32/MEM32,REG32/IMM8;
作用:CF=DEST的第index位,dest的第index位=0;
BTC(位测试并复位)
写法:BTC REG16/MEM16,REG16/IMM8;或BTC REG32/MEM32,REG32/IMM8;
作用:CF=DEST的第index位,dest的第index位取反;
说明:若dest为寄存器,则以index除以16(dest为reg16)或32(dest为reg32)的余数作为测试位。当然,index最好不要超出操作数的位数。
若dest为内存操作数,则无论其类型为字或双字,测试位为相对于起始地址的位移,例如,设BX=50,X为字类型的变量,则执行指令BT X,BX;后,CF=X+6单元的第2位,因为50%8=6余2.
BTS、BTC、BTR指令可用于并发程序设计。
29、位扫描指令
BSF(前向位扫描)
写法:BSF reg16/reg32, reg16/reg32/mem16/mem32;(类型须匹配)
作用:dest=src中值为1的最低位编号(从低位向高位搜索)
BSR(后向位扫描)
写法:BSR reg16/reg32, reg16/reg32/mem16/mem32;(类型须匹配)
作用:dest=src中值为1的最高位编号(从高位向低位搜索)
说明:BSF和BSR搜索SRC操作数中首次出现1的位置,BSF从低位向高位搜索,BSR反之。若找到一个1,则置ZF=0,并存储位编号到DEST操作数中。若SRC=0,即没有1出现,则置ZF=1,且dest的值不确定。
比如,有如下二进制数0111 1111 1010 0100
执行bsf后,位编号为2,执行bsr后,位编号为14.
(1)将一个寄存器或内存单元中的数据向左移位
(2)将最后移出的一位写入CF中
(3)最低位用0补充
如果移动位数大于1时,必须将移动位数放在cl中。BUF DB 'hello world',0 ;定义被填充的缓冲区 MOV DI,BUF ;将BUF的地址赋值给DI MOV AL,0FFH ;给AL寄存器赋值 MOV CX,11 ;填充缓冲区长度 CLD ;清零方向标志,DI地址自增 REP STOSB ;开始填充
最终,BUF内存单元被FFH填充掉
CX中可以存放循环次数,
在保护模式,cpu通过段选择子找到段描述符表,来寻址。包括全局段表,局部段表,中断表。段选择子通过LGDR寄存器找到全局段表,通过IDTR找到中断表。lgdb即是设置全局表的地址和大小,lidt即是设置lidt的地址和大小
bsfl汇编指令:
intel汇编指令:bsf oprd1,oprd2;
顺向位扫描(bit scan forward)
从右向左(从位0-->位15或位31)扫描字或双字操作数oprd2中第一个含"1"的位,并把扫描到的第一个含'1'的位的位号送操作数oprd1
AT&T格式汇编指令bsfl类似bsf,只是源操作数和目的操作数顺序相反。
汇编语句bsfl %eax, %ebx, 把%eax的内容从0位开始扫描,找到第一个为1的赋给%ebx.
btrl %eax, %ebx, 把%ebx中的%eax位复位。
用C内嵌汇编实验了一下,确实如此。