汇编语言Assembly Language.asm--8086(持续更新)
汇编语言Assembly Language.asm--8086
数据转移指令MOV 数据流向图
XCHG OPD,OPS数据交换指令
功能:将源操作数和目的操作数内容互换
AX=1234H XCHG AL,AH 执行后(AX)=3412H
注意:不能使用段寄存器执行交换操作
XCHG DS,AX ×交换指令不能使用段寄存器segment register
XCHG BUF1,BUF2 ×两个操作数不能同时为存储器操作数;
MOV ES,SEG BUF; ×变量不能直接送入ES,要通过其他寄存器送入;
MOV DS,DATA; ×变量不能直接送入ES,要通过其他寄存器送入;
MOV CS,AXL; ×CS只能读出,不能送入;
MOV DS,BUF; ×BUF为字变量,其所在的段与DS建立联系;语法正确,执行结果可能不对;
立即数只能送出,不能送入;只能作为源操作数;
不能将立即数送入DS,ES,FS,GS,SS
不能使用MOV将任何数据送入CS;
不能用MOV修改CS、IP,只能用JMP指令;
ADD WORD PTR [SI],[DI] ×两个操作数都是存储器操作数
指令的共同要求:
- 双操作数的操作数类型(字节数)必须匹配;MOV AX,BL ×
- 目的操作数不能是立即数;CMP 2,AX ×
- 目的操作数和源操作数不能同时为存储器操作数;MOV BUF1,BUF2 ×
MOVSX指令(386指令)有符号数传送指令;相当于类型转换;
功能:将源操作数的符号向前扩展(前面的数全部与符号位相同)成与目的操作数相同的数据类型后,再送入目的地址对应的单元中;扩展之后的数和原数的值相同,但是类型不同(所占字节数变多了);
OPS不能是立即数;
OPD必须是16/32位寄存器;
源操作数位数必须小于目的操作数的位数;
例题:MOV BL,0E3H MOVSX EBX,BL (EBX)=?
|
BYTE0 DB 0A8H MOV BL,BYTE0 MOVSX ECX,BL MOVSX EBX,BYTE0 |
0E3H=11100011B→BL BL→EBX,符号位1向前扩展,高8位全扩展成1 (EBX)=1111 1111 1110 0011B=0FFE3H |
0A8H=1010 1000B→BL BL→ECX,符号位1向前扩展,高8位全1 (ECX)=1111 1111 1010 1000B=0FFA8H |
立即数immediate operand:
- 立即数可以有三种表示方式,二进制、十进制、十六进制;
- 十六进制立即数需加后缀H;二进制立即数需加B;十进制立即数不需要后缀;
- 十六进制立即数,如果最前面一个数是字母,需要在字母前加0;
- FFH应该表示为0FFH,从而告诉编译器这是一个立即数,而不是一个变量;
- 立即数只能作为源操作数,不能作为目的操作数;
- 立即数低字节存放在低地址,高字节存放在高地址;小端模式;
- 反过来存放,也就是低字节存放在高地址,称为大端模式;
BP、EBP、ESP系统默认操作数在堆栈中,等同于SS:[R];base pointer,stack pointer;
其他情况下,默认操作数在DS寄存器中;
从目标地址中取多少数据,取决于目标寄存器,AX作为目标寄存器,则取16位,AH作为目标寄存器,则取8位,以此类推;数据类型,取决于目标操作数类型,目标操作数是几个字节,就取几个字节;
SP指向栈顶;
指针寄存器包括堆栈寄存器SP(stack pointer)和基数指针寄存器BP(base pointer),变值寄存器包括源变址寄存器SI(source index)和目的变值寄存器DI(destination index)。这4个寄存器都是16位寄存器,这些寄存器在运算过程中也可以用来存放操作数(只能以字为单位),但经常的用途是在段内寻址时提供偏移地址;
SP,BP一般与段寄存器SS联用,以确定堆栈寄存器中某一单元的地址,SP用以指示栈顶的偏移地址,而BP可作为堆栈区中的一个基地址,用以确定在堆栈中的操作数地址。
SI,DI一般与段寄存器DS联用,以确定数据段中某一存储单元的地址,SI,DI具有自动增量和自动减量的功能,这一点使在串操作指令中用做变址非常方便,SI作为隐含的源变址DS联用,DI作为隐含的目的变址和ES连用,从而达到在数据段和附加段中寻址的目的;
描述符表(descriptor table)
简称 |
全称 |
描述 |
GDT |
global descriptor table 全局描述符表 |
每一个系统只能有一个,所有的程序和任务共享使用;通过指令lgdt将GDT的入口地址加载到GDTR寄存器中。 |
LDT |
local descriptor table 局部描述符表 |
可以定义多个,可以被隔离的任务单独定义也可以被多个任务共享;LDT在系统中作为一个段存储,通过指令lldt将段描述符加载到LDTR寄存器中,GDT必须包含LDT段的描述符。 |
IDT |
Interrupt descriptor table 中断描述符表 |
保存256个门描述符。门描述符包括中断门描述符、陷阱门描述符和任务门描述符 |
GDTR=global descriptor table register=全局描述符表寄存器;
LDTR=local descriptor table register=局部描述符表寄存器;
Privilege英 /ˈprɪvəlɪdʒ/ 美 /ˈprɪvəlɪdʒ/n. 特权,特殊待遇;
特权级=PL=Privilege Level
描述符特权级(DPL,Descriptor Privilege Level) |
实施特权级保护的第一步,是为所有可管理的对象赋予一个特权级,以决定谁能访问它们。每个 Descriptor 都具有描述符特权级(DPL,Descriptor Privilege Level)字段,Descriptor 总是指向它所“描述”的目标对象,代表着该对象,因此该字段(DPL)实际上是目标对象的特权级。 |
当前特权级(CPL,Current Privilege Level)
|
当处理器正在一个代码段中取指令和执行指令时,那个代码段的特权级叫做当前特权级(Current Privilege Level, CPL)。 正在执行的这个代码段,其选择子位于段寄存器CS中,其最低两位就是当前特权级的数值。 |
请求特权级(RPL,Request Privilege Level) |
RPL也就是指请求者的特权级别(Requestor’s Privilege Level)。 |
特权指令(Privileged Instructions) |
不同特权级别的程序,所担负的职责以及在系统中扮演的角色是不一样的。计算机系统的脆弱性在于一条指令就能改变它的整体运行状态,比如停机指令hlt 和对控制寄存器CRO的写操作,像这样的指令只能由最高特权级别的程序来做。因此,那些只有在当前特权级 CPL 为 0 时才能执行的指令,称为特权指令(Privileged Instructions)。 |
输出特权级(I/O Privilege Level) |
在处理器的标志寄存器EFLAGS中,位13、位12是IOPL位,也就是输入/输出特权级(I/O Privilege Level),它代表着当前任务的I/O特权级别。某些指令,例如IN,OUT,CLI需要 I/O 特权,这些操作根据 IOPL 和 CPL 确定合法性。 |
CPU特权级别
Intel CPU 拥有四个特权级别,由r0到r3,由 寄存器 中的两个隐藏位(bit)指定:
00为r0,01为r1,10为r2,11为r3。
权限大小: r0>r1>r2>r3,每种特权级别所能执行的 CPU指令 都不同,r0能执行所有 指令,其它三个能执行的 指令 依次递减。
Windows 使用r0作为 内核态 特权级别,使用r3作为 用户态 特权级别,其它 CPU 和系统具体情况不了解,应该大同小异。
程序员在用户程序开发过程中,会遇到两个基本概念即用户态和内核态,我们所说的模式切换,就是用户态和内核态之间的切换。
用户态和内核态其实是CPU的特权级,所以模式的切换就是CPU特权级的切换,模式等同于特权级,不同的模式表示CPU处于不同的特权级下,因此CPU特权级的切换不能局限于用户态到内核态之间,理论上CPU可以在任何特权级之间互相切换。
CPU特权级表示处理器访问计算机资源时,CPU所处的特权级即CPL,CPU处于不同的特权级,它能访问的计算机资源范围不同,计算机资源包括内存段(代码段,数据段,栈段),IO设备,核心数据结构。
特权级根据权限大小,分为4个等级即0,1,2,3,如下图
程序访问流程
虚拟地址→LDTR→GDT→GDTR→LDT→程序段
LDTR局部描述符表寄存器
GDTR全局描述符表寄存器
全局描述符表
- Global Description Table 简称GDT
- 只有一个,GDT最大可为64KB,存放8192个描述符
- 操作胸痛所使用的段描述符
- 各个LDT段的描述
- GDT包括OS代码段描述符、OS数据段描述符、OS堆栈段描述符、各个局部段描述符LDT;
局部描述符表
Local Description Table 简称LDT
- 一个LDT是一个系统段,最大可为64KB,最多可以存放8192个描述符。
- (64KByte/8Byte per Descriptor)
- 对每一个程序,都建立一个局部描述符表(LDT)
- 描述符的集合:描述程序的代码段、数据段、堆栈段...
段的保护
要保护一个段,应该提供哪些信息?这些信息存放在何处?
- 段的起始位置(段基地址)
- 段的大小(段界限)
- 段的特权级
- 段的属性(是代码段、数据段,还是堆栈段)
- (数据段是否可写?代码段是否可读出?)
- 段的位置(在内存还是在磁盘?)
- 段的类型(在系统段还是用户段?)
- 段的使用(段被访问过,还是没有?)
内存分段的意义
- 在多任务环境下,系统中有多个程序在运行;
- 程序之间需要隔离!
- 分段是存储管理的一种方式,为保护提供基础;
- 不同程序在不同段中;
- 一个程序可以包含多个段;
- 段用于封闭具有共同属性的存储区域;
程序的本质:数据以及对数据的加工。
汇编语言学习目标
- 深刻理解计算机工作的本质
- 掌握语法:指令格式(关键:寻址方式)
- 掌握语义:指令功能(关键:分类记忆)
- 灵活应用:阅读、编写程序(关键:实践)
构建主义学习理论:从已有的知识经验中生长出新的知识经验;
学习汇编语言的意义
- 理解C等高级语言的最好途径;
- 为什么调用一个函数后,能正确返回?
- 函数之间是如何传递参数的?
- 为什么局部变量的作用域只在函数内部?
- 递归程序如何理解?
- 数组越界访问时怎么回事?
- 指针是如何指向对应对象的?
- Union结构是如何转换的?
- 解密程序、逆向工程、病毒木马分析和防止的唯一选择;
- 了解操作系统运行细节的最佳方式;
- 特性场合下编写程序的必然选择;
了解计算机工作原理和后续课程学习的基础;
MODEM=MOdulator+DEModulator
调制器=modulator:数字信号→模拟信号
解调器=demodulator:模拟信号→数字信号
modem英 /ˈməʊdem/ 美 /ˈmoʊdəmˌˈmoʊdem/调制解调器(等于 modulator-demodulator)
半双工(一条线):收完再发,发完再收,分时使用;
全双工(两条线):一条接收,一条发送,同时进行;
中断向量:段基址CS占2字节,偏移地址IP占2字节,共4字节;
中断向量表:低地址存放IP,高地址存放CS;
8086共支持256个中断向量,共占用256*4=1024字节(1KB)
向量表地址范围:0000H-03FFH
分类,共256个 |
类型 |
专用中断*5 |
0:除法中断 1,单步中断 2,NMI中断, 3,断点中断 4,溢出中断 |
备用中断*59 |
类型5-类型3FH 不允许用户改变其用途; 10-1FH为ROM-BIOS中断; 21H为DOS系统调用; |
用户中断*192 |
类型40H-FFH 由用户自定义 |
中断处理优先级:
- 除法错误中断、溢出中断、INT N中断、断点中断;
- 非屏蔽中断NMI;
- 可屏蔽中断INTR;
- 单步中断;
- NMI=Non Maskable Interrupt=不可屏蔽中断(即CPU不能屏蔽)
- INTR=INTerrupt Request=中断请求
- 中断向量=中断服务程序的CS:IP=中断服务程序的入口地址
- 中断向量表=各种中断的服务程序的CS:IP地址列表=各种中断服务程序的入口地址列表
中断:用以提高计算机工作效率;
中断:是指在正常执行程序过程中,由于内部/外部事件或由程序的预先安排,引起CPU暂时中断当前程序的运行,而转去执行为事件服务的子程序,带中断服务子程序执行完毕后,CPU再返回到暂停处(断点)继续执行原来的程序;
中断技术的优点:并行操作、实时处理、故障处理、分时操作;
中断源:能引起中断的外部设备或内部原因称为中断源;
- 设备中断:键盘、打印机等的数据传送请求;
- 指令中断:为方便用户使用系统资源或调试软件而设置的中断指令INT N;
- 故障中断:如电源掉电、奇偶校验错误、协处理器中断请求等;
- 实时时钟中断:定时检测和时间控制;
- CPU运算错误:除法出错、运算溢出、程序调试断点;
存储器
用途 |
内存=内存储器=主存储器 |
外存=外存储器=辅助存储器 |
|
高速缓存cache,位于CPU和主存之间 |
|
介质 |
半导体存储器、磁表面存储器、光表面存储器 |
读写功能 |
只读存储器ROM、随机存储器RAM |
IO端口
分类 |
定义 |
优点 |
缺点 |
统一编制=存储器映射 |
端口和存储单元统一编制,将IO端口地址置于1MB的存储器空间中,在整个存储器空间中划出一部分空间给外设端口,把它们看做存储器单元对待;
|
CPU访问存储器的各种寻址方式都可以用于寻址端口,访问端口和访问存储器单元在形式上完全一样; 使用通用指令访问 ; |
端口占用存储器地址空间, 使存储器容量更加紧张; 端口指令长度增加,执行时间较长,译码复杂; |
独立编址=IO映射 |
端口单独编制构成一个IO空间,不占用存储器地址;CPU设置了专门的输入输出指令IN/OUT来访问端口; |
不占用存储器地址; 指令较短,执行较快,译码简单; |
指令类别少; 需要专用指令来访问; CPU必须提供控制信号,以区分访问存储还是IO; |
8086结构
分类 |
组成 |
功能 |
执行部件=EU =execution unit |
算术逻辑单元ALU*1 通用寄存器*8 状态标志寄存器FLAG*1 数据暂存寄存器*1 控制电路 |
从BIU指令队列,取出指令 向BIU发出指令,取出数据 执行指令的全部功能 向BIU发出指令,写入结果
|
总线接口部件=BIU =bus interface unit |
段地址寄存器*4 指令指针寄存器IP*1 指令队列缓冲器*1 地址加法器*1 总线控制电路 |
从指令单元取出指令 将指令送至缓冲器或EU 从指定单元或外设取出操作数 将操作数送至EU 将EU运算结果送至存储单元或外设 |
寄存器*14
分类 |
简称 |
全称 |
中文名 |
作用 |
|
通用*8 |
数据*4 |
AX-AH/AL |
accumulator |
累加器 |
乘除、IO |
BX-BH/BL |
base |
基地址 |
寻址 |
||
CX-CH/CL |
count |
计数 |
循环、字符串 |
||
DX-DH/DL |
data |
数据 |
乘除、间接IO |
||
指针*2 变址*2 |
BP |
base pointer |
基指针 |
寻址 |
|
SP |
stack pointer |
栈指针 |
寻址 |
||
SI |
source index |
源变址 |
字符串 |
||
DI |
destination index |
目的变址 |
字符串 |
||
控制*4 |
IP |
instruction pointer |
指令指针 |
指令寻址 |
|
FLAG |
flag |
标志 |
运算结果特征 |
||
段*4 |
CS |
code segment |
代码段 |
配合IP,寻址代码 |
|
SS |
stack segment |
栈段 |
配合SP,寻址栈 |
||
DS |
data segment |
数据段 |
存放操作数、中间结果 |
||
ES |
extra segment |
附加段 |
存放处理后的数据 |
说明:
- 通用寄存器:专门用途+通用用途(数据传送、数据暂存);
- SS:SP组:SP必须和 SS 一起使用,在任何时刻,SS:SP都是指向栈顶元素;
- CS:IP组:两个寄存器指示了 CPU 当前将要读取的指令的地址;
- 8086中,只有4个寄存器能以[…] 的方式使用,分别是 BX、SI、DI和BP;
- [BP]默认段为SS,[BX],[SI],[DI] 默认段DS;
FLAG标志位*9
分类 |
位置 |
简称 |
全称 |
中文名 |
作用 |
状态类*6 |
0 |
CF |
carry flag |
进位标志 |
加减、移位、循环 |
2 |
PF |
parity flag |
奇偶标志 |
错误检查 |
|
4 |
AF |
auxiliary carry flag |
辅助进位标志 |
BCD码运算 |
|
6 |
ZF |
zero flag |
零标志 |
结果判断、控制转移 |
|
7 |
SF |
sign flag |
符号标志 |
结果判断、控制转移 |
|
11 |
OF |
overflow flag |
溢出标志 |
结果判断 |
|
控制类*3 |
8 |
TF |
trap flag |
陷阱标志 |
调试 |
9 |
IF |
interrupt flag |
中断标志 |
控制可屏蔽中断 |
|
10 |
DF |
direction flag |
方向标志 |
字符串步进方向 |
什么是指令?
去哪里找操作数?
寻址方式*4
寻址方式 |
操作数 |
寻址 |
举例 |
立即数寻址 |
操作数就是立即数 |
-- |
MOV AX,8086H |
寄存器寻址 |
操作数在寄存器中 |
用寄存器名寻址 |
MOV AX,BX |
内存寻址 |
操作数在内存中 |
用物理地址寻址 |
见下表 |
I/O端口寻址 |
操作数在IO设备中 |
立即数作为地址 |
IN AL,25H |
地址存入寄存器 |
MOV DX,285H OUT DX,AL |
内存寻址*5
寻址方式 |
有效地址EA |
默认段 |
举例 |
直接寻址 |
EA=IMME |
默认段DS |
MOV AX,[8086H] |
寄存器间接寻址 |
EA=(REG) |
REG:BX/SI/DI、BP; BX/SI/DI默认DS,BP默认SS; |
MOV AX,[BX] |
寄存器相对间接寻址 |
EA=(REG)+IMME |
MOV AX,[BX+8086H] |
|
基址变址寻址 |
EA=(基REG)+(变REG) |
基REG:BX/BP,变REG:SI/DI BX默认DS,BP默认SS |
MOV AX,[BX+SI] |
相对基址变址寄存器 |
EA=(基REG)+(变REG)+IMME |
MOV AX,[BX+SI+8086H] |
|
IMME作为地址时,可以8位或16位;物理地址PA=SA*10H+EA; |
|
寄存器命名的演化
处理器 |
年份 |
寄存器名称演化 |
8008-世界上第一个8位微处理器 |
1972年 |
A B C D E H L |
8086-16位微处理器 |
1979年 |
AX BX CX DX AL BL CL DL AH BH CH DH |
80386-x86系列中的第一个32位处理器 |
1985年 |
EAX AX AH AL |
x86-64 |
2003年 |
RAX EAX AX AH AL |
x86-64 |
NOW |
R15(64) R15D(32) R15W(16) R15B(8) |
- A=accumulator=累加器,B=base基础,C=Count=计数,D=Data=数据,
- X表示H和L的结合,表示完整的16位,只是随便挑了一个字母X,没有实际含义;
- H=high=高8位,L=low=低8位,E=extend=扩展,R=register=寄存器
- D=double word=双字(32位),W=word=字(16位),B=byte=字节(8位)
物理地址=段地址*16+偏移地址
默认组合
SS:SP |
栈段地址+栈指针 |
SS:BP |
栈段地址+基指针 |
DS:SI |
数据段地址+源变址 |
ES:DI |
附加段地址+目标变址 |
CS:IP |
代码段地址+指令指针 |
DS:BX |
数据段地址+基数 |
寄存器*14
通用*4(ABCD) |
Accumulate+Base+Count+Data |
ACD(数据)B(地址) |
段*4(CDES) |
Code+Data+Extra+Stack |
CDES(地址) |
指针*3(SBI) |
Stack+Base+Instruction |
SBI(地址) |
变址*2(SD) |
Source+Destination |
SD(地址) |
标志*1 Flag/PSW |
program status word |
Flag(状态) |
指令分类
一、数据传送指令 |
MOV,PUSH,POP,XCHG,IN,OUT,XLAT,LEA,LDS,LES,LAHF,SAHF,PUSHF,POPF |
二、算术指令 |
ADD,ADC,INC,SUB,SBB,DEC,NEG,CMP,MUL,IMUL,DIV,IDIV,CBW,CWD |
三、逻辑指令 |
AND,OR,XOR,TEST,NOT,SHL/SHR,SAL/SAR,ROL/ROR,RCL/RCR |
四、串处理指令 |
MOVS,LODS,STOS,CMPS,SCAS |
五、控制转移指令 |
JMP,...,LOOP,LOOPZ/LOOPE,LOOPNZ/LOOPNE,CALL,RET,INT,INTO,IRET |
六、处理机控制指令 |
|
语言组成
①标号 |
表示指令地址或变量地址 start:mov ax,bx |
②助记符 |
机器指令的符号化表示jmp |
③操作数 |
add ax,250H |
④注释 |
单行注释;多行注释comment |
堆栈 heap+stack
堆=heap |
栈=stack |
人为申请开辟malloc |
系统自动分配 |
手动释放free |
编译器自动释放 |
空间较大 |
空间较小,栈的大小是1M |
速度比较慢 |
速度较快 |
不连续的空间,产生碎片 |
连续的空间,不会产生碎片 |
链表数据结构存储空闲内存地址 |
栈是机器系统提供的数据结构, 专门的寄存器存储地址 |
堆一般是在头部用一个字节存放堆的大小,堆中的具体内容是人为安排 |
栈在函数调用时,函数调用语句的下一条可执行语句的地址第一个进栈,然后函数的各个参数进栈,其中静态变量是不入栈的 |
汇编语言
基础
字和字节
字节=byte=8位=8bit字=word=2字节=16位字=高位字节+低位字节
进制
十六进制=H=hexadecimal,如AE20H二进制=B=binary,如1010100B十进制=D=decimal,如8866D
H=hex=hexadecimal/ˌheksəˈdesɪml/O=oct=octonary英 /ˈɒktənəri/
指令集
处理器能识别的指令的集合叫做指令集形式:二进制编码
(1) 算术运算指令和逻辑运算指令(2) 数据传送指令数据传送指令是寄存器与寄存器之间、处理器与内存之间、处理器与硬盘之间等的数据传送(3) 处理器状态控制指令
机器指令=机器码=电平信息
大小写
汇编语言不区分大小写,MOV等价于mov
机器语言
机器指令的集合
一台机器可以正确执行的命令
机器指令是一系列二进制数,计算机将其转化为一系列高低电平,使计算机的电子器件受到驱动,从而进行运算
指令和数据
在存储上,指令和数据没有区别,一段内存上存储的内容既可以作为指令也可以作为数据;
指令的数据的不同体现在应用上,把他当做指令来用,它才成为指令,把他当做数据来用,他才是数据
数据读写
①存储单元的地址(地址信息)②器件选择,读写命令(控制信息)③读写的数据(数据信息)
- ①地址信息-地址总线②控制信息-控制总线③数据信息-数据总线
总线=数据线=导线=一根根导线的集合①地址总线的宽度决定了寻址能力2^n②控制总线的宽度决定了对其他器件的控制能力③数据总线的宽度决定了一次数据传送量
硬件
随机存储器RAM
- 可读可写
- 必须带电存储,关机后内容消失
只读存储器ROM
- 只读不写
- 关机后内容不会消失
BIOS=basic input output system基本输入输出系统
寻址
分类
操作数寻址*7
- 立即数寻址、寄存器寻址、直接寻址、寄存器间接寻址、寄存器相对寻址、基址变址寻址、相对基址变址寻址
I/O端口寻址*2
- 直接端口寻址、间接端口寻址
存储器寻址*5
- 直接寻址
- 直接寻址,指令中直接给出操作数的有效地址MOV AX,[0002H] PA=DS*10H+0002H
- 8086指令系统规定,存储器直接寻址时如果不指定段寄存器,默认就在数据段DS
- 如果操作数在默认段意外的其他段,则必须在地址前加以说明,这种说明叫【段超越前缀】段超越前缀=不使用默认段=指定段
- 寄存器间接寻址
- 指令中给出寄存器,而寄存器中存储的是操作数的有效地址MOV AX,[BX] PA=(DS)*10+(BX)
- 若果指令中指定的存放有效地址的寄存器是BX、SI、DI,那么默认段就是DS
- 寄存器相对寻址
- 指令中给定一个寄存器和一个相对偏移量(8位/16位),两者之和左右操作数的有效地址
- MOV AX,[BX+10H] EA=(BX)+10H PA=(DS)*10H+EA这里的BX也叫做【间址】寄存器,就是说BX给出的地址本身并不是有效地址,而是一个间接地址
- BX、SI、DI作为间址寄存器,默认数据段寄存器位DSBP作为间址寄存器时,默认栈段寄存器为SS
- 有效地址EA=(R)+偏移量OFFSET(8位或16位)物理地址:PA=(DS)*10H+EA BX、SI、DI作为间址寄存器PA=(SS)*10H+EA BP作为间址寄存器
- 基址变址寻址
- 指令中给出一个基址寄存器和一个变址寄存器,二者内容之和作为操作数的有效地址MOV AX,[BX+SI] EA=(BX)+(SI) PA=(DS)*10H+EA
- 基址寄存器可取BX或BP,变址寄存器可取SI或DI指令中不能同时出现两个基址寄存器或两个变址寄存器
- 如果基址寄存器为BX,默认数据段寄存器DS如果基址寄存器为BP,默认代码段寄存器SS
- BX+SI BX+DI √ 默认DS段BP+SI BP+DI √ 默认SS段BX+BP SI+DI × 错误的组合
- 相对基址变址寻址
- 指令中给出一个基址寄存器、一个变址寄存器和 一个相对偏移量(8位或16位),3者之和作为操作数的有效地址
- MOV AX,[BX+DI+0050H]EA=(BX)+(DI)+0050HPA=(DS)*10H+EA
- 基址寄存器可取BX或BP,变址寄存器可取SI或DI指令中不能同时出现两个基址寄存器或两个变址寄存器
- 如果基址寄存器为BX,默认数据段寄存器DS如果基址寄存器为BP,默认代码段寄存器SS
I/O端口寻址
- 直接端口寻址
- 在指令中直接给出要访问的端口地址,范围范围0-255一般采用2位16进制数表示,也可以用符号表示
- IN AL,25H 从25H端口取数据送入AL
- 间接端口寻址
- 若访问端口地址>255,则必须采用间接端口寻址,访问范围0-65535先将端口地址送入DX寄存器,用DX作为间接寻址寄存器
- MOV DX,285H 将端口地址285H送入DX寄存器OUT DX,AL 将AL中的数据输出到DX指定端口
立即数寻址
- 将操作数直接放在指令中,并紧跟在代码之后,就叫立即数寻址;立即数只能作为源操作数,不能作为目的操作数,一般用来给寄存器赋值;立即数寻址速度快;8086支持2进制、10进制16进制的立即数;10进制可以不指定后缀(D/d),2进制必须指定后缀B/b,16进制必须指定后缀H/h;
寄存器寻址
- 操作数存放于寄存器中,通过指定寄存器名称,来获取寄存器的数据,叫做寄存器寻址;可采用的寄存器名:AL/AH/BL/BH/CL/CH/DL/DH,AX/BX/CX/DX/BP/SP/SI/DI寄存器寻址在CPU内部进行,不需要总线周期,速度快;寄存器寻址可用于源操作数,也可用于目的操作数,或者同时用于二者;
存储器寻址
- 由于寄存器数量有限,因此程序中大多数操作数需要从内存中获得;内存寻址最终将得到存放操作数的物理地址;
定义
【寻址】指令指定操作数的位置,即给出地址信息,在执行时需要根据这个地址信息找到需要的操作数,这种寻找操作数的过程称为寻址;【寻址方式】就是寻找操作数或操作数地址的方式;
指令
分类
汇编指令
- 汇编指令是机器指令便于记忆的书写格式;
- 汇编指令是机器指令的助记符,有对应的机器指令;
- 汇编语言的核心是汇编指令,它决定了汇编语言的特性
伪指令
- 没有对应的机器指令,由编译器执行,计算机并不执行
其他符号
- +-*/等,由编译器识别,没有对应的机器指令
伪指令
分段指令:一个汇编程序是由若干个段segment组成的;segname segment......segname endssegment=start of code segmen=代码段的开始位置,ends=end of code segmen=代码段的结束位置
end是一个汇编程序结束的标志,而ends是一个代码段结束的标志;end应该在程序末尾单独使用,而ends必须和segment配对使用
assume假设假设某个寄存器和某个程序段相关联;assume segname
组成
指令(instruction)是一种语句,它在程序汇编编译时变得可执行。汇编器将指令翻译为机器语言字节,并且在运行时由 CPU 加载和执行。一条指令有四个组成部分:①标号(可选)----表示指令地址或变量地址②指令助记符(必需)③操作数(通常是必需的)④注释(可选)不同部分的位置安排如下所示:[label: ] mnemonic [operands] [;comment]
标号(label)是一种标识符,是指令和数据的位置标记。标号位于指令的前端,表示指令的地址。同样,标号也位于变量的前端,表示变量的地址。标号有两种类型:数据标号和代码标号。数据标号标识变量的位置,它提供了一种方便的手段在代码中引用该变量。比如,下面定义了一个名为 count 的变量:count DWORD 100array DWORD 1024, 2048 DWORD 4096, 8192
指令助记符(instruction mnemonic)是标记一条指令的短单词。在英语中,助记符是帮助记忆的方法。相似地,汇编语言指令助记符,如 mov, add 和 sub,给出了指令执行操作类型的线索。
操作数操作数是指令输入输出的数值。汇编语言指令操作数的个数范围是 0〜3 个,每个操作数可以是寄存器、内存操作数、整数表达式和输入输岀端口。生成内存操作数有不同的方法,比如,使用变量名、带方括号的寄存器等。变量名暗示了变量地址,并指示计算机使用给定地址的内存内容。
注释注释是程序编写者与阅读者交流程序设计信息的重要途径。程序清单的开始部分通常包含如下信息:程序目标的说明程序创建者或修改者的名单程序创建和修改的日期程序实现技术的说明注释有两种指定方法:①单行注释,用分号(;)开始。汇编器将忽略在同一行上分号之后的所有字符。②块注释,用 COMMENT 伪指令和一个用户定义的符号开始。汇编器将忽略其后所有的文本行,直到相同的用户定义符号出现为止。
NOP(空操作)指令最安全(也是最无用)的指令是 NOP(空操作)。它在程序空间中占有一个字节,但是不做任何操作。它有时被编译器和汇编器用于将代码对齐到有效的地址边界。在下面的例子中,第一条指令 MOV 生成了 3 字节的机器代码。NOP 指令就把第三条指令的地址对齐到双字边界(4 的偶数倍):00000000 66 8B C3 mov ax,bx00000003 90 nop ;对齐下条指令00000004 8B D1 mov edx,ecxx86 处理器被设计为从双字的偶数倍地址处加载代码和数据,这使得加载速度更快。
分类
一、数据传送指令 : MOV,PUSH,POP,XCHG,IN,OUT,XLAT,LEA,LDS,LES,LAHF,SAHF,PUSHF,POPF 二、算术指令 : ADD,ADC,INC,SUB,SBB,DEC,NEG,CMP,MUL,IMUL,DIV,IDIV,CBW,CWD 三、逻辑指令 : AND,OR,XOR,TEST,NOT,SHL/SHR,SAL/SAR,ROL/ROR,RCL/RCR 四、串处理指令 : MOVS,LODS,STOS,CMPS,SCAS 五、控制转移指令 : JMP,...,LOOP,LOOPZ/LOOPE,LOOPNZ/LOOPNE,CALL,RET,INT,INTO,IRET 六、处理机控制指令。
指令+
数据传送指令
定义
- 可以修改IP或者同时修改CS和IP的指令称为转移指令;转移指令就是控制CPU执行某行代码的指令;
分类
- 只修改IP时,称为段内转移;如jmp ax同时修改CS和IP,称为段间转移,如jmp 10000:0
- 段内转移分为短转移和长转移:短转移:IP修改范围-128~127,长转移:IP修改范围-32768~32767
- ①无条件转移,如jmp②条件转移③循环转移,如loop④过程、⑤中断
分组
- 通用数据传送
- MOV dst src 字节或字传送执行指令后,src内容不变,dst和src内容相同源操作数可以是:通用寄存器、段寄存器、存储器、立即数目标操作数可以是:通用寄存器、段寄存器(CS除外)、存储器■ 目的操作数不能用立即数寻址IMME■ 目的操作数不能用代码段寄存器CS■ 源操作数和目的操作数不能同时为存储器MEM■ 两个段寄存器之间不能直接传送数据
- PUSH src 字入栈 不能使用立即数作为PUSH操作数通用寄存器、段寄存器、存储器可以作为操作数
- POP dst 字出栈操作数必须为16位,且不能是立即数通用寄存器、段寄存器、存储器可以作为操作数
- XCHG dst,src 字节或字交换=exchange必须有一个操作数在寄存器中,结果不影响标志位可以实现字节数据交换,也可是实现字(2byte)数据交换
- XLAT 换码指令累加器AX是数据传送的核心输入指令/输出指令/换码指令都是通过AX完成的IN Acc,src 其中Acc表示8位或16位的累加器IN AL,30H 将30端口中的数据读入到ALIN AX,20H 将20H端口中的数据读入到AL,同时将21H端口中的数据读入到AHXLAT换码指令:AL←(BX+AL),将累加器AL中的值转换为内存表中的某个值,再送回AL中;XLAT一般用来实现码制之间的转换,也称为【查表转换指令】
- 地址传送
- LEA dst,src 装入有效地址=load effective address有效地址送寄存器指令将存储器的16位有效地址传送到通用寄存器LEA BX,[SI+BP] 将(SI)+(BP)的结果送入BX注意:传送的是地址本身,而不是该内存地址处的数据
- LDS dst,src装入DS寄存器=load to data segment register地址指针送寄存器指令将src指示的前两个字节单元的内容送入指令中指定的通用寄存器,同时将src+2指示的两个字节内容送入DS;LDS BX,ARR[SI] (ARR)=010H (SI)=020H (BX)=6AE0H(20030H)=0080H (20032H)=4000H EA=ARR[SI]=0010H+0020H=0030H,PA=(DS)*10H+EA=20000H+0030H=20030HSRC+2=EA+2H=0032H,PA=(DS)*10H+EA=20000H+0032H=20032H指令执行后(BX)=0080H (DS)=4000H将存储器MEM中的两个16位数据作为地址,分别送入BX和DS
- LES dst,src 装入ES寄存器=load to extra segment register和LDS指令类似,指示将寄存器由DS改为ES
- 标志位传送
- 标志寄存器指令共4条,这些指令都是单字节(1byte)指令操作数以隐含的形式规定,默认为AH寄存器
- LAHF=将FLAG低字节送入AH=load to AH from flag register将FLAG中5个标志位SF、ZF、AF、PF、CF分别取出,传送到累加器AG的对应位;
- SAHF=将AH内容装入FLAG低字节=send AH to flag registerLAHF的反向操作,将AH寄存器中的对应位传送到FLAG对应的5个标志位SF、ZF、AF、PF、CF
- PUSHF=将FLAG内容压栈=push flag register先将SP减2,然后将标志寄存器FLAG中的内容压入栈
- POPF=从堆中弹出一个字给FLAG=pop flag registerPUSHF的反向操作,将堆栈内容弹出到标志寄存器FLAG,然后加2
- PUSHF和POPF的作用①保护调用过程以前的标志寄存器的值,过程返回后再回复此标志位;②用来修改标志寄存器中相应标志位的值;
算数指令
加法*3
- ADD dst,src 加法(字节/字)=addition■ 两个存储器操作数MEM不能直接相加,■ 段寄存器不能参与运算,■ 两个操作数类型保持一致
- ADC dst,src 带进位加法(字节/字)=addition with carry
- INC dst 加1(字节/字)=increase自增(i++)■ 操作数只能是通用寄存器REG或存储器MEM,■ 操作数不可以用立即数IMME■ 操作数不可以用段寄存器segment■ 常用语循环中修改指令或用作循环计数器,
减法*5
- SUB dst,src 减法(字节/字)=subtraction
- SBB dst,src 带借位减法(字节/字)=subtraction with borrow
- DEC dst 减1=decrease自减(i--)
- NEC dst 取补=negative操作对象中的内容取2的补码,相当于先按位取反,然后末位加1
- CMP dst 比较=compare■ CMP与SUB指令一样执行减法操作,但是不保存结果■ 指令执行后,两个数不会改变,■ 这条指令是根据操作的结果设置状态标志位,按照比较结果使程序产生条件转移;CMP AL,0 AL和0进行比较JGE NEXT 如果AL>0则转到NEXT位置执行
乘法*2
- MUL src 不带符号乘法=multiply■ 乘数由src指定,被乘数隐式指定;结果也隐式指定;■ 被乘数默认存放于AL或AX中;结果默认存放于AX或(AX和DX)中■ 8位*8位=16位,AL被乘数,src乘数,AX积■ 16位*16位=32位,AX被乘数,src乘数,积:AX存低16位DX存高16位■ src可采用寄存器操作数、存储器操作数,不能采用段寄存器或者立即数;
- IMUL src带符号乘法=integer multiplication■ src可采用寄存器操作数、存储器操作数,不能采用段寄存器或者立即数;
除法*4
- DIV src 不带符号除法=divide ■ 8086规定:除数长度只能是被除数长度的一半;■ 被除数16位时,除数只能8位,被除数32位时,除数只能16位;■ 被除数、除数、商、余数全部都是无符号数;src位字节(1byte)数据时:被除数AX,除数src,商AL,余数AHsrc为字(2byte)数据时:被除数DX AX,除数src,商AX,余数DX
- IDIV src 带符号除法=integer divide■ 被除数、除数、商、余数全部都是带符号数,且余数符号位与被除数相同;
- CBW 字节扩展=change byte to word(1byte→2byte)■ 用一个操作数的符号位形成另一个操作数;■ 后一个操作数的各位全是0(正数)或全是1(负数);■ 结果是使数据位数加长,但数据大小不变;■ 符号扩展指令不影响标志位FLAG;CBW将字节转换为字,将AL中的符号位扩展到AH中;若AL中D7=0,则(AH)=00H,若AL中D7=1,则(AH)=FFH
- CWD 字扩展=change word to double word(2byte→4byte)CWD将字转换为双字,将AX中的符号位扩展到DX中;若AX中D15=0,则(DX)=0000H,若AX中D15=1,则(DX)=FFFFH,
十进制调整*6
- AAA 非组合BCD码的加法调整=ascii add with adjust
- DAA 组合BCD码的加法调整=decimal add with adjust
- AAS 非组合BCD码的减法调整=ascii adjust on substract
- DAS 组合BCD码的减法调整=decimal adjust on substract
- AAM 非组合BCD码的乘法调整=ascii adjust on multiplication
- AAD 非组合BCD码的除法调整=ascii adjust on divide
逻辑指令
逻辑运算
- NOT dst 非(字节/字)
- AND dst,src 与(字节/字)
- OR dst,src 或(字节/字)
- XOR dst,src 异或(字节/字)
- TEST dst,src 测试(字节/字)执行与操作,结果不回送;只影响状态标志位PF、SF、ZF,使CF=0,OF=0;可以在不改变原有操作数的情况下,检测某一位或某几位是0还是1;
一般位移
- SHL dst,计数值 逻辑左移(字节/字)=shift leftSHL dst,1/CL左移一位或CL中指定位数;左移1位时,最高位移出到CF【进位标志位】中,最低位补0;■ dst可以是存储器操作数或通用寄存器擦作数;■ dst不能是立即数或段寄存器操作数;■ dst可以是8位或16位;■ 如果移位次数大于1,则应将移位次数放入CL中;■ SHL将影响CF、OF、SF、ZF、PF标志位;■ 利用左移1位可以实现操作数*2的运算
- SHR dst,计数值 逻辑右移(字节/字)=shift rightSHR dst,1/CL 右移一位或CL中指定位数;右移1位时,最低位移出到CF【进位标志位】中,最高位补0■ 利用右移1位可以实现无符号操作数/2的运算
- SAL dst,计数值 算数左移(字节/字)=arithmatic shift leftSAL dst,1/CL左移一位或CL中指定位数;左移1位时,最高位移出到CF【进位标志位】中,最低位补0;■ 利用左移1位可以实现操作数*2的运算
- SAR dst,计数值 算数右移(字节/字)=arithmatic shift rightSHR dst,1/CL 右移一位或CL中指定位数;右移1位时,最低位移出到CF【进位标志位】中,最高位补符号位■ SAR将影响CF、OF、SF、ZF、PF标志位;■ 利用右移1位可以实现带符号操作数/2的运算
循环位移
- ROL dst,计数值 循环左移(字节/字)=rotate left左移1位时,最高位移出到CF【进位标志位】中,同时送入最低位;
- ROR dst,计数值 循环右移(字节/字)=rotate right右移1位时,最低位移出到CF【进位标志位】中,同时送入最高位;
- RCL dst,计数值 带进位循环左移(字节/字)=rotate left with carry左移1位时,最高位移出到CF【进位标志位】中,CF中原有内容送入最低位;
- RCR dst,计数值 带进位循环右移(字节/字)=rotate right with carry右移1位时,最低位移出到CF【进位标志位】中,CF中原有内容送入最高位;
- 4种指令,均影响CF、OF、SF、ZF、PF标志位;
串指令
串指令操作对象:内存中地址连续的字节串或字串;每次基本操作后,能够自动修改地址指针,为下一次操作做准备;基本串操作指令前可以加【操作重复前缀】使指令操作重复;用重复前缀比用循环快得多;
约定:以DS:SI寻址源串,以ES:DI寻址目标串;用方向标志规定串处理方向,方向标志DF=0,从低地址到高地址方向处理;字节操作指针+1,字操作指针+2;方向标志DF=1,从高地址到低地址方向处理;字节操作指针-1,字操作指针-2;■ 可以在串操作指令前加重复前缀,对一个以上串进行操作;■ 必须用CX作为重复次数计数器,串操作指令每执行一次,计数-1,直到减为0为止;
串传送指令
- MOVS---->move string;MOVES dst,src(字节/字)MOVESB(字节),MOVESW(字):(DI)←((SI)),将SI所指单元的内容传送到DI所指单元,然后修改地址指针;字节操作时:SI←(SI)±1,DI←(DI)±1字操作时:SI←(SI)±2,DI←(DI)±2当方向标志位DF(direction flag)=0时,用+ ,DF=1时,用-;该指令不影响标志位;
串存储指令
- STOS---->store string;格式:STOS dst,STOSB字节存储,STOSW字存储字节操作:(DI)←(AL)将AL内容送入DI所指字节单元;DI←(DI)±1指针移位字操作:(DI)←(AX)将AL内容送入DI所指字单元;DI←(DI)±2指针移位■ 该指令把AL或AX内容送入由DI指示的附加段ES(extra segment);■ 同时,根据DF(direction flag)值及数据类型修改DI(destination index)值;■ STOS不影响标志位;STOS配合REP(repeat操作重复前缀),可将存储区中某一连续区域放入相同的内容;
取串指令
- LODS---->load string;格式LODS dst,LODSB字节,LODSW字字节操作:AL←((SI))将SI所指单元内容送入AL,SI←(SI)±1 指针移位字操作:AX←((SI))将SI所指单元内容送入AX,SI←(SI)±2 指针移位■ 用来从数据段取出一个字节/字,一般不和REP配合使用;
串比较指令
- CMPS---->compare string;格式CMPS dst,src,CMPSB字节,CMPSW字;字节操作:((SI))-((DI))相减,SI←(SI)±1,DI←(DI)±1指针移位字操作:((SI))-((DI))相减,SI←(SI)±2,DI←(DI)±2指针移位■ 将两个字节/字数据相减,结果不送回,只影响标志位;■ CMPS和REPE/PEPZ或REPNE/REPNZ配合,可以判断两个字符串是否相等;
串搜索指令
- SCAS---->scan string;SCAS dst,src;SCASB;SCASW;字节操作:AL-((ID))相减,DI←(DI)±1指针移位字操作:AX-((ID))相减,DI←(DI)±2指针移位相减结果不送回,只影响状态标志位;
方向标志DF处理指令
- 方向标志清除指令CLD(clear direction flag):使DF=0,串操作时,使地址自增++;方向标志设置指令STD(set direction flag):使DF=1,串操作时,使地址自减--;
重复操作前缀指令
- REP---->repeat ;格式REP String Primitive;原始串指令String Primitive可以为MOVES,STOS,LODS;REP使后面的串指令重复执行;执行次数预存如CX中;每执行一次串指令,(CX)--,直到(CX)=0,指令结束;
- REPE/REPZ(repeat when equal /zero flag)相等或为0时重复;String Primitive可以为CMPS,SCAS;当(CX)≠0并且比较相等的情况下,重复串指令;重复次数存入CX;
- REPNE/REPNZ(repeat when not equal/ zero flag) ;String Primitive可以为CMPS,SCAS;当(CX)≠0并且比较不相等的情况下,重复串指令;重复次数存入CX;
- REPC---->repeat when carry flag 进位时重复REPNC---->repeat when not carry flag 不进位时重复
控制指令控制转移指令
分类
- 段内转移:只改变IP不改变CS段间转移:同时改变IP和CS
- 无条件转移指令、条件转移指令、循环控制指令、子程序调用和返回指令
无条件转移
- JMP---->jump oprJMP SHORT opr 段内直接短转移指令JMP NEAR PTR opr 段内直接近转移指令JMP WORD PTR opr 段内间接转移指令JMP FAR PTR opr 段间直接转移指令JMP DWORD PTR opr 段间间接转移指令opr为转移目标地址,可以使用符号地址(标号)
- SHORT表示汇编程序将目标地址opr汇编成8位偏移量有效地址是当前IP值和指令中给定的8位偏移量opr值之和;
- NEAR PTR表示汇编程序将符号地址opr汇编成16位偏移量;目标地址(有效地址)为当前IP值和指令中给定的16位偏移量opr值之和;
- 偏移地址紧跟在指令码之后,由汇编程序计算得出;
条件转移指令
- 以某些标志位的状态或者标志位的逻辑运算结果作为依据,以此决定是否转移;标志位通常由转移指令的上一条指令设置;若果满足条件,则执行条件转移指令指定的位置,如果不满足,则继续执行条件转移指令之后的指令;
- JZ/JE(jump if zero、jump if equal),为0/相等,ZF(zero flag)=1;JNZ/JNE(jump if not zero,jump if not equal),不为0/不相等,ZF=0JS(jump if sign flag),符号为负,SF(sign flag)=1;JNS(jump if not sign flag),符号不为负,SF=0JO(jump if overflow),结果溢出,OF(overflow flag)=1;JNO(jump if not overflow),结果不溢出,OF=0JP/JPE(if parity flag,if parity is even),1的个数为偶数,PF=1;JNP/JPO(if not parity flag,if parity is odd),1的个数为奇数,PF=0JC/JB/JNAE(if carry flag,if blow,if not above or equal),进位/低于/不高于,CF=1JNC/JNB/JAE(if not carry,if not blow ,if above or equal),CF=0JBE/JNA(if blow or equal,if not above)小于等于/不高于,CF=1或ZF=1JNBE/JA(not blow or equal,above)不低于等于/高于,CF=0或ZF=0JL/JNGE(less,not greater or equal)小于/不大于等于,SF≠OFJNL/JGE(not less,greater or equal)不小于/大于或等于,SF=OFJLE/JNG(less or equal,not greater)小于等于/不大于,ZF≠0或ZF=1JNLE/JG(not less or equal,greater)不小于等于/大于,SF=0或ZF=0
- 偶数even number 奇数odd number;parity 奇偶性,carry 进位,borrow借位
循环控制指令
- LOOP ,循环,CX=CX-1,CX≠0LOOPE/LOOPZ(equal /zero),等于/结果为0循环,CX=CX-1,ZF=1且CX≠0LOOPNE/LOOPNZ(not equal /not zero )不等于/结果不为0,CX=CX-1,ZF=0且CX≠0JCXZ(jump when CX is zero ),CX内容为0转移,CX=0
- 循环控制指令根据结果的标志位状态进行控制操作;循环控制指令本身不影响标志位;转向的目的地址范围:当前IP为中心的-128~+127之间;循环控制指令以CX为计数器,每执行一次指令,CX-1,直到为零,循环结束;转向的目的地址(IP)=(IP)+位移量;LOOPE/LOOPZ执行的三个操作:①CX=CX-1②CX是否为0③ZF值判断,
子程序调用/返回指令
- 段内调用:CALL NEAR PTR opr段间调用:CALL FAR PTR opr子程序返回:RET (RET=return)opr为子程序名,也就是子程序第一条指令的符号地址
- CALL---->call RET---->return RETF---->return far
处理器控制指令
- 功能
- 修改状态标志位;控制CPU,使CPU暂停、等待、空操作;
- 标志操作
- STC---->set carry 进位标志置1,即CF=1CLC---->clear carry 进位标志置0,即CF=0CMC---->carry make change ,进位标志取反STD---->set direction方向标志置1,即DF=1CLD---->clear direction 方向标志置0,即DF=0STI---->set interrupt 中断标志置1,即IF=1CLI---->clear interrupt中断标志置0,即IF=0
- CPU控制
- HLT---->halt 停机WAIT---->wait 等待ESC---->escape 交权LOCK---->lock 封锁总线NOP---->no operation空操作
DOS和BIOS中断调用
DOS功能调用,可以完成对文件、设备、内存的管理;这些功能模块就是几十个独立的【中断服务程序】;【中断服务程序】的入口地址由系统置入【中断向量表】中;在汇编语言中,可以用【中断指令】直接调用;
调用方法/步骤:①将【入口参数】送入指定寄存器;②将子程序【功能号】送入AH寄存器;③使用INT 21H指令转入子程序入口,执行相应操作;
AH=01H,表示带显示的键盘输入;01号功能调用,是系统扫描键盘,并等待键盘输入单个字符;当有键按下时,先检查是否Ctrl+Break键,若是则将字符键值(ASCII码)送入AL,并在屏幕上显示该字符,此调用没有【入口参数】;MOV AH,01H INT 21H
AH=02H,表示从显示器上输出单个字符;02号功能的入口参数:被显示字符的(ASCII码)送入DL;MOV DL,'S' MOV AH,02H INT 21H
AH=09H,在显示器上输出字符串;将指定字符串送显示器显示;字符串预存入内存的数据缓冲区;字符串首地址送入指定位置,并且字符串必须以'$'结束;入口参数:DS(data segment):DX(data register)指向字符串的首单元;
AH=0AH,将字符串输入到缓冲区;将键盘输入的字符串写入内存缓冲区;为了接收字符,首先在内存区定义一个缓冲区;缓冲区第一个字节是缓冲区字符个数;第二个字节用作系统填写实际键入字符总数;从第三个字节开始存放字符串;输入字符串以回车键结束;如果输入字符不足以填满缓冲区,其余字节补0;若输入字符个数大于定义长度,超出字符将丢弃,并响铃警告;
BIOS中断调用IBM PC在ROM中提供了BIOS基本输入/输出系统,占用系统板上8KB空间,又称为ROM BIOS;BIOS为用户程序和系统程序提供主要外设的控制功能;如系统加电自检、引导装入、对键盘/磁盘/磁带/显示器/打印机/异步串行通信接口的控制;计算机系统软件就是利用这些基本的设备驱动程序,完成各种功能操作;每个功能模块的入口地址都在【中断是量表】中;通过中断指令INT n,可以直接调用;n是中断类型号,每个类型号n对应一种IO设备的中断调用,每个中断调用又以功能号来区分其控制功能;
其他
在汇编源程序中,数据不能以字母开头,如FFH应写为0FFH;程序加载后,CX内存储的是程序段的长度(字节数);DS中存储的是空闲内存区的段地址;CS中存储的是代码段的段地址,CS-DS=10H,左移变为100H=256Byte,存放PSP=程序段前缀;操作系统(DOS)利用PSP和程序进行通信;
操作数类型operand
- 立即数=立即操作数=immediate operand=IMME寄存器操作数=Register operand=REG存储器操作数=Memory operand=MEM输入输出端口操作数=Input/Output port operand
指令类型
- 隐含操作数指令、单操作数指令、双操作数指令
指令通常不直接给出操作数,而是给出操作数的存放地址;【寻址方式】寻找操作数地址的方式;8086寻址方式*7:立即数寻址、寄存器寻址、和存储器寻址*5;存储器寻址*5:(直接寻址/寄存器间接寻址/寄存器相对寻址/基址变址寻址/相对基址变址寻址)BX(base) SI(source index)DI(destination)对应数据段DS(data segment)BP(base pointer)对应栈段SS(stack segment)立即数寻址:立即数作为操作数;寄存器寻址:寄存器名称作为操作数;EA=REG Name;
直接寻址:立即数作为地址;EA=IMME;默认数据段DS;寄存器间接寻址:EA=(REG),BX/SI/DI默认数据段DS,BP默认栈段SS;寄存器相对寻址:EA=(REG)+IMME;BX/SI/DI默认数据段DS,BP默认栈段SS;基址变址寻址:EA=(基REG)+(变REG);BX默认DS,BP默认SS;相对基址变址寻址:EA=(基REG)+(变REG)+IMME;BX默认DS,BP默认SS;
机器指令
概念
8086指令采用变长指令,指令长度可有1-6个字节组成8086机器指令有零或多个操作数每种指令的操作码: 对应着机器指令的一个二进制编码 ,用一个唯一的助记符表示(指令功能的英文缩写)
组成
8086指令由操作码和操作对象两部分组成在一条指令中,操作码部分是必需的,而操作数部分可能隐含在操作码中,或者由操作码后面的指令给出
详细
操作码(4-7位)
- 高6位是操作码,后面两位是DW特征位/标志位mov操作码100010/push操作码111111pop操作码100011/add操作码000000sub操作码001010
标志位(2位)
- 特征位=标志位,大部分是DW标志位,除了D/W标志位,某些指令格式中还会使用SW,VW,ZW标志位
- 标志位D
- D表示数据传送方向,D=0,数据从寄存器传出,D=1,数据传入寄存器
- D=0ModR/M字节的REG域是源操作数D=1ModR/M字节的REG域是目标操作数
- 标志位W
- 说明传递的数据类型是字(2byte)还是字节(1byte)
- W=0,传递字节(1byte),W=1,传递字(2byte)
MOD(2位)
- mod(2位):用来区分另一个操作数是在寄存器还是存储器中
- mod=00,存储器寻址,没有位移量mod=01,存储器寻址,有8位位移量mod=10,存储器寻址,有16位位移量mod=11,寄存器寻址,没有位移量
REG(2-3位)
- 用3位编码寻址8种不同的寄存器,根据不同的W,分别寻址16位和8位寄存器000 001 010 011 100 101 110 111AX CX DX BX SP BP SI DI (W=1)AL CL DL BL AH CH DH BH (W=0)
- 对使用段寄存器的指令,REG占两位00 01 10 11ES CS SS DS
R/M(3位)
- r/m(3位):受寻址方式mod控制,如果mod=11则r/m为寄存器寻址,r/m的值就是寄存器的编号,如果mod为00,01,10的话则是存储器寻址,r/m的值便是和mod组合来指定一个有效寻址方式
举例
89C8 MOV AX(另一操作数),CX(第一操作数,传出/源)对应机器码 1000 1001 1100 1000■1-6位100010表示mov操作码;■7-8位01标志位,其中D=0表示数据从寄存器AX传出(源操作数)而不是传入;W=1,传递字(2byte);■9-10位11,mod=11,寄存器寻址,没有位移量;■11-13位001,reg=001,表示寄存器CX,■14-16位000,由于mod=11,000表示寄存器编号,也就是000对应的AX
B82211 MOV AX,11221011 1000 0010 0010 0001 00011 0 1 1 w reg data data if w e 1第一个字节前4位是操作码 W=1表示传递的数据类型是字 后3位代表寄存器编号AX(000) 第二字节表示数据,如果w=1则是16位的数据
8B872211 MOV AX,[BX+1122]对应机器码 1000 1011 1000 0111 0010 0010 0001 0001第一个字节前7位是操作码 W=1表示传递的数据类型是字 第二个字节前2位mod=10表示是存储器寻址,有16位位移量,接着3位reg=000表示寄存器编号是AX,因为mod=10,所以r/m后3位和mod组合成一个存储器寻址,查表得知mod=10 r/m=111对应的是BX+16位位移量(BX存储值与一个16位的数相加作为位移量/地址偏移量)由mod=10可以得知第三和四个字节为16位位移量1122(小端存储)
寄存器
8086 CPU 中寄存器总共为 14 个,且均为 16 位 。即 AX,BX,CX,DX,SP,BP,SI,DI,IP,FLAG(PSW),CS,DS,SS,ES 。这 14 个寄存器按照一定方式又分为了通用寄存器,控制寄存器和段寄存器。
通用寄存器
在 8086 CPU 中,通用寄存器有 8 个,分别是 AX,BX,CX,DX,SP,BP,SI,DI ,这些个寄存器除了自身的专门用途外,还可以用来传送数据和暂存数据,所以才称它们为通用寄存器 。
数据寄存器
AX (Accumulator):累加寄存器,或累加器; BX (Base):基地址寄存器; CX (Count):计数器寄存器; DX (Data):数据寄存器;
AX 寄存器可以分为两个独立的 8 位的 AH 和 AL 寄存器; BX 寄存器可以分为两个独立的 8 位的 BH 和 BL 寄存器; CX 寄存器可以分为两个独立的 8 位的 CH 和 CL 寄存器; DX 寄存器可以分为两个独立的 8 位的 DH 和 DL 寄存器;
AX 寄存器,作为累加器,特殊用途是在使用DIV和MUL指令时使用。 BX主要是用做内存寻址时候表示偏移地址,[…]表示一个内存单元 CX 作为计数寄存器,在使用loop指令循环时用来指定循环次数的寄存器。 DX 寄存器,作为数据寄存器器,特殊用途是在使用DIV和MUL指令时使用。
指针寄存器
SP (Stack Pointer):栈指针寄存器; BP (Base Pointer):基指针寄存器;
SP 寄存器上必须和 SS 段寄存器一起使用,表示栈顶的偏移地址,8086CPU中,有两个寄存器:段寄存器SS 存放栈顶的段地址寄存器SP 存放栈顶的偏移地址
以 […] 的方式访问内存单元而且在 […] 中使用了寄存器 BP 的话,那么如果在指令中没有明确或者说是显示的给出段地址时,段地址则使用默认的 SS 寄存器中的值(BX,SI,DI 会默认使用 DS 段寄存器)
变址寄存器
SI (Source Index):源变址寄存器; DI (Destination Index):目的变址寄存器;
SI,DI 两个寄存器的功能和 BX 差不多,自然,SI 和 DI 中也是可以暂存一般性数据的,同时,通过使用 SI 和 DI 寄存器也是可以用来完成寻址操作的。SI和DI可以分别和BX,BP组合使用。
段寄存器
CS (Code Segment):代码段寄存器; DS (Data Segment):数据段寄存器; SS (Stack Segment):栈段寄存器; ES (Extra Segment):附加段寄存器;
8086有20位地址总线,可传送20位地址,寻址能力为1M。8086内部为16位结构,它只能传送16位的地址,表现出的寻址能力却只有64K。
8086CPU采用一种在内部用两个16位地址合成的方法来形成一个20位的物理地址。段地址×16+偏移地址=物理地址,段的起始地址肯定是16的倍数,并且由于偏移地址最多16位,所以段长度最大为64KB(0000H~FFFFH)。
CS中保存代码段寄存器的段地址,通常和IP一起使用,利用CS:IP确定当前需要执行的指令的地址。代码段是我们自己定义的一段内存,只是我们自己编程时候的逻辑定义。DS是数据段寄存器,存放的是数据段的段地址,偏移地址通常由BX,SI,DI或者常数给出,DS:BX。数据段是我们自己定义的一段内存,只是我们自己编程时候的逻辑定义。 SS是栈段寄存器,存放的是栈段的段地址,偏移地址通常由SP,BP给出,SS:SP。栈段是我们自己定义的一段内存,只是我们自己编程时候的逻辑定义。 ES是用于定义一个段的段地址,使用和CS、DS、SS类似。
控制寄存器
IP (Instruction Pointer):指令指针寄存器;
IP通常是和CS一起使用,CS:IP表示将要读取的指令的内存地址,CS表示代码段地址,IP是表示偏移地址。(1)从CS:IP指向内存单元读取指令,读取的指令进入指令缓冲器;(2)IP = IP + 所读取指令的长度,从而指向下一条指令;(3)执行指令。 转到步骤 (1),重复这个过程。
标志寄存器
FLAG:标志寄存器,又称程序状态字PSW
Flag 和其他寄存器不一样,其他寄存器是用来存放数据的,都是整个寄存器具有一个含义。而flag寄存器是按位起作用的,也就是说,它的每一位都有专门的含义,记录特定的信息。8086CPU的标志寄存器有16位,其中存储的信息通常被称为程序状态字(PSW)。
OF overflow flag 溢出标志 操作数超出机器能表示的范围表示溢出,溢出时为1.SF sign Flag 符号标志 记录运算结果的符号,结果负时为1.ZF zero flag 零标志 运算结果等于0时为1,否则为0.CF carry flag 进位标志 最高有效位产生进位时为1,否则为0.AF auxiliary carry flag 辅助进位标志 运算时,第3位向第4位产生进位时为1,否则为0.PF parity flag 奇偶标志 运算结果操作数位为1的个数为偶数个时为1,否则为0.IF interrupt flag 中断标志 IF=1时,允许CPU响应可屏蔽中断,否则关闭中断.TF trap flag 陷阱标志 用于调试单步操作.DF direcion flag 方向标志 用于串处理.DF=1时,每次操作后使SI和DI减小.DF=0时则增大.
指针寄存器和 变址寄存器
指针寄存器和 变址寄存器,包括:SP(Stack Pointer): 栈指针,与SS配合使用,可指向目前的堆栈位置BP(Base Pointer): 基址指针寄存器,可用作SS的一个相对基址位置SI(Source Index):源 变址 寄存器,可用来存放相对于DS段之源变址指针DI(Destination Index):目的 变址 寄存器,可用来存放相对于ES 段之目的变址 指针。
这4个16位 寄存器只能按16位进行存取操作,主要用来形成 操作数的地址,用于堆栈操作和 变址运算中计算操作数的 有效地址。
默认组合
SS:SP 栈段地址+栈指针SS:BP 栈段地址+基指针DS:SI 数据段地址+源变址ES:DI 附加段地址+目标变址CS:IP 代码段地址+指令指针DS:BX 数据段地址+基数
寄存器总结*14
通用*4(ABCD):Accumulate+Base+Count+Data段*4(CDES):Code+Data+Extra+Stack指针*3(SBI):Stack+Base+Instruction变址*2(SD):Source+Destination标志*1 Flag
- 通用*4=ACD(数据)B(地址)段*4=CDES(地址)指针*3=SBI(地址)变址*2=SD(地址)标志*1=Flag(状态)
8086 术语说明IMME=immediate operand=立即操作数=立即数MEM=memory=存储器=内存REG=register=寄存器dst=destination operand=目的操作数src=source operand=源操作数effective address=EA=有效地址;physical address=PA=物理地址,segment address=SA=段地址