CTFHUB技能树——Pwn前置技能学习
文章目录
- CTFHUB技能树——Pwn前置技能学习
- **PS:这里仅供查阅指令用,不需要很认真的学,因为写题过程中,你总要看汇编代码的,总会接触原理,自然而然就会懂了**
- **一、汇编语言学习**
- ***一、(一)基础知识***
- ***一、(二)寄存器***
- 一、(三)寄存器(内存访问)
- 一、(四)第一个程序
- 一、(五)[BX]和loop指令
- 一、(六)包含多个段的程序
- 一、(七)更灵活的定位内存地址的方法
- 一、(八)数据处理的两个基本问题
- 一、(九)转移指令的原理
- 一、(十)CALL和RET指令
- 一、(期中)课程设计一
- 一、(十一)标志寄存器
- 一、(十二)内中断
- 一、(十三)int指令
- 一、(十四)端口
- 一、(十五)外中断
- 指令系统总结
- 一、(十六)直接定址表
- 一、(十七)使用BIOS进行键盘输入和磁盘读写
- 指令系统总结
- 一、(十六)直接定址表
- 一、(十七)使用BIOS进行键盘输入和磁盘读写
- 一、(综合研究)
PS:这里仅供查阅指令用,不需要很认真的学,因为写题过程中,你总要看汇编代码的,总会接触原理,自然而然就会懂了
一、汇编语言学习
资料来源:
汇编语言(第4版)_9787302539414.pdf
一、(一)基础知识
a、计算机操作和机器指令及汇编指令的转化形式:
名称 | 实际行动 |
---|---|
操作 | 寄存器BX的内容发送到AX中 |
机器指令 | 1000100111011000 |
汇编指令 | mov ax,bx(即将BX的内容传送进AX) |
b、汇编语言的组成:
名称 | 实际操作 |
---|---|
汇编指令 | 机器码的助记符,有对应的机器码 |
伪指令 | 没有对应的机器码,由编译器执行,计算机并不执行 |
其他符号 | 如±*/等,有编译器识别,没有对应的机器码 |
c、指令和数据:
没有太大区别,只用应用时才会视作有区别
d、CPU对存储器的读写:
需要
- 存储单元的地址(地址信息);
- 器件的选择,读或写的命令(操作信息);
- 读或写的数据(数据信息)
过程:
e、转化形式:
名称 | 解释 |
---|---|
机器码 | 101000010000001100000000 |
对应的汇编指令 | MOV AX,[3] |
含义 | 传送3号单元的内容入AX |
f、机器部件:
名称 | 解释 |
---|---|
存储单元 | 是存储器的单元划分,一般编号为0-127 |
地址总线 | CPU通过地址总线来指定存储器单元,一般CPU通过这个计算可对对少存储单元进行寻址,如若有N根线,则可寻找2的N次方个内存单元 |
数据总线 | CPU通过数据总线进行与内存或其他器件之间的数据传送,1根数据可传送1位8位二进制数据(1bit) |
a-f小结:
a-f检测:
g、内存地址空间
CPU能探寻的内存单元
g、①主板
g、②接口卡
h、各类存储器芯片
从读写分两类:随机存储器和只读存储器
名称 | 解释 |
---|---|
随机储存器 | 存放CPU使用的绝大部分程序和数据 |
装有BIOS的ROM | 利用该硬件,设备进行最基本输入输出 |
接口卡上的RAM | 对接口卡的大批量数据输入输出数据进行暂时存储 |
I、各类存储器的逻辑连接情况
J、内存地址空间
一、(二)寄存器
CPU的主要部件
即可用指令读写的部件
在CPU中:
通用寄存器
AX、BX、CX、DX四种
一个寄存器能存储16位,同时可拆分为两个八位的寄存器
字在寄存器的存储
8086CPU可一次性处理两种尺寸的数据
几条汇编指令
汇编指令 | 控制CPU完成的操作 | 用高级语言的语法描述 |
---|---|---|
mov ax,18 | 将18送入寄存器AX | AX=18 |
mov ah,78 | 将78送入寄存器AH | AH=78 |
add ax,8 | 将寄存器AX中的数值加上8 | AX=AX+8 |
mov ax,bx | 将寄存器BX中的数据送入寄存器AX | AX=BX |
add ax,bx | 将AX和BX中的数值相加,结果存在AX中 | AX=AX+BX |
即超出的位会被“丢弃”
正确的指令和错误的指令:
物理地址
即每个内存单元在此空间中的唯一地址,称为物理地址
16位结构的CPU
能一次性处理、传输、暂时存储的信息的最大长度为16位
8086CPU给出物理地址的方法
段地址x16+偏移地址=物理地址的本质含义
CPU在访问内存时,用基础地址和一个相对基础地址的偏移地址相加,给出内存单元的物理地址
形象比喻:
段的概念
即对内存地址的划分,不是物理意义上的分段
段寄存器
即形如:CS,DS,SS,ES的寄存器,可提供该内存单元的段地址
CS和IP
CS为代码段寄存器,IP为指针寄存器
在8086PC机中,如若CS的内容为M,IP的内容为N,8086CPU将从内存Mx16+N单元开始,读取指令执行
亦或如此理解:8086机中,任意时刻,CPU将CS:IP指向的内容当成指令执行
如果内存内的一段信息曾被CPU执行过的话,那么,它所在的内存单元必然被CS:IP指向过
修改CS、IP的指令
jmp命令:转移指令
jmp 段地址:偏移地址
jmp 某一合法寄存器
用寄存器中的值修改IP
代码段
若有一段N字节的指令,存放在指定的一组内存单元内,那么就可认为,这组内存单元即用来存放代码的,是一个代码段,长度为N个字节
小结
实验一:查看PDF:Debug指令表
一、(三)寄存器(内存访问)
内存中字的存储:字单元
字单元的概念:即存放一个字形数据(16位)的内存单元,由两个地址连续的内存单元组成
将起始地址为N的字单元简称为N地址单元。
PS:任何两个地址连续的内存单元,N号单元和N+1号单元,也可看成两个内存单元,也可看成一个地址为N的字单元中的高位字节单元和低位字节单元
0 | 20H |
---|---|
1 | 4EH |
2 | 12H |
3 | 00H |
4 | |
5 |
DS和[address]
DS寄存器:存放要访问数据的段地址
mov al,[0] //[]代表从内存单元偏移地址为零取出数值,而如果不指定,则将会从段地址寄存器ds取出
PS:不能直接mov ds,1000H之类的操作,只能中转,即由一般寄存器存放后,转移到ds
字的传送
mov指令,可在寄存器和内存之间进行字节型数据的传送
例子:
mov(传送)、add(相加)、sub(相差)命令
mov:
指令方式 | 例子 |
---|---|
mov 寄存器,数据 | mov ax,8 |
mov 寄存器,寄存器 | mov ax,bx |
mov 寄存器,内存单元 | mov ax,[0] |
mov 内存单元,寄存器 | mov [0],ax |
mov 段寄存器,寄存器 | mov ds,ax |
数据段
即一组包含数据的内存单元,然后将其导入ds,即可通过ds访问数据段中的具体单元
小结:
栈
数据结构:一种概念,后进先出
CPU提供的栈机制
push和pop指令,和栈是同理的
引出两个寄存器:段寄存器SS和寄存器SP,SS:SP指向栈顶元素
栈顶超界问题
只能自己注意,8086CPU没有对应的措施
push、pop命令
一些命令:
形式 | 解释 |
---|---|
push 寄存器 | 将一个寄存器中的数据入栈 |
pop 寄存器 | 出栈,用一个寄存器接收出栈的数据 |
push 段寄存器 | 同上的push |
pop 段寄存器 | 同上的pop |
push 内存单元 | 将一个内存单元处的字入栈(栈操作均以字为单位) |
pop 内存单元 | 出栈,用一个内存单元接收出栈的数据 |
栈的综述
栈段
即栈占用的内存空间
一个栈段最大容量64KB
栈的综述
实验二、看PDF
一、(四)第一个程序
一个源程序从写出到执行的过程
步骤 | 实际工作结果 |
---|---|
编写汇编源程序 | 产生了一个存储原程序的文本文件 |
对源程序进行编译链接 | 产生了一个可在操作系统中运行的可执行文件 |
执行可执行文件中的程序 | 操作系统根据描述信息,进行相关初始化并执行程序 |
源程序
1、伪指令
指令 | 解释 |
---|---|
XXX segment和 XXX ends | 定义一个段,segment代表段开始,ends代表段结束 |
end | 汇编语言的结束标记 |
assume | 将有特定用途的段和相关的段寄存器关联 |
2、源程序中的“程序”
这里的程序指的是源程序中最终由计算机执行、处理的指令或数据
3、标号
标号指代了一个地址
例如刚刚的codesg作为一个段的名称,最终将被编译、链接程序处理为一个段的段地址
4、程序的结构
形如写代码的框架
5、程序返回
目前尚未解释
但指明:
使用
mov ax,4c00H int 21H
即可使得程序返回
与结束相关的概念:
目的 | 相关指令 | 指令性质 | 指令执行者 |
---|---|---|---|
通知编译器一个段的结束 | 段名 ends | 伪指令 | 编译时,由编译器执行 |
通知编译器程序结束 | end | 伪指令 | 编译时,由编译器执行 |
程序返回 | mov ax,4c00H int 21H | 汇编指令 | 执行时,由CPU执行 |
6、语法错误和逻辑错误
和正常的写代码时的错误差不多
编辑源程序
也就是写代码
这里使用DOSBOX
DOS中输入edit
然后输入程序
保存为C:\1.asm
assume cs:codesg
codesg segment
mov ax,0123h
mov bx,0456h
add ax,bx
add ax,ax
mov ax,4c00h
int 21h
codesg ends
end
编译
使用MASM5.0即可
下载MASM5.0后跳转到其目录,然后
输入masm.exe运行masm
过程如图所示:
连接
生成可执行文件,步骤如图:
以简化的方式进行编译和连接
即使用
masm c:\1;(省略后缀)
link 1;
生成1.exe
程序执行过程的跟踪
使用Debug 1.exe即可
PSP:程序段前缀的数据区
这里讲解了我们的程序加载在内存的什么地方
而这个地方即ds:0,也就是PSP后,PSP在内存区前0-255,程序就会从256开始
通俗易懂的计算:
从ds可得知PSP的段地址SA,又PSP的偏移地址为0,那么PSP物理地址为SA*16+0,又因为PSP占256字节(100H),那么程序的物理地址为:SA*16+0+256=SA*16+16*16+0=(SA+16)*16+0
用段地址和偏移地址表示为:SA+10H:0
在Debug中使用T命令单步执行程序中每个指令,到了int 21,使用P命令,然后使用Q命令退出debug
实验三:看pdf:必须完成
一、(五)[BX]和loop指令
一些描述:
[bx]和内存单元的描述
注意到[0]作为表示内存单元,即解释:
[0]表示一个内存单元时,0表示单元的偏移地址,段地址默认在ds中,单元的长度(类型)可以由具体指令中的其他操作对象(比如说寄存器)指出
[bx]也同样为表示内存单元,即解释:
[bx]表示一个内存单元你是,它的偏移地址在bx中,段地址默认在ds中,单元的长度(类型)可以由具体指令中的其他操作对象(比如说寄存器)指出
loop
循环的含义
定义的描述性符号:“()”
"()"表示一个寄存器或一个内存单元中的内容:
比如:
(ax)表示ax中的内容、(al)表示al中的内容;
应用:
约定符号idata表示常量
[BX]
功能:
注意等号应该为赋值的意思,不是相等
Loop指令
格式:loop 标号
CPU执行loop指令的时候,进行两步操作:
- (cx)=(cx)-1;
- 判断cx中的值,必为零则转至标号处执行程序,如果为零则向下执行
可知:cx的值影响loop指令的执行结果,通常:loop指令实现循环功能,cx中存放循环次数。
Debug跟踪loop
要点:G命令可指定执行次数,
用法:g IP
这里的IP即让指针在IP时继续对loop的指令执行
要点:P命令可一次性执行完所有次数
Debug和汇编编译器masm对指令的不同处理
简述:Debug视mov ax,[0]的操作中[idata]为内存单元,而编译器解释为idata
那么统一:mov ds,ax后,使用mov al,ds:[0]
即显式地给出段地址所在的段寄存器
loop和[bx]的联合应用
程序对比:
和
段前缀
一段安全的空间
段前缀的使用
即不过度设置ds
实验四:看PDF
一、(六)包含多个段的程序
在代码段中使用数据
dw:定义字型数据,即defind word,可用在代码段中
标号start:与end start连用
end start:end后面的start可以提醒编译期程序的入口在什么地方
程序的框架图
在代码段中使用栈
也就是通过dw的形式,定义一个类似于数组的玩艺儿,把它当成栈来使用就可以了
将数据、代码、栈放入不同的段
通过name segment实现,然后通过mov 寄存器,name访问name段地址
实验五:看pdf实现
一、(七)更灵活的定位内存地址的方法
and 和 or 指令
and指令:逻辑与指令,按位进行与运算
or指令:逻辑或指令,按位进行或运算
关于ASCII码
如何显示在控制台中:将字符的ascii码输入显存中
以字符形式给出的数据
db:defind byte,定义数据,并将其存储在内存中,以’'单引号括起来的内容被视为字符形式,将会转化为ascii码存储到内存中
大小写转化的问题
一般来说,应该减去大写和小写之间的数值差:20,但在汇编中,我们应该通过二进制的方法,观察客至,第五位置决定了是否为大小写:自己观察或者看书即可知道了
[bx+idata]
表示一个内存单元:它的偏移地址为(bx)+idata(bx中的数值加上idata)
数学化的描述为:(ax) = ((ds)*16+(bx)+200)
可写为:
mov ax,[200+bx] mov ax,200[bx] mov ax,[bx].200
用[bx+idata]的方式处理数组
形象化:
C语言:a[i],b[i]
汇编语言:0[bx],5[bx]
SI和DI
和bx功能类似的寄存器,但是不能分开成bh,bl这样的两个八位寄存器,通常用来处理字符串,SI存储源(source),DI存储目的(Destination),这两个的i代表index
[bx+si]和[bx+di]
表示一个内存单元,偏移地址为(bx)+(si)(即bx中的数值加上si中的数值)
数学化描述为:
(ax) = ((ds)*16+(bx)+(si))
可写成以下格式
mov ax,[bx][si]
[bx+si+idata]和[bx+di+idata]
表示一个内存单元,偏移地址为(bx)+(si)+idata(即bx中的数值加上si中的数值,再加上idata)
数学化描述为:
(ax) = ((ds)*16+(bx)+(si)+idata)
可写成以下格式
mov ax,[bx+200+si] mov ax,[200+bx+si] mov ax,200[bx][si] mov ax,[bx].200[si] mov ax,[bx][si].200
不同寻址方式的灵活运用
- [idata]用一个常量来表示地址,可用于直接定位一个内存单元;
- [bx]用一个变量来表示内存地址,可用于间接定位一个内存单元;
- [bx+idata]用一个变量和常量表示地址,可在一个起始地址的基础上用变量间接定位一个内存单元
- [bx+si]用两个变量表示地址
- [bx+si+idata]用两个变量和一个常量表示地址
一般来说,在需要暂存数据的时候,都应该使用栈
实验六:实践课程中的程序
一、(八)数据处理的两个基本问题
前置知识
描述型符号:reg和sreg
reg的集合:ax,bx,cx,dx,ah,al,bh,bl,ch,cl,dh,dl,sp,bp,si,di
sreg的集合:ds,ss,cs,es
bx、si、di和bp
- 在8086CPU中,只有这四个寄存器可以用在"[…]"中来进行内存单元的寻址
- 在[…]中,这四个寄存器可以单个出现,或只能以四种组合出现:bx和si、bx和di、bp和si、bp和di
- 只要在[…]中使用寄存器bp,而指令中没有先行的给出段地址,段地址就默认在ss中
机器指令处理的数据在什么地方
指令执行前一刻,所要处理数据所在的位置:CPU内部、内存、端口
机器码 | 汇编指令 | 指令执行前数据的位置 |
---|---|---|
8E1E0000 | mov bx,[0] | 内存,ds:[0]单元 |
89C3 | mov bx,ax | CPU内部,ax寄存器 |
BB0100 | mov bx,1 | CPU内部,指令缓冲器 |
汇编语言中数据位置的表达
- 立即数(idata)
即直接包含在机器指令中的数据(执行在CPU的指令缓冲器中),在汇编语言中称为立即数(idata),在汇编指令中直接给出 - 寄存器
指令要处理的数据啊在寄存器中,在汇编指令中给出相对应的寄存器名 - 段地址(SA)和偏移地址(EA)
指令要处理的数据在内存中,在汇编指令中可用[X]的格式给出EA,SA在某个段寄存器中
寻址方式
指令要处理的数据有多长
- 通过寄存器名指明要处理的数据的尺寸
- 在没有寄存器名存在的情况下,用操作符X ptr指明内存单元的长度,X在汇编指令中可以为word或者byte
- 其他方法
寻址方式的综合应用
以不同方式用在合理的地方
div指令
div是除法指令
注意的问题:
- 除数:有8位和16位两种,在一个reg或内存单元中
- 被除数:默认放在AX或DX和AX中,如果除数位8位,则被除数为16位,默认在AX中存放;如果除数位16位,被除数则为32位,在DX和AX中存放,DX存放高16位,AX存放低16位
- 结果:如果被除数位8位,则AL存储除法操作的商,AH存放除法操作的余数;如果除数位16位,则AX存储除法操作的商,DX存储除法操作的余数
伪指令dd
用来定义dword(double word,双字)型数据的
dup
操作符,用来进行数据的重复。
实验七:寻址方式在结构化数据访问中的应用:这个是对从前学习的最好实践
一、(九)转移指令的原理
前置知识
可以修改IP,或同时修改CS和IP的指令统称为转移指令,即,可以控制CPU执行内存中某处代码的指令
8086CPU的转移行为有:
- 只修改IP时,称为段内转移,比如:jmp ax
- 同时修改CS和IP时,称为段间转移,比如:jmp 1000:0
由于转移指令对IP的修改范围不同,段内转移又分为:短转移和近转移
- 短转移IP的修改范围为-128~127
- 近转移IP的修改范围位-32768~32767
8086CPU的转移指令分为以下几类
- 无条件转移指令(jmp)
- 条件转移指令
- 循环指令(loop)
- 过程
- 中断
操作符offset
功能是取得标号的偏移地址
jmp指令
无条件转移指令,可以只修改IP,也可同时修改CS和IP
jmp要给出两种信息:
- 转移的目的地址
- 转移的距离(段间转移、段内短转移、段内近转移)
根据位移进行转移的jmp指令
转移的目的地址在指令中的jmp指令
jmp far ptr 标号实现的是段间转移,又称为远转移
转移地址在寄存器中的jmp指令
功能格式:jmp 16位reg
功能:(IP)=(16位reg)
转移地址在内存中的jmp指令
两种格式:
jmp word ptr 内存单元地址(段内转移)
功能:从内存单元地址处开始存放着一个字,是转移的目的偏移地址jmp dword ptr 内存单元地址(段间转移)
功能:从内存单元地址处开始存放着两个字,高地指出的字是转移的目的段地址,低地址处是转移的目的偏移地址(CS)=(内存单元地址+2)
(IP)=(内存单元地址)
jcxz指令
指令形式:jcxz 标号(如果(cx)=0),转移到标号处执行
操作:当(cx)=0时,(IP)=(IP)+8位位移
loop指令
根据位移进行转移的意义
jmp short 标号
jmp near ptr 标号
jcxz 标号
loop 标号
编译器对转移位移超界的检测
实验八:分析一个奇怪的程序
实验九:根据材料编程
一、(十)CALL和RET指令
前置知识
这两个命令都是转移指令,都修改IP,或同时修改CS和IP。经常被共同用来实现子程序的设计。
ret和retf
用栈中的数据
指令 | 修改什么 | IP或CS和IP的变化 |
---|---|---|
ret | IP,实现近转移 | 1、(IP)=((ss)*16+(sp));2、(sp)=(sp)+2 |
retf | CS和IP,实现远转移 | 1、(IP)=((ss)*16+(sp));2、(sp)=(sp)+2;3、(CS)=((ss)*16+(sp));4、(sp)=(sp)+2 |
执行ret指令时相当于进行:pop IP;执行retf指令时相当于进行:pop IP和pop CS |
---|
call指令
执行call指令时:
- 将当前的IP或CS和IP压入栈中
- 转移
根据位移进行转移的call指令
call 标号(将当前的IP压入栈后,转移到标号处执行指令)
执行此格式的call指令时,进行:
- (sp)=(sp)-2
((ss)*16+(sp))=(IP) - (IP)=(IP)+16位位移
其实相当于:
push IP
jmp near ptr 标号
转移的目的地在指令中的call指令
call far ptr 标号 实现的是段间转移
执行此格式的call指令时,进行如下操作。
- (sp)=(sp)-2
((ss)*16+(sp))=(CS)
(sp)=(sp)-2
((ss)*16+(sp))=(IP) - (CS)=标号所在段的段地址
(IP)=标号在段中的偏移地址
相当于:
push CS
push IP
jmp far ptr 标号
转移地址在寄存器中的call指令
指令格式:call 16位reg
功能:
(sp)=(sp)-2
((ss)*16+(sp))=(IP)
(IP)=(16位reg)
相当于:
push IP
jmp 16位reg
转移地址在内存中的call指令
-
call word ptr 内存单元地址
相当于:
push IP
jmp word ptr 内存单元地址 -
call dword ptr 内存单元地址
相当于:
push CSpush IP
jmp dword ptr 内存单元地址
call和ret的配合使用
用于编写一个具有一定功能的程序段,称为子程序;框架如下;
mul指令
乘法指令
注意要点:
- 两个相乘的数:位数相同,8位对8位,16位对16位
- 结果:如果是8位,结果默认放在AX中;如果是16位,结果高位默认在DX中存放,低位在AX中放
格式:
- mul reg
- mul 内存单元
模块化程序设计
使用call和ret指令
参数和结果传递的问题
用寄存器存储参数和结果
- 对于调用者:将参数送入参数寄存器,从结果寄存器中取得返回值;
- 对于子程序:从参数寄存器中取得参数,将返回值送入结果寄存器;
批量数据的传送
使用栈或连续的内存空间,然后使用其首地址
寄存器冲突的问题
子程序编写标准框架,如下:
实验十:编写子程序
一、(期中)课程设计一
一、(十一)标志寄存器
前置知识
特殊寄存器:标识寄存器的作用
- 用来存储相关指令的某些执行结果
- 用来为CPU执行相关指令提供行为依据
- 用来控制CPU的相关工作方式
简称:flag
15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
OF | DF | IF | TF | SF | ZF | AF | PF | CF |
flag的图上空白的位在8086CPU没有使用,不具有含义,其余有含义
ZF标志
- 零标志位。用于记录相关指令执行后,期结果是否为0。如果结果为0,那么zf=1;如果结果不为0,那么zf为0
PF标志
- 奇偶标志位。用于记录相关指令执行后,其所有结果中的所有bit位中1的个数是否位偶数,如果是,则,pf=1,否则pf=0
SF标志
- 符号标志位。用于记录相关指令执行后,其结果是否为负。如果是,则sf=1,非负则sf=0
CF标志
- 进位标志位。记录运算结果的最高有效位向更高位的进位值,或从更高位的借位值
OF标志
- 溢出标志位。一般情况下,OF记录了有符号数运算的结果是否发生了溢出,如果是,则OF=1;如果没有,OF=0
- CF和OF的区别:CF是对无符号数运算有意义的标志位,而OF是对有符号数运算有意义的标志位
abc指令
带进位加法指令,利用的就是就是CF位上记录的进位值
指令格式:
abc 操作对象1,操作对象2
功能:操作对象1 = 操作对象1 + 操作对象2 + CF
abc指令和add指令相配合就能对更大的数据进行加法运算
sbb指令
带借位减法指令,利用CF位上记录的借位值
指令格式:sbb 操作对象1,操作对象2
功能:操作对象1 = 操作对象1 - 操作对象2 - CF
sbb指令可以对任意大的数据进行减法运算
cmp指令
比较指令,功能相当于减法指令,但不保存结果,会对flag产生影响
指令格式:
cmp 操作对象1,操作对象2
功能:
计算操作对象1 - 操作对象2,但不保存结果
- 如果因为溢出导致实际结果为负,那么逻辑上,真正的结果必然为正
- 反之为负
通过比较结果的条件转移指令
DF标志和串传送指令
1、DF标志
方向标志位,控制每次操作后si、di的增减
2、串传送指令
1️⃣、movsb
功能:将ds:si指向的内存单元中的字节送入es:di中,根据标志寄存器df位的值,将si和di递增或递减
相当于:
- ((es)*16+(di))=((ds)*16+(si))
- 如果df=0则:(si)=(si)+1
(di)=(di)-1
如果df=1则:(si)=(si)-1
(di)=(di)-1
2️⃣、movsw
功能:将ds:si指向的内存字单元中的字送入es:di中,然后根据标志寄存器df位的值,将si和di递增2或递减2
3️⃣、总结
一般来说,movsb和movsw都和rep配合使用,格式如下:rep movsb
功能:
s:movsb
loop s
pushf和popf
pushf:将标志寄存器的值压栈
popf:从栈中弹出数据,送入flag中
标志寄存器在Debug中的表示
标志 | 值为1的标记 | 值为0的标记 |
---|---|---|
of | OV | NV |
sf | NG | PL |
zf | ZR | NZ |
pf | PE | PO |
cf | CY | NC |
df | DN | UP |
实验十一:编写子程序
一、(十二)内中断
前置知识
中断信息:如若从外部或者内部检测到产生了一中特殊信息,则立即队所接受到的信息进行处理(中断:CPU不再接着(刚执行完的指令)向下执行,转去处理这个特殊信息) |
---|
内中断的产生
产生以下情况时,产生对应的中断信息: |
---|
- 除法错误,比如,执行div指令产生的除法溢出
- 单步执行
- 执行into指令
- 执行int指令
中断码如下: |
---|
- 除法错误:0
- 单步执行:1
- 执行into指令:4
- 执行int指令,该指令的格式位int n,指令中的n为字节型立即数,是提供给CPU的中断类型码
中断处理程序
用来处理中断信息的程序
根据8位的中断类型码得到中断处理程序的段地址和偏移地址
中断向量表
CPU通过8位的中断类型码的中断向量表处理中断程序的入口地址,这里的中断向量的列表就是中断向量表:中断处理程序入口地址的列表
一个表项存放一个中断向量,也就是一个中断处理程序的入口地址:包括段地址和偏移地址,占两个字,高地址字存放段地址,低地址字存放偏移地址
中断过程
用中断类型码找到中断向量,并用它设置CS和IP,这个过程就是中断过程
8086CPU在 收到信息后,所引发的中断过程: |
---|
- (从中断信息中)取得中断类型码
- 标志寄存器的值入栈
- 设置flag的第8位TF和第九位IF的值位0
- CS的内容入栈
- IP的内容入栈
- 从内存地址为中断类型码*4和中断类型码*4+2的两个字单元中读取中断处理程序的入口地址设置IP和CS
简洁地描述中断过程: |
---|
- 取得中断类型码N
- pushf
- TF=0,IF=0
- push CS
- push IP
- (IP)=(N*4),(CS)=(N*4+2)
中断处理程序和iret指令
中断处理程序的编写方法: |
---|
- 保存用到的寄存器
- 处理中断
- 恢复用到的寄存器
- 用iret指令返回
iret指令的汇编语法描述: |
---|
pop IP
pop CS
popf
除法错误中断的处理
显示提示信息“Divide overflow”后,返回操作系统中
编程处理0号中断
- 编写可以显示"overflow!"的中断处理程序:do0
- 将do0送入内存0000:0200处
- 将do0的入口地址0000:0200存储在中断向量表0号表项中
框架如下:
- 安装do0,设置中断向量的程序
- do0
安装
可使用movsb指令,将do0的代码送入0:200处
程序如下:
assume cs:code
code segment
start:设置es:di指向目的地址
设置ds:si指向源地址
设置cx为传输长度
设置传输方向为正
rep movsb
设置中断向量表
mov ax,4c00h
int 21h
do0:显示字符串"overflow!"
mov ax,4c00h
int 21h
code ends
end start
使用rep movsb指令要确定的信息: |
---|
- 传送的原始位置,段地址:code,偏移地址:offset do0
- 传送的目的位置:0:200
- 传送的长度:do0部分代码的长度
- 传送的方向:正向
更明确的程序:
do0
程序如下:
更完善的代码: |
---|
设置中断向量
单步中断
响应中断的特殊情况
实验十二:编写0号中断的处理程序
一、(十三)int指令
int指令
格式为:int n;n为中断类型码,功能是引发中断过程
执行过程:
- 取中断类型码n
- 标志寄存器入栈,IF=0,TF=0;
- CS、IP入栈
- (IP)=(n*4),(CS)=(n*4+2)
int指令的最终功能和call指令类似,都是调用一段程序
编写供应用程序调用的中断例程
避免寄存器的冲突,注意寄存器值的保存和恢复
对int、iret和栈的深入了解
也就是如何利用这三个指令实现loop功能
BIOS和DOS所提供的中断例程
BIOS中主要包括以下几部份内容
- 硬件系统的检测和初始化程序
- 外部中断和内部中断的中断例程
- 用于对硬件设备进行I/O操作的中断例程
- 其他和硬件系统相关的中断例程
BIOS和DOS中断例程的安装过程
BIOS中断例程应用
int 10h中断例程是BIOS提供的中断例程,包含多个和屏幕相关的子程序
BIOS和DOS提供和的中断例程一般用ah传递内部子程序的编号
DOS中断例程的应用
实验十三、编写、应用中断例程
一、(十四)端口
端口的读写
CMOS RAM芯片
shl和shr指令
逻辑位移指令
CMOS RAM中存储的时间信息
实验十四、访问CMOS RAM
一、(十五)外中断
接口芯片和端口
CPU通过端口和外部设备进行联系
外中断信息
1、可屏蔽中断
2、不可屏蔽中断
PC机键盘的处理过程
1、键盘输入
2、引发9号中断
3、执行int 9中断例程
编写int 9中断例程
1、从端口60h读出键盘输入
int al,60h
2、调用BIOS的int 9中断例程
3、如果是Esc的扫描码,改变显示的颜色后返回
安装新的int 9中断例程
实验十五、安装新的int 9中断例程
指令系统总结
8086CPU提供以下几大类指令。
1.数据传送指令
比如,mov、push、pop、pushf、.popf、xchg等都是数据传送指令,这些指令实现寄存器和内存、寄存器和寄存器之间的单个数据传送。
2.算术运算指令
比如,add、sub、adc、sbb、inc、dec、cp、imul、idiv、aaa等都是算术运算指令,这些指令实现寄存器和内存中的数据的算数运算。它们的执行结果影响标志寄存器的sf、zf、of、cf、pf、af位。
3.逻辑指令
比如,and、or、not、xor、test、shl、shr、sal、sar、rol、Ior、rcl、Icr等都是逻辑指令。除了not指令外,它们的执行结果都影响标志寄存器的相关标志位。
4.转移指令
可以修改P,或同时修改CS和P的指令统称为转移指令。转移指令分为以下几类。
- 无条件转移指令,比如,jmp:
- 条件转移指令,比如,jcxz、je、jb、ja、jnb、jna等:
- 循环指令,比如,loop:
- 过程,比如,call、Iet、retf
- 中断,比如,int、iret。
5.处理机控制指令
这些指令对标志寄存器或其他处理机状态进行设置,比如,cld、std、ci、sti、nop、clc、cmc、stc、hlt、wait、esc、lock等都是处理机控制指令。
6.串处理指令
这些指令对内存中的批量数据进行处理,比如,movsb、movsw、cmps、scas、lods、stos等。若要使用这些指令方便地进行批量数据的处理,则需要和rep、repe、repne等前缀指令配合使用。
一、(十六)直接定址表
描述单元长度的标号
即a db 1,2,3,4,5,6
在其他段中使用数据标号
直接定址表
程序入口地址的直接定址表
实验十六:编写包含多个功能子程序的中断例程
一、(十七)使用BIOS进行键盘输入和磁盘读写
不可屏蔽中断
[外链图片转存中…(img-FzAjfl8f-1713970527606)]
PC机键盘的处理过程
1、键盘输入
[外链图片转存中…(img-ElUvUG9z-1713970527606)]
[外链图片转存中…(img-g1fD0qU9-1713970527607)]
[外链图片转存中…(img-DmyDDPTk-1713970527607)]
2、引发9号中断
[外链图片转存中…(img-wNyGr6uR-1713970527607)]
3、执行int 9中断例程
[外链图片转存中…(img-jkUJDX80-1713970527607)]
编写int 9中断例程
1、从端口60h读出键盘输入
int al,60h
2、调用BIOS的int 9中断例程
[外链图片转存中…(img-5NloEgOZ-1713970527607)]
3、如果是Esc的扫描码,改变显示的颜色后返回
安装新的int 9中断例程
[外链图片转存中…(img-8sVOhkfn-1713970527608)]
实验十五、安装新的int 9中断例程
指令系统总结
8086CPU提供以下几大类指令。
1.数据传送指令
比如,mov、push、pop、pushf、.popf、xchg等都是数据传送指令,这些指令实现寄存器和内存、寄存器和寄存器之间的单个数据传送。
2.算术运算指令
比如,add、sub、adc、sbb、inc、dec、cp、imul、idiv、aaa等都是算术运算指令,这些指令实现寄存器和内存中的数据的算数运算。它们的执行结果影响标志寄存器的sf、zf、of、cf、pf、af位。
3.逻辑指令
比如,and、or、not、xor、test、shl、shr、sal、sar、rol、Ior、rcl、Icr等都是逻辑指令。除了not指令外,它们的执行结果都影响标志寄存器的相关标志位。
4.转移指令
可以修改P,或同时修改CS和P的指令统称为转移指令。转移指令分为以下几类。
- 无条件转移指令,比如,jmp:
- 条件转移指令,比如,jcxz、je、jb、ja、jnb、jna等:
- 循环指令,比如,loop:
- 过程,比如,call、Iet、retf
- 中断,比如,int、iret。
5.处理机控制指令
这些指令对标志寄存器或其他处理机状态进行设置,比如,cld、std、ci、sti、nop、clc、cmc、stc、hlt、wait、esc、lock等都是处理机控制指令。
6.串处理指令
这些指令对内存中的批量数据进行处理,比如,movsb、movsw、cmps、scas、lods、stos等。若要使用这些指令方便地进行批量数据的处理,则需要和rep、repe、repne等前缀指令配合使用。
一、(十六)直接定址表
描述单元长度的标号
即a db 1,2,3,4,5,6
[外链图片转存中…(img-eB68mGnB-1713970527608)]
[外链图片转存中…(img-JcsFYYQw-1713970527608)]
在其他段中使用数据标号
[外链图片转存中…(img-JvRN6uTg-1713970527609)]
直接定址表
[外链图片转存中…(img-zY4hvEPQ-1713970527609)]
程序入口地址的直接定址表
[外链图片转存中…(img-tUpZJLeF-1713970527609)]
[外链图片转存中…(img-Vk7BwjUl-1713970527609)]