汇编语言
基础知识
机器语言
cpu是一种微处理器,cpu及其控制的芯片,器件,设备组成了我们所说的pc机。
由于每一种微处理器的硬件设计不同,内部结构不同。所以需要不同的点评脉冲来控制。所以每一种微处理器都有自己的机器指令集,也就是机器语言。(这也就是我们自研发cpu的一个难点,这些硬件架构是有版权的)
汇编语言
汇编语言的主体是汇编指令,汇编指令和机器指令的 差别在于表示方法上,汇编指令是机器指令便于记忆的书写格式。
汇编语言的组成
- 汇编指令
- 伪指令(没对应的机器码,编译器执行
- 其他符号(编译器识别,没对应的机器码
存储单元
微机存储器的一个存储单元可以存储一个Byte(8bit)
区别于网速的10^3,存储的进制是2^10
CPU对存储器的读写
CPU想要进行读写必须要和外部器件(芯片)进行3类信息交互
- 存储单元的地址
- 器件的选择,读或写命令
- 读或写的数据
- cpu通过地址总线发出地址信息3
- cpu通过控制总线发出内存读命令,选中存储器芯片,通知他
- 存储器将3好存储单元的信息通过数据总线发送
地址总线
N根地址总线能访问2^N个内存单元。
数据总线
8088cpu的数据总线宽度为8,8086cpu数据总线宽度为16.
控制总线
cpu对外部器件的控制是通过控制总线来进行的。
主板
每一台pc机都有一个主板,主板上有核心器件和一些主要器件,通过总线相连。
接口卡
计算机系统中所有可用程序控制其工作的设备,必须受到cpu的控制。cpu对外部设备不能直接控制,直接控制这些设备的是插在扩展插槽上的接口卡。cpu通过控制这些接口卡间接控制外部设备。
各类存储芯片
RAM(随机存储器)可读可写,但是必须带电存储,关机后内容丢失。
ROM(只读存储器),只能读不能写,关机后内容不消失。
- 随机存储器
- 用于存放供cpu使用的绝大部分程序和数据,主随机存储器一般由两个位置上的RAM组成,装在主板上的RAM和插在扩展插槽上的RAM
- 装有BIOS的ROM
- BIOS是由主板和各类接口卡厂商提供的软件系统,可以通过它利用硬件设备进行输入输出。
- 接口卡上的RAM
- 某些接口卡需要对大批量的输入输出数据进行暂时的存储,在其上装有RAM,如显卡,显卡随时将显存中的数据向显示器上输出。
内存地址空间
CPU在操控存储器的时候,把它们都当内存来对待,把它们总的看作一个由若干存储单元组成的逻辑存储器,这个逻辑存储器就是我们说的内存地址空间。
内存地址空间的大小收到地址总线(cpu寻址能力)限制。
寄存器
CPU是由运算器,控制器,寄存器等器件构成,这些器件靠内部总线连接在一起。在cpu中:
- 运算器进行信息处理
- 寄存器进行信息存储
- 控制器控制各种器件进行工作
- 内部总线连接各个部件,在它们之间进行数据传递
通用寄存器
8086cpu的寄存器都是16位的,AX,BX,CX,DX这四个寄存器用来存放一般性数据,被称为通用寄存器。
AX的高位为AH,低位为AL,分别8位。
在数据传送和运算的时候要注意两个操作对象位数一致。
mov ax,bl //错误
物理地址
所有内存单元构成的存储空间是一个一维的线性空间,每一个内存单元在这个空间中都有唯一的地址,我们称这个地址为物理地址。
(这里区分一下每个程序在被加载后会有一个独享的虚拟地址。)
16位结构
- 运算器一次最多可以处理16位数据
- 寄存器的最大宽度为16位
- 寄存器和运算器之间的通路为16位
8086cpu给出物理地址的方法
8086cpu有20条地址总线,但是内部一次处理传输的地址为16位。
所以会合成两个16位地址来访问物理地址
计算物理地址的算法为
物理地址=段地址X16+偏移量
段
段的划分来自cpu,cpu的位数(偏移地址)决定了一个段有多大。16位是64KB,一个段的起始地址一定是16的倍数(SAX16),且一个物理地址可能由不同的段地址+偏移地址得到。
段寄存器
CS,DS,SS,ES
CS和IP
CS为代码段寄存器,IP为指针寄存器。
8086cpu在任意时刻,cpu将CS:IP中的指令进行执行。
8086CPU执行过程
- 从CS:IP读取指令,指令进入指令缓冲器
- IP=IP+读取的长度
- 开始执行指令
修改CS,IP的指令
jmp 段地址:偏移地址
jmp 任意寄存器 = mov ip,寄存器中的值
寄存器(内存访问)
内存中字的存储
一个字是16位,也就是两个字节,intel处理器存储字是小端存储,即高八位存放高位字节,低八位存放低位字节。(大端与阅读时习惯相似,高8位存低位字节,低8位存高位字节)
ds和[address]
mov指令:
- 将数据直接送入寄存器
- 将一个寄存器的内容放到另一个寄存器
8086cpu不允许mov ds,1000H
CPU提供的栈机制
push ax操作:
1. sp=sp-2
1. 将ax内容送入栈中
如果push sp那么会存放sp-2之前的值
pop ax 操作:
1. 将内存单元ss:sp中数据放入ax中
1. sp=sp+2
如果pop sp同样是sp+2之前的值
8086cpu没有对栈上下界的检测,无法保证不越界。
大小写字母即ASCII码
大写字母+20H=小写字母
即大写字母第五位为0,小写字母第五位为1。
数据处理
机器指令处理的数据在什么地方
- 立即数
- 执行前在cpu的指令缓冲器中。
- 寄存器
- 在寄存器中,cpu内部
- 段地址
- 在段寄存器中,cpu内部
指令处理的数据有多长
word ptr指定处理一个字
byte ptr指定处理一个字节
dd伪指令
db 一个字节,dw一个字,dd双字
转移指令的原理
jmp指令
cpu在执行jmp指令的时候并不关心跳转的地址,而是只考虑偏移。并且读完jmp后,ip增加过一次,所以是在增加后的ip之后在增加偏移量。
jmp short 标号的功能:(IP)=(IP)+8位偏移
- 8位偏移=标号处地址-jmp指令后的第一个字节的地址
- short指明为8位偏移
- 8位偏移为-128~127,补码表示法
- 8位偏移编译时给出
jmp far 标号 EB 偏移地址 段地址
转移地址在内存中的jmp指令
- jmp word ptr 内存单元地址
- ip = []
- jmp dword ptr 内存单元地址
- cs=第二个字,ip=第一个字
jcxz指令
jmp if cx==zero
所有的条件转移指令都是短转移,ip修改范围为-128~127.
CALL和RET指令
ret和retf
ret指令使用栈中的数据,修改ip,实现近转移
CPU执行ret:
- (ip)=((ss)*16+(sp))
- (sp)=(sp)+2
CPU执行RETF:
- (ip)=((ss)*16+(sp))
- (sp)=(sp)+2
- (cs)=((ss)*16+(sp))
- (sp)=(sp)+2
call指令
- 将当前的ip或者ip和cs压入栈中
- 转移
根据位移进行的call指令
call 标号
- (sp)=(sp)-2
- ((ss)*16+(sp))=(IP)
- (IP)=(IP)+16位位移
16位位移=标号处地址-call指令后第一个字节地址
16位位移的范围为-32768-32767,补码表示
16位移在编译时给出
转移目的地址在指令中的call指令
call far ptr 标号
- push cs
- push ip
- jmp far ptr 标号
标志寄存器
flag寄存器
ZF标志
zf=1结果为0,zf=0结果不为0
PF标志
奇偶校验位,如果所有bit中1的个数位偶数,pf=1;如果为奇数,pf=0。
SF标志
如果结果为负,SF=1;如果结果不为负,SF=0。
CF标志
在进行无符号数运算的时候,它记录了运算结果的最高有效位向更高位的进位值。
OF标志
进行有符号数运算的时候。结果超过了机器能表示的范围称为溢出。
cmp指令
jmp 操作对象1,操作对象2
计算操作对象1-操作对象2,改变flag寄存器。
指令 | 含义 | 检测到相关标志位 |
---|---|---|
je | 等于则转移 | zf=1 |
jne | 不等于则转移 | zf=0 |
jb | 低于则转移 | cf=1 |
jnb | 不低于则转移 | cf=0 |
ja | 高于则转移 | cf=0且zf=0 |
jna | 不高于则转移 | cf=1或zf=1 |
中断
内中断
在操作系统中中断操作会从用户态变成系统态。这个后续会写操作系统的总结。
本质上,这个就是在执行完当前正在执行的指令后,检测从cpu外部发送过来或者内部产生的一种特殊信息,可以立即对所接收到的信息进行处理,外部信号(外中断可以屏蔽)。
内中断的产生
当cpu内部有以下事情发生的时候,产生马上需要处理的中断的信息,对于8086cpu有以下情况:
- 除法错误
- 单步执行
- 执行into指令
- 执行int指令
中断信息必须包含识别来源的编码,8086cpu用称为中断类型码的数据来表示中断信息。中断类型码为一个字节的数据,可以表示256种终端信息的来源。有如下几种:
- 除法错误:0
- 单步执行:1
- 执行into指令:4
- 执行int指令,该指令格式为int n,n为字符型立即数
中断处理程序
cpu收到中断信息后,需要对终端信息进行处理。而这个处理程序,是可以通过我们编写的,被称作中断处理程序。
cpu收到中断信息后,应该转去执行该中断信息的处理程序,cpu在接收到一个中断信息后,会将cs:ip指向中断处理程序的入口。
中断向量表
cpu用8为的中断类型码通过中断向量表找到相应的中断处理程序的入口地址。
中断向量表在内存中保存,其中存放着256给中断源所相应的中断处理程序的入口。对于8086cpu,中断向量表指定放在,内存地址0处,内存0000:0000带到0000:03ff的1024给单元中存放着中断向量表。其一个表项占2个字,高地址存放段地址,低地址字存放偏移地址。
中断过程
cpu收到中断信息后,要对中断信息进行处理,首先将引发中断过程,硬件在完成终端过程后,CS:IP将指向中断程序的入口,cpu开始执行中断处理程序。
cpu在执行完中断处理程序后,若返回原来的执行点继续执行下面的指令。在设置CS:IP之前还要将之前的cs和ip存储起来。
下面是8086cpu在收到中断信息后,所引发的终端过程。
- 取得中断类型码
- 标志寄存器入栈
- 设置标志寄存器第8位TF和第9位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
iret指令执行后,cpu回到执行中断处理程序前的执行点继续执行程序。
编程处理0号中断
cpu内部产生0号中断信息后,需要通过设置cs和ip到中断处理程序的地址,如果是操作系统管理的pc,我们可以向操作熊进行申请一块内存区域存储。若不通过操作系统,则需要找到一块别的程序不会用到的内存区,将do0传送到其中即可。
前面讲到,内存0000:03FF,大小位1KB的空间是系统存放中断处理程序入口地址的中断向量表。
一般情况下,从0000:0200至0000:02ff的256个字节的空间按所对应的中断向量表项都是空的,操作系统和其他应用程序都不占用。
故而可以将do0存放到0000:0200处
单步中断
在cpu执行完一条指令后,如果检测到标志寄存器Tf位为1,则产生单步中断,引发中断过程。单步中断的中断类型码为1,则它所引发的中断过程如下。
debug提供了单步中断的中断处理程序,当t命令执行指令时,debug使用t命令执行指令时,debug将tf设置为1,时cpu工作在单步中断的情况下。
响应中断的特殊情况
在响应中断的时候,标志寄存器入栈 TF=0,IF=1,在执行完ss指令后,应连续设置sp,所以在执行完设置ss的指令后cpu不会响应中断。
int指令
中断信息可以来自cpu的内部和外部。
int指令
int指令的格式为,int n,n为中断类型码,它的功能时引发中断过程。
cpu执行int n指令,相当于引发一个n号中断过程。执行过程:
- 取中断类型码
- 标志寄存器入栈,TF=0,IF=0
- CS,IP入栈
- (IP)=(n*4) (CS)=(n*4+2)
iret指令
功能为:
pop ip
pop cs
popf
BIOS和DOS所提供的中断例程
在系统板的ROM中存放着一套程序,称为BIOS,BIOS中主要包含以下几部分内容。
- 硬件系统的检测和初始化程序
- 外部中断和内部终端的例程
- 用于对硬件设备进行操作的中断例程
- 其他和硬件系统相关的中断例程
操作系统DOS也提供了中断例程,从操作系统角度来看,DOS的中断例程就是操作系统向程序员提供的编程资源。
BIOS和DOS提供的中断例程中包含了很多子程序,这些子程序实现了程序员在编程的时候经常需要用到的功能。和硬件设备相关的DOS中断例程,一般都调用了BIOS的中断例程。
BIOS和DOS中断例程的安装过程
- 开机后,CPU一加电,初始化(CS)=0ffffh,(IP)=0。ffff:0处有一条跳转指令,cpu执行该指令后,转取执行BIOS中的操作系统检测和初始化程序
- 初始化程序将建立BIOS所支持的中断向量,即将BIOS所提供的中断例程的入口地址放入中断向量表中,对于BIOS所提供的中断例程,由于其是固化在ROM中的程序,所以只需要将入口地址登记在中断向量表中即可。
- 硬件系统检测和初始化完成后,调用int 19h进行操作系统的引导,从此将计算机交由操作系统控制。
- DOS启动后,除完成其他工作外,还将他所提供的中断例程装入内存,并建立相应的中断向量。
BIOS中断例程应用
int 10h中断例程是BIOS提供的中断例程,其中包含了多个和屏幕输出相关的子程序。
一般来说,一个供程序员调用的中断例程中往往包括多个子程序,中断例程内部用传递进来的参数来决定执行哪一个子程序。BIOS和DOS提供的中断例程,都用ah来传递内部子程序的编号。
下面看一下int 10h中断例程的设置光标位置功能。
mov ah,2 ;置光标
mov bh,0 ;第0页
mov dh,5 ;dh中放行号
mov dl,12 ;dl中放列号
int 10h
(ah)表示调用第10h号中断例程中的2号子程序,功能为设置光标位置,可以提供光标所在的行号,列号和页号作为参数。
bh中页号的含义:内存地址空间中,b8000h~bffffh共32kb空间,为80*25彩色字符模式的显示缓冲区,一屏的内容在显示缓冲区中共占4000个字节,显示缓冲区分为8页,一页4kb,显示器可以显示任意一页的内容,一般情况下显示第0页的内容。也就是说通常情况下,显示b8000h~b8f9f中的4000个字节的内容将出现在显示器上。
DOS中断例程的应用
int 21h中断例程是DOS提供的中断例程,其中包含了DOS提供给程序员在编程时调用的子程序。
我们前面一直使用的是int 21h的4c号功能,即程序返回功能,如下:
mov ah,4ch ;程序返回
mov al,0 ;返回值
int 12h
(ah)=4ch表示调用第21h中断程序的4c号子程序,功能为程序返回,可以提供返回值作为参数。
端口
各种存储器都和cpu的地址线,数据线,控制线相连。cpu在操控它们的时候,把它们都当内存对待,把它们总督看作一个由若干存储单元组成的逻辑存储器,这个逻辑存储器就是我们所称的内存地址空间。
在pc机系统中,和cpu通过总线相连的芯片除各种存储器外,还有以下3种芯片。
- 各类接口卡(网卡,显卡)上的接口芯片,它们控制接口卡进行工作
- 主板上的接口芯片,cpu通过它们对部分外设进行访问
- 其他芯片,用来存储相关系统信息,或进行相关的输入输出处理。
在这些芯片种,都有一组可以由cpu读写的寄存器,这些寄存器,它们在物理上能处于不同的芯片种,但是它们在以下两点上相同。
- 都和cpu总线相连,这种链接是通过所在的芯片进行的。
- cpu对它们进行读写的时候通过控制线向他它们所在的芯片发出端口读写命令。
从cpu的角度,将这些寄存器当作端口,对它们进行统一编制,从而建立一个独立的端口地址空间,每一个端口在地址空间都由一个地址。cpu可以直接读写以下三个地方的数据。
- cpu内部的寄存器
- 内存单元
- 端口
端口读写
在pc机种,cpu最多可以定位64KB给不同的端口,则端口地址的范围是0~65535
访问端口:
in al,60h ;从60h号端口读取一个字节
执行时与总线相关的操作如下。
- cpu通过地址总线将地址60h发出
- cpu通过控制线发出端口都命令,选中端口所在的芯片,通知它
- 端口所在的芯片将60h端口中的数据通过数据线送给cpu。
在in和out命令中,只能用ax或al存放端口读入的数据或者发送到端口的数据,访问8位端口的时候用al,访问16位端口的时候用ax。
in al,20h
out 20h,al
对0~255以内的端口进行读写
mov dx,3f8h
in al,dx
out dx,al
对256~65535的端口进行读写,端口号在dx中
CMOS RAM芯片
pc机中有一个CMOS RAM芯片,此芯片特征如下。
- 包含一个实时钟和一个有128给存储单元的RAM存储器(早期的计算机为64个字节)
- 该芯片靠电池供电。所以关机后其内部的实时钟仍能正常工作
- 128个字节的RAM中,内部实时钟占0~0d单元来保存时间信息,其余大部分单元用于保存系统配置信息,供系统启用时BIOS程序读取。BIOS也提供了相关程序,使我们可以在开机的时候配置CMOS RAM中的系统信息。
- 该芯片内部有两个端口,端口地址为70h和71h,cpu通过这两个端口来读取CMOS RAM。
shl和slr指令
shl是逻辑左移指令,功能为:
- 将一个寄存器或内存单元的数据向左移位。
- 将最后移出的一位写入CF中
- 最低为用0补充
- 当移动位数大于1的时候,必须将移动位数放在cl中。
CMOS RAM中存储的时间信息
在CMOSRAM中,存放着当前的时间,年月日时分秒,这六个信息的长度都为一个字节,存放单元为
秒:0 分:2 时:4 日:7 月:8 年:9
这些数据以bcd码存放
外中断
一些信息来自于cpu外部,如,外设的输入到达,相关芯片向cpu发出相应的中断信息,cpu在执行完当前的指令后,可以进啊册到发送过来的中断信息,引发中断过程,处理外设的输入。
可屏蔽中断与不可屏蔽中断
可屏蔽中断时cpu可以不响应的外中断,cpu是否响应可屏蔽中断,要看标志寄存器的IF位的设置,如果IF=1,则cpu在执行完当前指令后响应中断,引发中断过程;如果IF=0,则不响应可屏蔽中断。
不可屏蔽中断是cpu必须响应的外中断,不可屏蔽中断的中断类型码固定为2,所以中断过程中,不需要取中断类型码。
pc机键盘的处理过程
1.键盘上的每一个键相当于一个开关,键盘中有一个芯片对键盘上的每一个键的开关状态进行扫描。
按下一个键的时候,该芯片产生一个扫描码,扫描码说明了按下的键在键盘上的位置。扫描码被送入主板上的相关接口的芯片的寄存器中,该寄存器的端口地址为60h。
松开按下的键,也产生一个扫描码,扫描码说明了松开的键在键盘上的位置,松开按键时产生的扫描码也被送入到60端口中。
一般按下一个键时产生的扫描码为通码,松开一个键时产生的扫描码为断码,扫描码长度为1给字节,通码第七位为0,断码第七位为1。
所以断码=通码+80h
2.相关的输入到达60h端口时,相关的芯片就会发出中断类型码为9的可屏蔽中断信息,如果IF=1,即响应中断,引发终端过程。
3.BIOS提供了int9中断例程,用来进行基本的键盘输入处理,主要的工作如下:
- 读出60h端口的扫描码
- 如果是字符键的扫描码,将该扫描码和它对应的字符码送入内存中的BIOS缓冲区;如果是控制键(如ctrl)和切换键(capslock)的扫描码,则将其转变为状态字节写入内存中存储状态字节的单元。
- BIOS键盘缓冲区时系统启动后,BIOS用于存放int 9中断例程所接受的键盘输入的内存区,该内存区可以接受15个键盘输入,因为int9中断例程除了接受扫描码外,还要产生和扫描码对应的字符码,所以在BIOS键盘缓冲区中,一个键盘输入用一个字单元存放,高位 字节存放扫描码,低位字节存放字符码。0040:17单元存储键盘状态字节。
- 0 右shift 置一表示按下
- 1 左shift
- 2 ctrl
- 3 alt
- 4 scollLock
- 5 NumLock
- 6 CapsLock
- 7 Insert
文章评论