数据寻址方式
一、立即数寻址
MOV AX,0102H; 指令代码:B8 02 01
注意:按照低对低、高对高的小端存储原则,低字节放在低地址单元
所以指令代码中是 B8 02 01,而不是 B8 01 02
速度最快
二、寄存器寻址方式
8位寄存器r8 :AH/AL、BH/BL、CH/CL、DH/DL
16位寄存器r16:AX、BX、CX、DX、SI、DI、BP、SP
段寄存器seg :CS、DS、SS、ES
(即除了IP和FLAGS)
三、存储器寻址方式
- 默认段寄存器
寄存器寻址主存 | 默认段寄存器 |
---|---|
BP寄存器 | SS堆栈段寄存器 |
其他寄存器 | DS数据段寄存器 |
- 寻址方式
寻址方式 | 示例 | 源操作数语法 |
---|---|---|
直接寻址 | MOV AX,[2000H] MOV AX,WVAR |
[数值] 直接引用变量名 |
寄存器间接寻址 | MOV AX,[BX] 效果:AX←DS:[BX] |
基址寄存器BX、BP 变址寄存器SI、DI |
寄存器相对寻址 | MOV AX,[BX+06H] MOV AX,[BX+WVAR] MOV AX,WVAR[BX] |
基址寄存器BX、BP 或 变址寄存器SI、DI 加上 8位或16位位移量 |
基址变址寻址 | MOV AX,[BX+SI] MOV AX,[BX][SI] |
基址寄存器BX、BP 加上 变址寄存器SI、DI |
相对基址变址寻址 | MOV AX,[BX+SI-06H] MOV AX,[BX+SI+WVAR] |
基址寄存器BX、BP 加上 变址寄存器SI、DI 加上 8位或16位位移量 |
MOV AX,[WVAR]为直接寻址,假如WVAR的偏移地址为0010H,则该指令等同于MOV AX,[0010H],也等同于MOV AX,WVAR
BX 使用寄存器BX上的数据
[BX] 用寄存器BX的数据作为地址,使用该地址上的数据
[2000H] 使用2000H作为地址,使用该地址上的数据
MOV AX,[BX+WVAR] 等效于 MOV AX,WVAR[BX]
MOV AX,[BX+SI] 等效于 MOV AX,[BX][SI]
MOV AX,[BX+SI+WVAR] 等效于 MOV AX,WVAR[BX+SI] 等效于 MOV AX,WVAR[BX][SI]
- 物理地址
物理地址用逻辑地址来表示,逻辑地址等于:段寄存器内的数据 × 16 + 源操作数表达的地址
即 段地址左移4位 + 偏移地址
EA针对的是带有 [ ] 的寻址方式(即存储器寻址)
基本指令
一、前置知识
- 操作数的表达符号
寻址方式 | 操作数符号及含义 |
---|---|
立即数 | imm:i8或i16 i8 :8位立即数 i16 :16位立即数 |
寄存器寻址 | reg:r8或r16 r8 :8位通用寄存器 r16:16位通用寄存器 seg:段寄存器 |
存储器寻址 | men:m8或m16 m8 :8位存储器操作数 m16:16位存储器操作数 |
- 十六进制表达的数值,若以A-F开头,则要加前导0,否则会被识别为变量名。
- 目的操作数和源操作数的类型要一致(同为字or同为字节)
非法指令:
MOV AL,300 300D=12CH超过8位二进制
MOV AL,050AH AL为字节,050AH为字
MOV [AX],050AH 只知道目的操作数起始地址,不知道是字节还是字
MOV [SP],AX SP为堆栈指针,不能间接寻址
合法指令:
MOV AX,05H 05H会根据AX自动调整为字0005H
MOV AX,300 300D=12CH没有超过16位二进制 - 立即数传给存储单元时,指令中的立即数可以理解为字or字节,如果不显式(byte指示字节,word指示字)指出则为非法指令。
非法指令:
MOV [BX+SI],255;
MOV [BX+SI],0002H;
合法指令:
mov byte ptr [bx+si],255; - 除串操作类指令外,其余操作不可直接实现men到men
- 不可直接实现seg到seg,eg:MOV DS,ES;
不允许立即数到seg,eg:MOV DS,100H
不应该直接改变CS(代码寄存器),eg:MOV CS,[SI],还有IP、FLAGS - 不能给立即数赋值,eg:MOV DATA,2000H
- 定义字变量WVAR,WVAR+1表示字变量WVAR的高字节(从WVAR的起始地址+一个字节)
但是以下指令为非法指令:
mov al,WVAR[0]
尽管WVAR[0]只是表示字节,字节传给8位寄存器仍旧非法,应该将WVAR[0]声明为字节,以下指令为合法指令:
mov al,byte ptr WVAR[0] - 寄存器的数值减1后再赋给另一个寄存器
非法指令:
mov cx,ax-1
合法指令:
dec ax
mov cx,ax
二、数据传送类指令
指令 | 基本格式 | 功能 | 其他 |
---|---|---|---|
传送指令 | MOV reg/men,imm MOV reg/men/seg,reg MOV reg/seg,men MOV reg/men,seg |
把一个字节或字的操作 数从源地址传送到目的 地址 |
仅复制 源操作数不变 不改变标志位 |
交换指令 | XCHG reg,men XCHG reg/men,reg |
源操作数和目的操作数 数据交换(字或字节) |
|
换码指令 | XLAT | AL ← [BX+AL] BX指向的内容加AL 指向的内容作为新地址 新地址指向的内容赋值 给AL |
|
堆栈操作 指令 |
PUSH r16/m16/seg | 先 SP ← SP-2 后 SS:[SP]←r16/m16/seg |
堆栈操作的对象只能 是字,有2个字节, 所以是SP-2 |
POP r16/m16/seg | 先 r16/m16/seg←SS:[SP] 后 SP ← SP+2 |
栈顶指针SP初始时 不是指向SS,而是 指向栈空间另一端 |
|
标志操作 指令 |
CLC | CF←0 | |
STC | CF←1 | ||
CMC | CF←~CF | ||
CLD | DF←0 | 串操作后地址增大 | |
STD | DF←1 | 串操作后地址减小 | |
CLI | IF←0 | ||
STI | IF←1 | ||
地址传送 指令 |
LEA r16,mem | 将存储器操作数的有效 地址(段内偏移地址) 传送到16位通用寄存器 |
不是将men的内容作为 地址并将该地址的数据 传给r16,而是直接把这 个地址赋值给r16 |
seg一般只出现在MOV 、PUSH、POP
操作符OFFSET,可以在汇编过程中获得变量的偏移地址
三、算术运算类指令
指令 | 基本格式 | 功能 | 对标志位 的影响 |
其他 |
---|---|---|---|---|
加和减 指令 |
ADD dest,src | dest←dest + src | 全部 | |
SUB dest,src | dest←dest - src | 全部 | ||
带进位 加和减 指令 |
ADC dest,src | dest←dest+src+CF | 全部 | 对寄存器DX.AX 中较高位寄存器 DX进行操作, 相当于低位寄存 器AX,进行了 进位 |
SBB dest,src | dest←dest-src-CF | 全部 | 类似于ADC,只 是进行了借位 |
|
比较指令 | CMP dest,src | dest - src | 全部 | 结果不送回目的 操作数通过该指 令影响标志位 |
增量指令 | INC reg/men | 自增 | 不影响CF | 非法指令 INC [0002H] 不知道是对字还 是字节进行操作 |
减量指令 | DEC reg/men | 自减 | 不影响CF | |
求补指令 | NEG reg/men | reg/men←0-reg/men | 全部 | |
符号扩展 指令 |
CBW | 字节转为字 AL→AX 只是位数变多了 不改变数值大小 |
不影响 | AL为1xxx xxxx, 改变后为AX 1111 1111 1xxx xxxx,(AL最 高位为1则全1, 为0则全0) |
CWD | 字转为双字 AX→DX.AX |
不影响 | CBW和CWD只 针对有符号数, 无符号数直接 高位清0 |
|
乘法指令 | MUL reg/men | AX←AL×r8/m8 DX.AX←AX×r16/m16 |
如果乘积的 高一半是 低一半的 符号扩展 则OF=CF=0 否则均为1 (即高一半 含有效值) 其他标志位 无定义, 取值随机 |
无符号乘法, 加减指令利用 CF、OF区分 有无符号 |
IMUL reg/men | AX←AL×r8/m8 DX.AX←AX×r16/m16 |
同MUL | 有符号乘法 | |
除法指令 | DIV reg/men | AL←AX÷r8/m8的商 AH←AX÷r8/m8的余数 AX←DX.AX÷r16/m16 的商 DX←DX.AX÷r16/m16 的余数 |
状态标志位 没有定义, 但可能产生 溢出,此时 CPU产生 编号为0 的内部中断 |
|
IDIV reg/men | AL←AX÷r8/m8的商 AH←AX÷r8/m8的余数 AX←DX.AX÷r16/m16 的商 DX←DX.AX÷r16/m16 的余数 |
同DIV | 余数和被除数 符号相同 |
- 溢出(OF)不是最高位有进位(CF),而是正数相加变负数,负数相加变正数(补码形式,最高位(符号位)变化)
- 十进制数64,压缩BCD码为64H,非压缩BCD码为0604H
- DAA和DAS分别实现加法和减法的压缩BCD码调整
AAA、AAS、AAM和AAD分别实现加减乘除法的非压缩BCD码调整
四、位操作类指令
指令 | 基本格式 | 功能 | 对标志位的影响 | 其他 |
---|---|---|---|---|
逻辑运算 指令 |
AND dest,src | dest←dest ^ src | CF=OF=0 影响SF、ZF、PF AF未定义 |
|
OR dest,src | 或 | 跟“与”一样 | ||
XOR dest,src | 异或,同为0, 异为1 |
跟“与”一样 | ||
TEST dest,src | 跟“与”一样 结果不返回 |
跟“与”一样 | 只用来影响 标志位 |
|
NOT reg/men | 非 | 不影响标志位 | ||
移位指令 | SHL reg/men,1/CL | 逻辑左移 reg/men左移 1/CL位 最低位补0 最高位进入CF |
用最后移入CF的位 设置进位标志CF 最高位操作数改变 则OF=1,否则为0 若移位次数 >1 则OF不确定 |
移位位数 大于1时 只能用 寄存器CL 来表示 移位数 |
SHR reg/men,1/CL | 逻辑右移 reg/men右移 1/CL位 最高位补0 最低位进入CF |
和SHL一样 | ||
SAL reg/men,1/CL | 算术左移 和SHL一样 |
和SHL一样 | 左移相当于 ✖2 |
|
SAR reg/men,1/CL | 算术右移 reg/men右移 1/CL位 最高位不变 最低位进入CF |
和SHL一样 | ||
循环移位 指令 |
ROL reg/men,1/CL | 不带进位 循环左移 移出的位补到 末位 |
移出的位给CF OF和SHL一样 |
书P39 示意图 |
ROR reg/men,1/CL | 不带进位 循环右移 移出的位补到 首位 |
和ROL一样 | ||
RCL reg/men,1/CL | 带进位 循环左移 移出的位给到 CF CF给到末位 |
和ROL一样 | ||
RCR reg/men,1/CL | 带进位 循环右移 移出的位给到 CF CF给到首位 |
和ROL一样 |
五、控制转移类指令
- 目的地指令所在的存储器地址称为目的地址、目标地址或转移地址
- 代码段寄存器CS指定段地址,指令指针IP指定偏移地址
- 表达相对寻址和直接寻址时,采用目的地址的标号label
表达间接寻址时,采用寄存器名和存储器操作数 - 段内转移(近转移):不改变CS,只改变IP偏移地址;其中位移量可以用一个字节表达的称为“短转移”
段间转移(远转移):需要改变CS段地址和IP偏移地址
指令 | 基本格式 | 功能 | 其他 |
---|---|---|---|
无条件 转移指令 |
JMP label | IP←IP+距离 标号处的位移量 |
跳到标号处开始执行指令 |
JMP r16/m16 | IP←r16/m16 | ||
JMP far ptr label | IP←标号的偏移地址 CS←标号的段地址 |
跳到标号处开始执行指令 | |
JMP far ptr men | IP←[men] CS←[men+2] |
主存中连续的两个字单元 低字送IP,高字送CS |
|
条件转移 指令 |
JCC label | 单个标志位的 状态判断 如果条件满足 则转移去label执行 IP ← IP+8位位移量 |
8位位移量 只能实现-128~+127个 单元范围的跳转 条件CC见书本P42 转移指令前,常有CMP、 TEST、加减运算、 逻辑运算 |
比较数据大小 利用标志位CF、ZF 或OF、SF、ZF 确定高低、是否相等 |
无符号数用高(Above) 低(Below) 有符号数用大(Greater) 小(Less) N表示不,E表示相等 具体见书P44 |
||
循环指令 | LOOP label | CX←CX-1 CX≠0,转移 |
短转移寻址方式 (段内-128~+127) 循环指令不影响标志 |
LOOPE label | CX←CX-1 CX≠0且ZF=1,转移 |
||
LOOPNE label | CX←CX-1 CX≠0且ZF=0,转移 |
||
JCXZ label | CX=0,转移 | ||
子程序 调用指令 |
CALL label | 相对寻址的段内调用 | IP入栈:SP←SP-2 SS[SP]←IP 实现转移:IP←IP+16位位移量 |
CALL r16/m16 | 间接寻址的段内调用 | IP入栈:SP←SP-2 SS[SP]←IP 实现转移:IP←r16/m16 |
|
CALL far ptr label | 直接寻址的段间调用 | CS入栈:SP←SP-2 SS[SP]←CS IP入栈:SP←SP-2 SS[SP]←IP 实现转移:IP←label偏移地址 CS←label段地址 |
|
CALL far ptr men | 间接寻址的段间调用 | CS入栈:SP←SP-2 SS[SP]←CS IP入栈:SP←SP-2 SS[SP]←IP 实现转移:IP←[men] CS←[men+2] |
|
子程序 返回指令 |
RET | 无参返回 | 弹出IP:IP←SS:[SP] SP←SP+2 段间返回则还要弹出CS: CS←SS[SP],SP←SP+2 |
RET i16 | 带参返回 | 弹出IP:IP←SS:[SP] SP←SP+2 段间返回则还要弹出CS: CS←SS[SP],SP←SP+2 调整指针:SP←SP+i16 调整指针可以废除若干 执行CALL指令之前入栈 的参数 |
|
中断指令 | INT i8 | 中断调用指令 产生i8号中断 |
|
IRENT | 中断返回指令 | ||
INTO | 溢出中断指令 若溢出标志OF=1 则产生4号中断 否则顺序执行 |
中断指令和系统功能调用:
- A产生“中断”,在A的“断点”处处理“中断服务程序”
- 中断服务程序本身可以安排在主存的任何位置,但起始地址则按向量号顺序存放在最低000H~3FFH的1KB物理存储器中
- ROM-BIOS和DOS功能调用方法:
1)在AH寄存器中设置系统功能调用号(即中断服务程序的哪个子功能)
2)在指定寄存器中设置入口参数
3)用中断调用指令(INT i8)执行功能调用
4)根据出口参数分析功能调用执行情况 - DOS常用输入输出功能调用
子功能号 | 功能 | 入口参数 | 出口参数 |
---|---|---|---|
AH=01H | 输入一个字符 | AL=输入字符的ASCII码 | |
AH=02H | 输出一个字符 | DL=欲显示字符的ASCII码 | |
AH=09H | 输出一个字符串 | DS:DX=欲显示的字符串 在内存中的首地址 |
|
AH=0AH | 输入一个字符串 | DS:DX=输入字符串 将在内存缓冲区的首地址 |
|
AH=0BH | 判断是否有输入 | AL=0,没有输入 AL=FFH,已有输入 |
- AH=09H号功能的调用,要求字符串必须以字符“$”(ASCII码为24H)结束
- AH=0AH号功能的调用,要求
第一个字节填入最多欲接收的字符个数(1~255,包括最后的回车)
第二个字节存放实际输入字符的个数(不包括最后的回车)
第三个字节开始存放实际输入的字符串ASCII码(最后总是回车符)
多出的字符被丢掉,最后一个字符是回车符 - ROM-BIOS常用的输入输出功能调用
子功能号 | 功能 | 入口参数 | 出口参数 | 对应DOS 功能号 |
---|---|---|---|---|
AH=00H INT 16H |
输入一个字符 | AX=键值代码 | 01H | |
AH=01H INT 16H |
判定是否有输入 | ZF=1,没有输入 ZF=0,已有输入 |
0BH | |
AH=0EH INT 10H |
输出一个字符 | AL=输出字符的ASCII码 BH=显示页号 |
02H |
- AH=00H,INT 16H输入时,
按下标准ASCII码键:AL=ASCII码,AH=扫描码
按下扩展键:AL=00H,AH=健扩展码
按下“ALT+小键盘数字按键”:AL=ASCII码,AH=00H - AH=0EH,INT 10H输出时,通常使BX=0
六、处理器控制类指令
指令 | 基本格式 | 功能 | 其他 |
---|---|---|---|
空操作指令 | NOP | 空操作 实现软件延时 预留指令空间 填充代码空间 |
占用一个字节存储单元 空耗一个指令执行周期 |
暂停指令 | HLT | 暂停指令 用于等待中断 |
CPU发生复位或外部 中断时,CPU脱离暂停 状态 |
段超越前缀指令 | |||
LOCK | 封锁总线的前缀指令 | ||
交权指令 ESC |
与浮点协处理器有关 | ||
等待指令 WAIT |