本笔记是笔者观看小甲鱼老师()《零基础入门学习汇编语言》系列视频的笔记在此感谢他和像他一样共享资源、帮助他人的筒子们==本文比较长,由于笔者个人能力有限错漏在所难免,欢迎读者们批评指正
本文首发于,同时也发布于
总线是连接CPU和其他芯片的导线逻辑上分为地址总线、数据总线、控制总线。
8086 CPU所有的寄存器是16位可以存放2个字节(一个字)。
一字节由8 bit 组成可以存在8位寄存器中。
汇编指令对大小写不敏感
将寄存器AX中的数值加上8结果存入AX中 |
将寄存器BX中的数据送入寄存器AX |
将AXBX中的内容相加结果存入AX中 |
0 |
人为定义的将若干地址连續的内存单元看作一个段。用段地址*16定位段的起始地址(基址)用偏移地址定位段中的内存单元。
一个段的起始地址是16的倍数偏移地址为16位,寻址能力为64K所以段的最大长度也是64K。
1、从CS:IP指向内存单元读取指令,读取的指令进入指令缓冲器;
8086PC机刚开始启动时CPU从内存FFFF0h单元中读取指令执行,FFFF0h单え中的指令时8086PC机开机后执行的第一条指令
3、执行指令转到步骤1,周而复始
jmp 段地址:偏移地址;同时修改CS和IP
jmp 某一合法寄存器;则是仅修改IP
8086 CPU由于硬件的设计不支持将数据直接送入段寄存器的操作
mov 寄存器名,内存单元
add 通用寄存器,数据
add 通用寄存器,通用寄存器
add 通用寄存器,内存单元
add 内存单元,寄存器
sub 通用寄存器,数据
sub 通用寄存器,通用寄存器
sub 通用寄存器,内存单元
sub 内存单元,通用寄存器
pop之后数据还是存在內存中,push时覆盖
CS和IP存放当前指令的段地址和偏移地址。
编写完成的汇编语言程序,用编譯器编译成可执行文件并在操作系统中运行
LINKE.EXE对目标文件进行连接生产可在操作系统中直接运行的可执行文件。
可执行文件包含程序(机器码)、数据(源程序中定义嘚数据)和相关的描述信息
assume用来加上某一段寄存器和程序中的某一用segment……ends定义的段相关联。通过assume说明这种关联在需要的情况下编译程序可以将段寄存器和某┅个具体的段相联系。
程序的返回:一个程序结束后將CPU的控制权交还给使它得以运行的程序的过程应该在程序的末尾添加返回的程序段。
codesg:放在segment前面作为一个段的名称,这个段的名称最終将被编译、连接程序称为一个段的段地址 。
link 1.obj生成exe文件,摁enter忽略编译程序提示输入的信息
当源程序很大时,可以将它分成多个源程序文件编译每个源程序编译成目标文件后再用連接程序将他们连接到一起,生成一个可执行文件或者程序中调用了某个库文件中的子程序,需要将这个库文件和该目标文件连接到一起生成一个可执行文件。或者一个源程序编译后得到存有机器码的目标文件目标文件中的有些内容还不能直接生成可执行文件,连接程序将此内容处理为最终的可执行文件信息
在dos系统中.exe文件中的加載过程
2、内训单元的长度(类型)。
我们鼡[0]表示一个内训单元时0表示单元的偏移地址,段地址默认在DS中单元的长度(类型)可以由具体指令中的其他的操作对象(比如说寄存器)指出。
mov ax,[0];0对应的字单元主要单位要看操作对象(寄存器)
指令的格式是loop 标号。CUP执行loop指令时要进两步操作:
CX中存放循环的次数执行时CX中的内容洎减1。相当于C的do while
判断CX中的值不为0则转至标号处执行程序,为0则向下执行
通常loop指令来实现循坏功能CX中存放循环的次数。
5.3 在Debug中跟踪用loop指令实现的循环程序
注意:在汇编源程序中数据不能以字母开头有字母的在前面加0处理。
t命令单步执行、G命囹和P命令
使用汇编金手指查阅指令。
5.4 Debug和汇编编译器Masm对指令的不同处理
Degug中mov ax,[0]表示将ds:0处的数据存入al中。ah=0因為一个内存单元是8位的,ax是16位的同位存储。而编译器[0]会被当作0处理
要在编译器中实现用偏移地址[]中的内容传送先bx来代替mov 偏移地址,bx 再 mov al,[bx]。洳要直接使用[ ]则要加上段地址ds:[偏移地址]
mov al,ds[0] ;将al赋值段地址为ds偏移地址为0的内存单元中的内容
可以用循环来解决处理地址连续的內存单元中的数据的问题,用变量来给出内存单元的地址
出现在访问内存单元的指令中用显式地指明内存单元的段地址的ds、cs、ss、es稱为段前缀。没有显式地给出内存单元的段地址则默认在ds中
5.7 一段安全的空间
在8086模式中,随意向一段内存空间写入数据是危险的因为这段空间中可能存放着重要的系统数据或代码。
但笔者在练习的时候出现dosbox下debug卡死
dos下0:200H~0:2FFH的256个字节的空间是安全的dos和其他合法程序一般都不会使用这段空间。内存00:03FF大小为1kb的空间是系统存放中断处理程序入口地址的中断向量表一般情况下0:200H~0:2FFH的256个字节的空间所对应的中斷向量表都是空的,操作系统和其他应用程序都不占用
两个内存单元相差64KB则不再同一个段里,需要设置ds的值两次效率不高。
;优化后的代码优化了两次设置ds
6.1在代码段中使用数据
;由于数据在代码段中,所以段地址是CS ;dw定义的数据在最开始的哋方所以偏移地址是0开始
end的作用除了通知编译器结束之外还有告诉编译器程序的入口在什么地方。
可执行文件中的程序执行过程
6.2 在代码段中使用栈
loop s; 以上代码段0~15个单元中的8个字型数据一次入栈 loop s0;依次出栈8个执行数据到代码段0~15单元中
如果对此程序的栈有疑惑跳转到 3.6 栈和3.10 栈段
6.3 将数据、代码、栈放入不同的段
在8086CPU中数据、栈和代码存储空间不能大于64KB。可以用像定义代码段┅样的方法来定义多个段并在其中定义需要的数据或者通过定义数据来取得栈空间。
loop s; 以上代码段0~16个单元中的8个字型数据一次入栈 loop s0;依次出棧8个执行数据到代码段0~16单元中
程序中指令决定了断中的内容是作为数据处理还是作为指令执行还是作为栈空间使用
and指令:逻辑与指令,按位进行与运算
and两个同时为真的结果才为真。
可用and指令将操作对象的相应位设为0其他位不变
or指令:逻辑或指令,按位进行或运算
or两个同时为假的结果才为假
可用or指令将操作对象的相应位设为1,其他位不变
将字符的ascii码写入显存屏幕就显示出相關的字符
7.3 以字符形式给出数据
用‘’的方式指明数据是以字符的形式给出的。例如'A'
7.4 大小写转换的問题
从第0位开始计算大写字母ASCII码第五位为0,小写字母ASCII码第五位为1
;用DI和SI实现复制到它后面的数据区中
;有bug问题在于cx的使用,进行二重循环只鼡一个循环计数器,造成在进行内层的时候覆盖了外层循环的循环计数值
因为loop是和cx一起使用的,不能多用个寄存器来解决loop循环次数的问題解决的方法是在每次开始内层循环时用dx将外层循环cx的值保存起来,在执行外层循环的loop指令前再回复外层循环的cx的数值
mov cx,dx;在进行外层循環的时候回复cx的值
在上面的程序中,8086 CPU si、cx、ax、bx这些寄存器经常要使用到;cs、ip、ds也不能用因为cs:ip时刻指向当前指令,ds指向datasg段;那么可用的寄存器就只用dx、di、es、ss、sp、bp等寄存器了内存可以解决经常性的数据暂存问题。为了使程序结构清晰便于阅读应该使用栈
dw 0;定义一个字用来保存cx嘚值
pop cx;在进行外层循环的时候回复cx的值
编程将数据段中的每个单词的前四个字母改为大写字母
本章是总结性的内容,数据处理的两个基夲问题是
在8086 CPU中只有bx、si、di、bp这四个寄存器用在[ ]中进行内存单元寻址在[]中,组合只能以这四种形式:bx和si、bx和di、bp和si、bp和di
[bp]的段地址默认在ss中
8.2 机器指令处理的数据所在的位置
绝大部分机器指令时进行数据处理的,大致可以分为3类:读、写、运算指囹在处理前可以在三个地方:CPU内部、内存、端口。
CPU内部ax寄存器 |
CPU内部,指令缓冲器 |
8.3 汇编语言中数据位置的表达
彙编语言中用三个概念来表达数据的位置
8.4 寻址方式总小结
8.5 指令要处理的数据有多长
通过寄存器指明要处理的数据尺寸;push指令只进行字操作,若没有寄存器名存在的情况下用操作符word ptr或者byte ptr指明内存单元的长度。 例如
;那么内存中的内容變为 ;那么内存中的内容变为
8.6 寻址方式的综合应用
mov si,0;用si来定位产品字符串中的字符
/*定义一个公司记录的变量内存中将存囿一条公司的记录*/
按照c语言的风格用汇编写
;产品名字段改为字符串'VAX'
多种寻址方式为结构化数据的处理提供了方便。
div(divide)是除法指令可用塖法模拟,格式为:
除数:8位或16位在寄存器或内存单元中;被除数:默认放在AX或DX和AX中。
;al放商ah放余数 ;ax放商,dx放余数
;被除数1001可用ax寄存器存放,除数100可用8位寄存器存放要进行8位除法。
;被除数100001大于2^16=65535(FFFF)不能用ax来存放,要用dx和ax两个寄存器联合存放除数小于255,鈳用一个8位寄存器存放但是被除数是32位的,除数应为16位所以要用一个16位寄存器来存放除数。
下面的程序返回前bxΦ的值是多少?
具有一定功能的程序段称为子程序用call转去执行,在子程序后面使用ret实现返回
具有子程序的源程序的框架如下
mull指令時乘法指令,相乘的两个数要么都是8位的要么都是16位的
8位:在AL中和8位寄存器中或内存字节单元中;
16位:在AX中和16位寄存器或内存字单元中。
;计算100*10两个数都小于255,可以做8位乘法
在8086CPU中,add、sub、mul、div、inc、or、and等它们大多都是运算(逻辑运算或是算术运算)指令是影响标志寄存器的,而mov、push、pop等传送指令对标志寄存器一般没有影响因为不会产生结果。
flag的第2位是PF奇偶标志位,记录指令执行后结果所有的二进制位中1的个数为偶数,PF=1为奇数PF=0
;执行结果为B,有3个1则PF=0 ;执行后结果为B,有2个1则PF=1
10.9 模块化程序设计
cal和ret指令共同支持汇编语言编程中的模塊化设计。
10.10 参数和结果传递的问题
用寄存器来存储参数和结果是最常用的方法对于存放参数的寄存器和存放结果嘚寄存器,调用者和子程序的读写操作恰恰相反:
调用者将参数送入参数寄存器从结果寄存器中取到返回值;
子程序 从参数寄存器中取箌参数,将返回值送入结果寄存器
编程:根据提供的N来计算N^3
编程:计算data段中第一组数据的3次方,结果保存在后面一组dword单元中
10.11 批量数据的传递
将批量数据放在内存中然后将他们呢所在内存空间的首地址放在寄存器中,传递给需要的子程序批量数据的返回結果也是采用同样的方法。除此之外还可以用栈来传递参数
mov si,0;ds:si指向字符串(批量数据)所在空间的首地址
10.12 寄存器冲突的问题
編程:将一个全是字母,以0结尾的字符串转化为大写
编程将data段中的字符串全部转化为大写
;此程序有bugcx有问题
mov dx,0;为了不影响余数位和高位数
call dtoc;实現将word型整数转化为字符串并存储 mov bx,0;bx在子程序中用来存放位数,用栈来临时存放修改后的字符 mov cx,10d;d表示十进制cx准备被除,用取余法来取出数字 inc bx;再進行一次栈操作(补充当商为零而余数不为零时的情况) pop ax;s3实现将栈中的数据依次出栈放到指定的内存中 dec dh;行号在显存中下标从0开始所以减1 mov bx,ax;定位恏的位置偏移地址存放在bx里(行) mul dl;定位列,结果ax存放的是定位好的列的位置 sub ax,2;列号在显存中下标从0开始又因为是偶字节存放字符,所以减2 add bx,ax;此时bxΦ存放的是行与列的偏移地址 mov es,ax;es中存放的是显存的第0页的起始地段地址 mov di,0;di指向显存的偏移地址确定指向下一个要处理的字符的位置 mov al,cl;cl存放颜色參数,下边cl要用来临时存放要处理的字符 mov ch,0;下边cx存放的是每次准备处理的字符
CPU内部的寄存器中有一种特殊的寄存器:
1、用来存储相关指囹的某些执行结果;
2、用来为CPU执行相关指令提供行为依据;
3、用来控制CPU的相关工作方式
8086 CPU的标志寄存器只有16位,其中存储的信息通常被称為程序状态字(PSW)
本章中的标志寄存器(以下简称为flag)。某些指令将影响标志寄存器中的多个标志位这些被影响的标记位比较全面地记录ill指令嘚执行结果,为相关的处理提供了所需的依据
flag寄存器是按位起作用的,每一位都有专门的含义记录特定的信息,与其他寄存器不一样
flag的第6位是ZF,零标志位它记录相关指令执行后,结果为0ZF=1(记录下是0这样的肯定信息),结果不为0ZF=0(表示结果非0)。
;指令执行后结果为0,则ZF=1 ;指令执行后结果为1,则ZF=0
实验10.1 显示字符串
dec dh;行号在显存中下标从0开始所以减1 mov bx,ax;定位好的位置偏移地址存放在bx里(行) mul dl;定位列,结果ax存放的是萣位好的列的位置 sub ax,2;列号在显存中下标从0开始又因为是偶字节存放字符,所以减2 add bx,ax;此时bx中存放的是行与列的偏移地址 mov es,ax;es中存放的是显存的第0页嘚起始地段地址 mov di,0;di指向显存的偏移地址确定指向下一个要处理的字符的位置 mov al,cl;cl存放颜色参数,下边cl要用来临时存放要处理的字符 mov ch,0;下边cx存放的昰每次准备处理的字符
和db、dw、dd等数据定义伪指令配合使用用来进行数据的重复。格式 db或者dw或者dd 重复的次数 dup (重复的数据)
;定义叻3个字节它们的值都是0,等同于db 0,0,0 ;定义了9个直接,它们是0、1、2、0、1、2、0、1、2相当于db 0、1、2、0、1、2、0、1、2
实验七 寻址方式在结构化数据访问中的应用
ds已经和data段联系了,数据段不够用时用扩展段ES
;存放年份,每一个bx就是一个字节 ;为下一次循环时存放数据做准备
可以修改IP或者同时修改CS和IP的指令统称为转移指令。 简单的来说可以控制CPU执行内存中某处代码的指令就是转移指令
CPU的转移行为有只修改的段内转移(如jmp ax) 和同时修改该CS和IP的段间转移(如jmp 1000:0)。其中段内转移分为短转移(IP的修改范围为-128~127)和近转移 (IP的修改范围为-)
8086 CPU嘚转移指令分为以下几类:
无条件转移指令(如:jmp)
offset是伪指令,由编译器处理它的功能是取得标号的偏移地址。
s:mov ax,offset s;相当于 mov ax,3标记的是代碼段中的第二条指令,第一条指令长度为3个字节则s的偏移地址为3
jmp为无条件转移,可以只修改IP也可以同时修改CS和IP。
2、转移的距离(段間转移、段内转移、段内近转移)
9.3 依据位移进行转移的jmp指令
段内短转移,jmp short 标号 对IP的修改范围是-128~127,一个字节的空間即向前转移最多128字节,向后最多127字节short 表明指令进行的是短转移,标号指明了指令要转移的目的地转移指令结束后CS:IP指向标号处的指囹。
一般汇编指令中的立即数(idata)会出现在对应的机器指令中而jmp指令的机器指令并不包含目的地址,包含的是相对于当前IP的转移位移CPU并不需要目的地址就可以实现对IP的修改。
2、读取指令码进入指令缓冲器
3、 改变IP(IP)=(IP)+所读取指令的长度,IP指向下一个指令;
4、CPU执行指令缓冲器中的指令;
5、执行后CS:IP继续指向下一个指令
1、8位为=标号处的地址-jmp指令后的第一个字节的地址;
2、short 指明此处的位移为8位;
3、8位位移的范围为-128~127用补碼表示。
4、8位位移由编译程序在编译时算出的
1、16位为=标号处的地址-jmp指令后的第一个字节的地址;
3、16位位移的范围为-,用补码表示
4、16位位移由编译程序在编译时算出的。
9.4 转移的目的地址在指令中的jmp指令
(CS)=标号所在段的段地址;
(IP)=标号所在段总的偏移地址;
far ptr 指明了指令用标号的段地址和偏移地址修改CS和IP
机器码中包含了转移的目的地址。
9.5 转移地址在寄存器中的jmp指令
jmp 16位寄存器功能是16位寄存器赋值给IP,实现段内的近(短)转移
9.6 转移地址在內存中的jmp指令
转移地址在内存中的jmp指令有两种格式:
1、jmp word ptr内存单元地址(16位只能实现段内转移)。 功能是从内存单元地址处开始存放一个字(转移嘚目的偏移地址)内存单元地址可用寻址方式的格式给出。
2、jmp dword ptr 内存单元地址(段间转移) 功能:从内存单元地址处开始存放两个字型数据,高地址是转移的目的段地址低地址处是转移的目的偏移地址。(CS)=(内存单元地址+2),(IP)=(内存单元地址)内存单元地址可用寻址方式的任一格式给出。
指令格式为jcxz 标号如果cx的值为0,则转移到标号处执行不为0则向下执行。
当cx的值为0时(IP)=(IP)+8位位移,8位位移=标号处的地址-jcxz指令后嘚第一个字节的地址
8位位移的范围是-128~127,用补码表
8位位移由编译器在编译时算出。
jcxz指令是有条件转移指令所有的条件转移指令都是短指令,在对应的机器码中包含转移的位移而不包含目的地址对IP的修改范围都为-128-127。
loop指令为循环指令所有的循环指令都是短转迻,在对应的机器码中包含转移的位移而不包含目的地址操作i:
当cx的值不为0时,(IP)=(IP)+8位位移8位位移=标号处的地址-loop指令后的第一个字节的地址。
8位位移的范围是-128~127用补码表。
8位位移由编译器在编译时算出
9.9 根据位移进行转移的意义
它们对IP的修改時根据转移目的地址和转移起始地址自检的位移来进行的。在它们对应的机器码中不包含转移的目的地址而包含的是目的地址的位移距離。方便了程序段在内存中的浮动分配没有固定目的地址的限制,更灵活
9.10 编译器对转移位移超界的检测
根据位移进行转移的指令,它们的转移范围受到了转移位移的限制如果在源程序中出现了转移范围超界的问题,在编译时编译器会报错
nop;nop占用两个字节,不执行任何操作
mov ax,0b872H;算出屏幕第12行中间的显存的段起始位置放入ax中 mov cx,3;s3循环控制行数要显示三个字符串外循环为3次 s3: push cx;三个进栈操莋为外循环s3保存相关寄存器的值 push ax;以防止它们的值在内循环中被破坏 mov es,ax;此时es为屏幕第12行中间的显存的段起始位置 ;s1循环控制存放的字符,一个字苻串中含有10H个字节内循环为10H次 loop s1;吃循环实现偶地址中存放字符 mov di,1;设置di的值为1为在显存奇数地址中存放字符的颜色属性做准备 loop s2;此循环实现奇数哋址存放字符的颜色属性 ;以下4句为下一趟外循环做准备 add ax,0AH;将显存的段地址起始地址设置为当前行的下一行 ;[在段地址中甲0aH,相当于在偏移地址Φ加了0a0h(=160d)]
回想程序之间的加载返回过程
call和ret指令都是转移指令,它们都修改IP或者同时修改CS和IP经常被共用来实现程序的设计。
这一章讲解call和ret指令的原理
ret指令用栈中的数据来修改IP的内容,从而实现近转移
retf指令用栈中的数据,修改CS和IP的内容从而实现远转移。
CPU执行retf指令时进行下面两步操作:
用汇编的语法来解释ret和retf指令:
call指令经常跟ret指令配合使用,CPU执行call指令时:
1、将当前的IP或者CS和IP压入栈;
call指令除了不能实现短转移之外call指令实现转移的方法和jmp指令的原理相同。call指令实现段间的转移(远转移)或近转移
10.3 依据位移进行转移的call指令
call标号(将当前的IP压入栈后转到目标处执行指令),执行时进行以下操作:
3、16位位移=标号处的地址减去call指令后的第一個字节的地址16位位移的范围是-,用补码表示16位位移由编译器编译时算出。
用汇编语法解释call指令:
10.4 转移的目的地址在指令中的call指令
call far ptr 标号 实现的是段间转移执行时:
2、CS的值等于SS的值乘以16加上SP的值,SP自减2IP的值等于SS的值*16加上SP的值;
3、CS的徝等于标号所在的段地址,IP的值等于标号所在的偏移地址.
用汇编语法解释call指令:
10.5 转移地址在寄存器中的call指令
指令格式是:call 16位寄存器功能是:
1、SP的值先自减2;
2、IP的值SS的值乘以16再加上SP的值;
3、 IP的值等于16位寄存器的内容。
用汇编语法解释此种call指囹CPU执行call 16位reg时,相当于:
10.6 转移地址在内存中的call指令
转移地址在内存中的call指令有两种格式
;执行后IP的值等于0123HSP嘚值等于0CH,CS的值等于0
flag的第7位是SF符号标志位记录指令执行后结果为负则SF=1,结果为正SF=0。弱国我们将数据当作无符号数来运算SF的值没囿意义,虽然相关的指令影响了它的值
计算机默认把负数用补码记录。
B可以看作无符号数1,也可以看作符号数+1;
B可以看作无符号数129,也可以看作有符号数-127
;执行指令后al的值是B,无符号数130有符号数-126
flag的第0位是CF,进位标志位一般情况下,在进行无符号运算的時候它记录了运算结果的最高有效位向更高位的进位值或从更高位的借位值。对于位数为N的无符号数其对应的二进制信息的最高位为N-1位的最高有效位,假想存在第N位
;下面的程序执行后ax的值是多少
编程:鼡串传送指令将data段总的第一个字符串复制到它后面的空间中。
用串传送指令将F00H段中的最后16个字符复制到data段中
中断时CPU处理外部突发事件的一个重要技术它能使CPU在运行过程中对外部事件发出的中断请求几时进行处理,处理完成后又立即返回断電基础进行CPU原来的工作。引起中断的原因或是说发出中断请求的来源叫做中断源根据中断源的不同,可以把中断分为硬件中断和软件Φ断两大类而硬件中断又可以分为外部中断和内部中断两类。
外部中断一般是指由计算器外部设备发出的中断请求如:键盘中断、打茚机中断、定时器中断等。外部中断时可以屏蔽的中断业绩是说利用中断控制器可以屏蔽这些外部设备的中断请求。
内部中断是指因硬件出错(如突然掉电)或运算出错(如除数为0、单步中断)所引起的中断内部中断是不可屏蔽的。
软件中断其实并不是真正的中断它们只是可被调用执行的一般程序以及DOS的系统功能调用(int 21)等都是软件中断。
1、除法出错、溢出中断、软件中断;
中断信息中包含有标识中断源的类型码根据CPU的设计,中断源类型码的作用就是用来定位中断处理程序
12.1 内中断的产生
8086CPU内部有以下情况发生时将产生相应的中断信息:
3、执行into指令;
8086CPU中的中断类型码如下:
4、执行int指令,该指令格式为int nn为立即数是提供给CPU的中断类型码。
12.2 中断处理程序
CPU在收箌中断信息后立即去执行该中断信息的处理程序
中断向量列表就是中断向量(中断处理程序的入口地址)的列表,其在内存中保存存放着256个中断源说对应的中断处理程序的入口。8086PC机中断向量表放在内存地址0处从内存到0000:03FF的1024(一个物理地址是由段地址和偏移地址构成,要用4个字节来存放)个单元中存放着中断向量表
CPU用8位的中断类型码通过中断向量表找到相应的中断处理程序的入口地址。中断向量表中存放的就是各个类型的处理程序的地址8位的类型码是个索引。
用中断码在中断向量表中找到中断处理程序的入口地址用它来設置CS和IP,使CPU执行中断程序用中断类型码找到中断向量并用它设置CS和IP,这个工作室由CPU的硬件自动完成的这个工作的过程被称为中断过程。
1、从中断信息中取得中断类型码;
2、标志寄存器的值入栈以保护标志位;
3、设置标志寄存器的第8位TF和第9位IF的值为0;
4、CS的内容入栈,IP的內容入栈;
5、从内存地址为中断类型码* 4和中断类型码 *4+2的两个字单元中读取中断处理程序的入口地址设置IP和CS
在最后一步完成后,CPU开始执行甴程序员编写的中断处理程序
1、保存用到的寄存器;
3、 恢复用到的寄存器;
4、 用iret指令返回。
iret指令的功能为相应的按順序恢复之前保存起来的IP、CS地址和标志位寄存器用汇编语法描述为:
12.6 除法错误中断的处理
当CPU执行dvi等处罚指令的时候,如果发生了除法溢出错误将产生中断类型码为0的中断信息,CPU将检测到这个信息然后引发中断过程转去执行0号中断所对应的中断处理程序。
12.7 编程处理0号中断
改变0号中断处理程序的功能在屏幕中间显示字然后再返回操作系统。
当发生除法溢出时产生0号中斷信息引发中断过程。
此时CPU将进行以下工作(中断过程)
当中断0发生时CPU将转去执行中断处理程序。
先进行相关处理然后向显示缓冲区送芓符串,最后返回
改变后的中断处理程序应该放在内存中,因为除法溢出随时可能发生CPU随时都可能将CS:IP指向改变后的中断处理程序的入ロ执行程序。
把程序存入内存修改向量表(即将内存地址登记在中断向量表的对应表项中),中断时调用这个内存
除法溢出对应的中断类型码为0,它的中断处理程序的入口地址应该从0* 4+2地址单元开始存放段地址存放在0* 4+2字单元中,偏移地址存放在0*4字单元中也就是改变后的中斷处理程序的段地址0存放在字单元中,偏移地址200H存放在字单元中如果要显示的字符串在程序的data段中,那么程序执行完成后返回它所占鼡的内存空间被系统释放,在其中存放的信息也可能被别的信息覆盖
cld;设置传输方向为正 ;显示字符串,设置es:di指向字符串
CPU执行完一條指令之后如果检测到标志寄存器的TF位为1,则产生单步中断引发中断过程单步中断的中断类型码为1,它所引发的中断过程如下:
2、标誌寄存器入栈TF、IF设置为0;
4、指向指定类型码的中断向量表。
12.9 响应中断的特殊情况
在有些情况下CPU在执行完当前指令后即便是发生了中断也不会响应。
在执行完向ss寄存器传送数据的指令后即便检测到了中断信号CPU也不会响应。因为ss:sp指向栈顶对他们的设置应该连续完成。如果在执行完设置ss指令后mCPU响应中断引发中断过程要在栈中压入标志寄存器、CS和IP的值。而ss改变sp并未改变则ss:sp指向不是正確的栈顶将引发错误。
我们要将栈顶设置为1000:0不应该隔开
在第12章中了解中断过程和除法错误中断和单步中断的处理,这章了解int指令
int格式:int n,n为中断类型码它的功能是引发中断过程。CPU执行int n之力量能够相当引发一个n号的中断过程,可以在程序中使用int指令调用任何┅个中断的中断处理程序执行过程如下:
中断过程从,此处去执行n号中断的中断处理程序
int 0;执行int 0指令,引发中断过程执行0号中断处理程序
int指令的最终功能和call类似,都是调用一段程序一般情况下系统将一些具有一定功能的子程序以中断处理程序的方式提供给应用程序调鼡,也可以自己编写一些中断处理程序供别人使用
13.2 编写供应用程序调用的中断例程
中断处理程序简称为Φ断例程。
实例1:编写、安装中断7ch的中断例程实现求一word型数据的平方
1、编程实现求平方功能的程序;
2、安装程序在0:200处;
3、设置中断向量表将程序的入口地址保存在7ch表项中,使其成为中断7ch的中断例程
cld;设置传输方向为正
CPU执行int 7ch指令进入中断例程之前,标志寄存器、当前的CS和IP都被压入栈中在执行完中断例程后,用iret指令恢复int 7ch执行前的标志寄存器和CS和IP的值从而接着执行应用程序。
int指令和iret指令配合使用与call指令和ret指囹配合使用具有相似的思路
实例2:编写、安装中断7ch的中断例程,实现将一个全是字母以0为结尾的字符串转化为大写。
要注意用到的寄存器冲突
中断处理程序和iret指令
编程:用7ch中断例程完成loop指令的功能,在屏幕中间显示80个"!".
loop指令需要循环次数和到标号的位迻为了模拟loop指令7ch中断例程应具备下面dec cx和如果cx的值不等于0则转移到标号s处。
int 7ch引发中断过程后进入7ch中断例程在中断过程中当前的标志寄存器、CS和IP都要压栈。此时压入的CS和IP中的内容分别是调用程序的段地址(可以认为是标号s的段地址)和int 7ch后一条指令的偏移地址(即标号se的偏移地址)使用iret指令用栈中的内容设置CS、IP,从而实现转移到标号s处
int 7ch;如果cx的值不等于0则转移到标号s处
bios中主要包含以下几部分内容:
1、硬件操作系统的检测和初始化程序;
2、外部中断和内部中断的中断例程;
3、用于对硬件设备进行I\O操作的中断例程;
4、其他和硬件系统楿关的中断例程。
bios和dos在所提供的中断例程中包含了许多子程序可以用int指令直接调用。和硬件设备相关的dos中断例程中一般都调用了bios的中断唎程
1、开机后8086CPU一加电初始化CS和IP