文章目录
微机原理复习
第二、三章 处理器结构&数据处理
1.指令mov al,[3]中,源操作数的寻址方式是存储器寻址
。,带方括号都是存储器寻址
2.指令mov al,bl中,源操作数的寻址方式时寄存器寻址
,mov al,3中是立即数寻址
(一)中央处理单元CPU 运算器 、 寄存器 、和 控制器 三部分组成。
(二)在计算机中,通常运算器和 控制器 是核心部件,合称为中央处理单元CPU。
(三)某CPU的字长为4,假设该CPU执行一次加法运算需要1ns,执行两个double 类型的数(假设double类型的变量占8个字节)相加时需要 16 ns。
字长为4==一次4位累加用时1ns
1字节=8位
8字节=64位,64÷4==16
(四)如果某CPU处理器的频率为100Hz,则该CPU做一次运算需要的时间为0.01秒。
(五)CPU芯片可以与它外部的两类芯片进行交互信息,这两类芯片分别是 内存储器芯片 、 I/O接口芯片 ;这些芯片之间通过 总线 互相连接。
(六)一条指令的执行包括三个步骤: 取指 、译码、 执行 。其中“取指”指的是把指令从 主存储器 中取到 处理器 中。
(七)8086CPU内部的AX是一个 16 位寄存器,可以进一步将其分为高8位寄存器 AH 和低8位寄存器 AL 。
(八)十进制数65对应的8位二进制数是0100 0001B,十进制数19对应的8位二进制数是 0001 0011,十进制数49对应的二进制数是 0011 0001。
(九)8位二进制数0010 0011B对应的十进制数是35,8位二进制数0101 0001B对应的十进制数是 81 ,8位二进制数1000 0101B对应的十进制数是 133。
(十)十进制数274D对应的十六进制数为112H ;十六进制数3CH对应的十进制数为60D 。
第四章 分支与循环
标志位寄存器
-
进位标志位CF(carry flag):当加减运算结果的
最高有效位
有进位(加法)或借位(减法)时,进位标志置1,即CF=1;否则CF=0 -
溢出标志位OF(overflow flag): 有符号数加减结果有溢出,则OF=1;否则OF=0,计算:次高位的进位和最高位的进位做异或
-
零标志位 ZF(zero flag): 运算结果每一位都是0,ZF=1,否则ZF=0
-
符号标志位SF(sign flag):运算结果最高位为1,SF=1,否则SF=0
已有AX=0D884H,BX=4988H,若执行ADD AX,BX指令,则结果AX是多少?标志位CF、OF、SF、ZF、各为何值?
CF=1: AX和BX的最高位运算向更高位有进位,所以CF=1
OF=0:AX和BX的最高位运算的进位为1,次高位进位为1,OF= 1 ⊕ 1 = 0
SF=0:AX和BX运算结果的最高位为0,所以SF=0
ZF=0:运算的结果并不是每一位都是0,所以ZF=0
代码题:
1.检测al中的数,如果是正数,输出’Y’,否则输出’N’
(loop lable 相当于dec cx,jnz label,所以在用之前需要给计数器cx赋好初值)
mov ah,1 int 21h mov bl,al and bl,80h rol bl,1;循环左移一位,准备判断最高位 cmp bl,1; je L0 ;这三行也可以用js L0来替代 mov dl,'Y' mov ah,2 int 21h jmp over L0: mov dl,'N' mov ah,2 int 21h over:
2.检测al中的数,如果是偶数,输出’Y’,否则输出’N’
mov ah,1 int 21h and al,01h jz L0 mov dl,'N' mov ah,2 int 21h jmp over L0: mov dl,'Y' mov ah,2 int 21h over:
编写子程序,其功能是将AX中的数以无符号十进制形式输出显示,然后在主程序中进行调用。(如果有入口 参数或出口参数,请给出注释说明。)
mov ax,1234 call output ;子程序如下 output proc;入口参数ax,没有出口参数 push cx;不要忘记压栈出栈! push dx mov ch,0 ;这里做计数器 mov cl,10 ;除数 ;如果是将BX中的数输出的话,可以直接在下一行mov ax,bx,偷个懒 ;如果是将DX中的数输出的话,可以直接在下一行mov ax,dx 然后去掉dx的push 和 pop L0: cmp ax,10 ;如果ax比10小的话 jb L1 ;跳转到L1,就可以直接输出了 div cl ;用ax除以cl,ah存余数,al存结果 push ax ;目的是存好ah mov ah,0 ;方便最后判断ax剩下的是不是小于10 inc ch ;计数器++ jmp L0 ;直到ax剩下的数为10之内的,这时的al存的就是最高位的数字了 L1: mov dl,al ;输出最高位 add dl,48 mov ah,2 int 21h L2: cmp ch,0 ;如果ch不为空的话,这个数就不止一位 je over pop dx ;把栈顶元素弹出到dx,咱们只需要高八位的dh mov dl,dh ;然后输出 add dl,48 mov ah,2 int 21h dec ch ;每输出一位,就计数器-- jmp L2 ;只有计数器为0的时候才能结束循环 over: pop dx ;记得出栈,恢复这些寄存器本来的值 pop cx ret output endp
编写子程序,其功能是将CX中的数以无符号十进制形式输出显示(其实就是把刚刚的cx全部换成bx,高换高,低换低)
output proc;入口参数cx,没有出口参数 ;push cx push bx push dx ;mov ch,0 ;mov cl,10 mov bh,0 mov bl,10 mov ax,cx L0: cmp ax,10 jb L1 ;div cl div bl push ax mov ah,0 ;inc ch inc bh jmp L0 L1: mov dl,al add dl,48 mov ah,2 int 21h L2: ;cmp ch,0 cmp bh,0 je over pop dx mov dl,dh add dl,48 mov ah,2 int 21h ;dec ch dec bh jmp L2 over: pop dx ;pop cx pop bx ret output endp
编写子程序,其功能是从键盘输入数字字符(例如‘1’‘2’‘6’‘a’),在程序中得到对应的数值(126),然后在主程序中进行调用。(如果有入口参数或出口参数,请给出注释说明。)
call input ;子程序如下 input proc;无入口参数 ,出口参数为bx push ax push cx mov bx,0;初始值 mov cl,10;乘数 L0: mov ah,1 int 21h cmp al,'0' jb over cmp al,'9' ja over sub al,48 mov ah,0 xchg bx,ax mul cl;现在用al来乘cl,即原来bl中的值乘以cl,结果 存入ax add bx,ax;将ax(原来bx的值)加到bx上 jmp L0 over: pop cx pop ax ret input endp
在主程序中调用上面的子程序,输入4个整数,分别存放到ax,bx,cx,dx中,然后调用1中的子程序,将ax,bx,cx,dx中的值分别输出显示。
call input mov ax,bx call input mov cx,bx call input mov dx,bx call input call output mov ax,cx call output mov ax,dx call output mov ax,bx call output
编写程序,从键盘输入1个数字字符(例如‘6’),在程序中得到对应的数值的阶乘(6!),然后在利用1中的输出功能,将得到的数值输出显示
mov ah,1 int 21h sub al,48 mov cl,al sub cl,1 again: mul cl dec cl cmp cl,1 jne again call output
回车符的ascii码是13,换行符的ascii是10,请编写回车换行子程序enters。
myenter proc push dx push ax mov dl,13 mov ah,2 int 21h mov dl,10 mov ah,2 int 21h pop ax pop dx ret myenter endp
在数据区定义一个字型变量a1,a1中有10个元素,读取a1中的值并利用输出子程序将10个元素输出显示。
DATAS SEGMENT ;此处输入数据段代码 a1 dw 13,12,11,10,9,8,7,6,5,4 DATAS ENDS
mov cl,0 mov si,offset a1 aa: mov ax,[si] add si,2 ;字型变量一次加2,byte型的加1 call output inc cl cmp cl,10 jne aa
在数据段中定义一个变量a1,其中有5个元素(类似于数组),其元素类型为word类型(即每个元素占2个字节,5个元素占10个字节) ,调用5次输入子程序分别得到5个整数,依次将它们存放到a2的5个元素中。
DATAS SEGMENT ;此处输入数据段代码 a1 word 5 DUP (?) DATAS ENDS
mov cl,0 mov si,offset a1 aa: call input mov [si],bx add si,2 inc cl cmp cl,5 jne aa mov cl,0 mov si,offset a1 bb: mov ax,[si] add si,2 call output inc cl cmp cl,5 jne bb
编写子程序,把以‘$’结尾的字符串输出显示(有无入口参数?需要用循环实现)。
DATAS SEGMENT ;此处输入数据段代码 a1 byte 'you speak what?$' DATAS ENDS
mov si,offset a1 call myoutput myoutput proc;入口参数ax,没有出口参数 push ax push dx aa: mov dl,[si] cmp dl,'$' je over inc si mov ah,2 int 21h jmp aa over: pop dx pop ax ret myoutput endp
编写输出子程序,把AX中的数以二进制形式显示输出,并在主程序中验证。(需要使用循环移位指令,逻辑与指令。)
binary_output proc;入口参数ax,在call此子程序前先给ax赋值 push cx push bx push dx mov cl,0 mov bx,ax again: rol bx,1 mov dx,bx and dx,1;按位与,只保留最低位 add dx,48 mov ah,2 int 21h inc cl cmp cl,16 jb again pop dx pop bx pop cx ret binary_output endp
编写输出子程序,把AX中的数以十六进制形式显示输出,
sixteen_output proc;入口参数ax,在call此子程序前先给ax赋值 mov cl,4 mov ch,0 mov bx,ax again: rol bx,cl inc ch mov dl,bl and dl,0FH;按位与 cmp dl,9 ja L1 add dl,48 jmp over L1: add dl,55 over: mov ah,2 int 21h cmp ch,4 jb again ret sixteen_output endp
编写输出子程序,把AX中的数以两个字符的形式(把AX两个字节中的二进制序列看成字符)显示输出,
char_out proc;入口参数ax,无出口参数 push bx push dx mov bx,ax mov dl,ah mov ah,2 int 21h mov dl,bl mov ah,2 int 21h pop dx pop bx ret char_out endp
编写输出子程序,把AX中的数以带符号十进制形式(把AX中的二进制序列看成带符号数,ax=123,显示123,ax=-123,显示-123,参考neg指令)显示输出,
mov ax,-159 mov bx,ax and ax,8000H ;cmp ax,0;这里也可以用cmp ax,0 来判断按位与之后的结果是否全0,jz效果和这个是一样的 jz print mov dl,'-' mov ah,2 int 21h neg bx print: mov ax,bx call output
综合使用之前的子函数,完成如下操作:
(1)用提示信息提示用户输入8个数,每个数输入后换行,在下一行输入下一个数;
(2)8个数输入完成后在新的一行显示这8个数;Please input 8 number:
23a
46c
。。。
the 8 nunber you input is: 23,46,…DATAS SEGMENT input_b byte 'Please input 8 numbers:$' a1 dw 8 dup(?) output_b byte 'the 8 words you input is:$' DATAS ENDS
mov si,offset input_b call myoutput call myenter mov cl,0 mov si,offset a1 again: call input mov [si],bx add si,2 inc cl cmp cl,8 jne again mov si,offset output_b call myoutput mov cl,0 mov si,offset a1 outagain: call myenter mov ax,[si] call output add si,2 inc cl cmp cl,8 jne outagain MOV AH,4CH INT 21H
第五章 总线
总线操作
占用总线进行数据传输有四个阶段(课本p152)
1.总线请求和仲裁 2.寻址 3.数据传送 4.结束
处理器有哪四种最基本的总线操作(周期)?
答:存储器读,存储器写,IO接口读,IO接口写
总线时序
指令周期
:一条指令在处理其中从取指、译码到最终执行完成的过程(p155)
1.某微机具有256M字节的内存空间,其CPU的地址总线应有(28)条。256M= 2 28 2^{28} 228
4.已知SP=2028H,执行POP AX后,SP寄存器的值是202AH。pop加2
5.已知SP=2020H,执行PUSH AX后,SP寄存器的值是201EH。push减2,注意是十六进制,不是十进制
6.8086 CPU用( ALE )信号下降沿在T1结束时将地址信息锁存在地址锁存器中。
7.JMP指令或带条件转移指令构成的段内转移中,转移的本质是改变(IP)寄存器的值。
8.标志寄存器中控制串传送方向的标志位是(DF)。
9.总线信号分成三组,分别是数据总线、地址总线和控制总线。
10.8086 CPU预取指令时,在其引脚上将产生存储器读总线操作;当其执行指令MOV [SI], DX 时,在其引脚上将产生存储器写总线操作。(由寄存器写入存储器)
11.占用总线进行数据传输,一般需要经过总线请求和仲裁、寻址 、数据传送和结束4个阶段。
12.堆栈操作时,8086 CPU会自动选择 SS 值作为段基值,再加上由SP提供的偏移量形成物理地址。(堆栈段寻址为SS+SP)
13.8086 CPU无等待的总线周期由__4__个T状态组成。
14.如果某处理器的时钟频率为200MHz,则每个时钟周期T的持续时间为 1 200 M \frac{1}{200M} 200M1。
15.逻辑地址0A100H :280EH对应的物理地址是0A380EH。
16.一条指令的执行包括三个步骤:取指、译码、执行。
1.某CPU数据线16根,地址线20根,其16-13号引脚分别对应多路复用的AD3-AD0,当前CS=36A8H,IP=007AH,DS=31A4H。假设IP当前所指向的指令为mov DS:[5],AX,当前AX中的值为5A7BH;假设该CPU所连接的总线中的数据总线的宽度是16。回答下列问题:
1、在取指对应的总线周期的T1中,16-13号引脚(即A3-A0)的值分别是多少?
2、在取指对应的总线周期中,M/ IO ‾ \overline{\text{IO}} IO引脚=? RD ‾ \overline{\text{RD}} RD引脚=? WR ‾ \overline{\text{WR}} WR引脚=?
3、在执行指令对应的总线周期的T1中,16-13号引脚(即A3-A0)的值分别是多少?
4、在执行指令对应的总线周期的T2-T4中,16-13号引脚(即D3-D0)的值分别是多少?
[解]1.A3~A0 = 1010。 取指令对应指令段地址为CS+IP,36A80+0074=36AFAH 由于16-13号引脚正好对应最低四位A3-A0 地址最后一个数为A 改为二进制:1010 2.M/ IO ‾ \overline{\text{IO}} IO 为存储器或I/O操作信号 其中I/O信号低电平有效
取指操作是由内存读入CPU中 故M高电平有效,M/IO*=1
RD ‾ \overline{\text{RD}} RD为读信号 且低电平有效 故 RD ‾ \overline{\text{RD}} RD=0
WR ‾ \overline{\text{WR}} WR*为写信号 且低电平有效 故 WR ‾ \overline{\text{WR}} WR=1
3.执行指令对应数据段地址为DS+数据偏移量[5] ,31A40+5=31A45H ,16-13号引脚对应最低位5 改为二进制:0101 即为A3-A0对应的值
4. 传送数据时,直接传数据值5A7BH,16-13号引脚传送最低位B,改为二进制为:1011,对应D3-D0值
2.某CPU地址线20根,数据线8根,其16-13号引脚分别对应多路复用的AD3-AD0,当前CS=12ACH,IP=007DH,DS=31A0H。
假设IP当前所指向的指令为mov DS:[5],AX ,AX中的值为5A7BH;
假设CPU所连接的总线的频率是100HZ,它内部的数据总线的宽度是8,利用该总线传送16位数据时,先传送低8位,再传送高8位。
回答下列问题:
1、该CPU执行IP所指向的这条指令的过程中,取指+执行总共需要几次访问内存?
取指访问1次内存+执行2次=3次
数据总线的宽度是8,利用该总线传送16位数据时,先传送低8位,再传送高8位
2、在取指对应的总线周期的T1中,16-13号引脚(即A3-A0)的值分别是多少?
CS寄存器左移4位补0+IP寄存器后 取最低四位:D = 1 1 0 1
3、在取指对应的总线周期中,M/IO* 引脚=?RD* 引脚=? WR* 引脚=?
存储器读总线操作
M/IO* 引脚= 1 RD* 引脚 = 0 WR* 引脚 = 1
4、在执行指令对应的第一个总线周期的T1中,16-13号引脚(即A3-A0)的值分别是多少?
DS: 31A0H,左移4位补0+偏移量5 = 31A05H
20位地址的最低4位 算出来是5->0 1 0 1
5、在执行指令对应的第一个总线周期的T2-T4中,16-13号引脚(即D3-D0)的值分别是多少?
第一次传AX低8位,7B中的低四位 1 0 1 1
6、在执行指令对应的第二个总线周期的T2-T4中,16-13号引脚(即D3-D0)的值分别是多少?
第二次传AX高8位,5A中的低四位 1 0 1 0
7、在执行指令对应的总线周期中,M/IO* 引脚=?RD* 引脚=? WR* 引脚=?
存储器写总线操作
M/IO* 引脚= 1
RD* 引脚 = 1
WR* 引脚 = 0
8、这条指令的指令周期是多少秒?
CPU所连接的总线的频率是100HZ
T0 = 1/f = 1/100 = 0.01s
用3次总线 ,访问内存就是读/写,用总线传递要往内存写的信息或者读取的信息
T = 3*T0 = 0.03s
第六章 存储系统
局部性原理
存储访问的局部性原理有两方面的含义:
- 空间局部性:紧邻被访问单元的地方也将被访问
- 时间局部性:刚刚被访问的单元很快将被访问
物理地址和逻辑地址的转换
CS+IP 段基址加偏移量
代码段寄存器(Code Segment)+IP 指令指针寄存器(Instruction Pointer)
逻辑地址:由CS + IP一起表示。
物理地址:用CS左移四位,然后和IP相加。(左移四个二进制位!)
CS存储内存中代码段的起始地址,IP存要取的下条指令距离代码段起始地址的偏移量,CS+IP决定CPU要取的下条指令在内存中的地址号。
8086CPU的外部引脚中的地址引脚决定该CPU能访问的外部内存的范围。
若微机具有16M的内存空间,则CPU的地址总线应有24条. 2 24 = 16 M 2^{24}=16M 224=16M
将下列逻辑地址转换为物理地址
- 2200H:3000H 2.90H:16H 3.0A000H:3800H
- CS左移四位->22000H,IP->3000H,物理地址为25000H
- CS左移四位->00900H,IP->0016H,物理地址为916H
- CS左移四位->0A0000H,IP->3800H,物理地址为0A3800H
(一)假设当前CS=36A8H,IP=007AH,DS=31A4H。假设IP当前所指向的指令为mov AX,[5],请回答:
1、CPU取的下条指令的物理地址是多少?
2、 取到该指令后,执行该指令时,需要从哪个内存单元开始取两个字节送到AX寄存器中?
1.CS+IP->36A80H+007AH = 36AFAH
2.DS+si->31A40H+5 = 31A45H
简答题
什么是存储器芯片的全译码和部分译码?各有什么特点?
[答]: 全译码:使用全部系统地址总线进行译码。特点是地址唯一,组成的存储系统地址空间连续。
部分译码:只使用部分系统地址总线进行译码。其特点:译码简单,地址重复。
请给出图6-12所给出的74LS138译码器的所有译码输出引脚对应的地址范围
观察这个74138的输入接口, A 17 A_{17} A17和 A 18 A_{18} A18取反之后需要是低电平,CBA一共有 2 3 2^{3} 23中方式
所以 A 19 A_{19} A19=1, A 18 A_{18} A18=1, A 17 A_{17} A17=1
CBA=000时,
A
19
A_{19}
A19~
A
0
A_{0}
A0的范围应该是1110 0000 0000 0000 0000 ~ 1110 00
11 1111 1111 1111B,即0E0000H~0E3FFFH
CBA=001时,
A
19
A_{19}
A19~
A
0
A_{0}
A0的范围应该是1110 0100 0000 0000 0000 ~ 1110 01
11 1111 1111 1111B,即0E4000H~0E7FFFH
CBA=010时,
A
19
A_{19}
A19~
A
0
A_{0}
A0的范围应该是1110 1000 0000 0000 0000 ~ 1110 10
11 1111 1111 1111B,即0E8000H~0EBFFFH
CBA=011时,
A
19
A_{19}
A19~
A
0
A_{0}
A0的范围应该是1110 1100 0000 0000 0000 ~ 1110 11
11 1111 1111 1111B,即0EC000H~0EFFFFH
CBA=100时,
A
19
A_{19}
A19~
A
0
A_{0}
A0的范围应该是1111 0000 0000 0000 0000 ~ 1111 00
11 1111 1111 1111B,即0F0000H~0F3FFFH
CBA=101时,
A
19
A_{19}
A19~
A
0
A_{0}
A0的范围应该是1111 0100 0000 0000 0000 ~ 1111 01
11 1111 1111 1111B,即0F4000H~0F7FFFH
CBA=110时,
A
19
A_{19}
A19~
A
0
A_{0}
A0的范围应该是1111 1000 0000 0000 0000 ~ 1111 10
11 1111 1111 1111B,即0F8000H~0FBFFFH
CBA=111时,
A
19
A_{19}
A19~
A
0
A_{0}
A0的范围应该是1111 1100 0000 0000 0000 ~ 1111 11
11 1111 1111 1111B,即0FC000H~0FFFFFH
现有一种存储芯片容量为512×8b,若要用它组成4KB的存储容量,需要多少片这样的存储芯片?每块芯片需要多少根寻址线?而4KB存储系统最少需要多少根寻址线,其中几根用作片选,几根用作片内寻址? (要列出计算公式)
4 × 1024 × 8 b 512 × 8 b \frac{4×1024×8b}{512×8b} 512×8b4×1024×8b=8片
512= 2 9 2^{9} 29,每块芯片需要9根寻址线
4K=4*1024= 2 12 2^{12} 212,最少需要12根寻址线,所以9根用作片内寻址,3根用作片选
设计一个存储器接口电路,其中部分电路给出如下图所示,要求该存储系统的地址范围为0DC000H~0DCFFFH,可增加的器件可以是基本门电路(与门、或门、非门、与非门、或非门),完成74LS138同CS的连接,画出虚线框中门电路。
DC000H~DCFFFH->1101 1100 0000 0000 0000B~1101 1100 1111 1111 1111B
所以 A 14 A_{14} A14 A 13 A_{13} A13 A 12 A_{12} A12=100, A 19 A_{19} A19 A 18 A_{18} A18 A 17 A_{17} A17 A 16 A_{16} A16=1101, A 15 A_{15} A15=1
所以CBA=001->38译码器的 Y 1 Y_{1} Y1有效,连接 CS ‾ \overline{\text{CS}} CS片选端
A 19 A_{19} A19 A 18 A_{18} A18 A 17 A_{17} A17 A 16 A_{16} A16=1101 -> A 17 A_{17} A17应该取反,加一个非门,其他的高电平, 最后四个输出为1再连接一个总的非门,因为E1低电平有效
(1)2KB=2x1024x8b 故(2x1024x8)/(1024x8)=2片
(2)1024=2^10 故需要10根地址线
(3)2K=2^11 故需要11根地址线 其中1个片选 10个片内寻址
(1)(2x1024x8)/(1024x4)=2×2=4片 (两组,每一组两片)
(2)1024=2^10 故需要10根地址线
(3)2K=2^11 故需要11根地址线寻址 其中1根做片选(每2片并一块看成1组),10根片内寻址
红箭头指示的地方 代表CS片选Y0低电平有效即A18 A17对应 0 0
A19 A18 A17 A16 A15~A0
0 0 0 0 0000 0000 0000 0000 最小范围
0 0 0 1 1111 1111 1111 1111 最大范围
故红箭头所指范围为:00000H——1FFFFH
绿箭头一样的道理,CS接Y3低电平,A18,A17应该是11
A19 A18 A17 A16 A15~A0
0 1 1 0 0000 0000 0000 0000 最小范围
0 1 1 1 1111 1111 1111 1111 最大范围
绿箭头指向的芯片范围是60000H~7FFFFH
观察图可知:2114芯片应该是一个1K×4的芯片(十根地址线,4根数据线)
Y0连接的这两个芯片组合在一起成了1K×8的芯片
由24译码器的Y0得A11A10为00,
A11 A10 A9 A8 A7 A6 A5 A4 A3 A2 A1 A0
0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 1 1 1 1 1 1 1 1 1
范围为000H~3FFH
第七章 I/O接口
内部结构:
数据寄存器
:保存处理器与外设之间交换的数据
状态寄存器:
保存接口电路和外设当前的工作状态信息
控制寄存器
:保存处理器控制接口电路和外设操作的有关信息
基本功能
数据缓冲
:匹配快速的处理器与相对慢速的外设的数据交换
信号变换
:把信号相互转换为适合对方的形式
编址方式
I/O端口与存储器地址独立编址
:优点:1.I/O端口的地址空间独立,2.控制和地址译码电路相对简单,3.专门的I/O指令使程序清晰易读;缺点:I/O指令没有存储器指令丰富
I/O端口与存储器地址统一编址
:优点:1.不需要专门的I/O指令 2.I/O数据存取灵活;缺点:1.占去部分存储器空间,2.程序不易阅读
8259A的三个寄存器及其功能
中断请求寄存器IRR:保存8条外界中断请求信号IR0~IR7的请求状态,Di位为1表示IRi引脚有中断请求
中断服务寄存器ISR:保存正在被8259A服务的中断状态,Di位为1表示IRi中断正在服务中
中断屏蔽寄存器IMR:保存对中断请求信号IR的屏蔽状态,Di位为1表示IRi中断被屏蔽(禁止)
答案:(一)存储器读 I/O接口写
(二)dx (因为dx存放有端口号可以送到地址总线上)
(三)al (al寄存器中存放有数据,故将al的内容送到数据总线上)
(四)I/O接口芯片
(五)数据缓冲 信号变换
(六)独立编址 统一编址
(七)2^20=1M (8086CPU含有20根地址线)
(八)2^16=64K(8086CPU采用独立编址方式,只使用最低16个地址信号)
-
指令IN是将数据从
I/O端口
传输到处理器
,执行该指令处理器引脚产生I/O读
总线周期。 -
指令“IN AL, 21H”的目的操作数是
寄存器
寻址方式,源操作数是直接寻址
方式。 (目的操作数在左,源操作数在右) -
指令“OUT DX, EAX”的目的操作数是
间接
寻址方式,源操作数是寄存器
寻址方式。
注意:I/O接口只有两种寻址方式:直接寻址和DX间接寻址(p219)
-
在IA-32处理器中0号中断被称为
除法错异常中断
,外部不可屏蔽中断是2
号中断。 -
IA-32处理器在开中断状态,其标志IF=1。指令STI就是开中断指令,而关中断指令就是CLI,关中断时IF=0。
-
实地址方式下,主存最低
1KB
的存储空间用于中断向量表。向量号8的中断向量保存在物理地址20H
开始的4个
连续字节空间;如果其内容从低地址开始依次就是00H、23H、10H、F0H,则其中断服务程序的首地址就是F010H∶2300H
。
编程题
7.7 参看图7-7,编程实现以下功能:当 K 0 K_{0} K0开关单独按下时,发光二极管 L 0 L_{0} L0~ L 7 L_{7} L7依次点亮,每个维持200ms;当开关 K 1 K_{1} K1单独按下时,发光二极管 L 0 L_{0} L0~ L 7 L_{7} L7反向依次点亮,每个也维持200ms;在其他情况下,各发光二极管均不点亮。假定有200ms的子程序DELAY可以直接调用。
这是delay函数,不用写,直接用
delay proc ;总共大约耗费2秒
push bx
push cx
mov bx,100h
L1: mov cx,0ffffh
L2:
loop L2;这是内层循环,空转FFFFH次
dec bx
jnz L1;这是外层循环,循环1000次;
pop cx
pop bx
ret
delay endp
代码如下:
mov cl,0
mov dx,8000h
in al,dx
mov bl,al
cmp bl,0feh
je L1
cmp al,ofdh
je L3
mov al,ffh
out dx,al
jmp over
L1: mov al,01h
L2: out dx,al
call delay
shl al,1
inc cl
cmp cl,8
jb L2
jmp over
L3: mov al,80h
L4: out dx,al
call delay
shr al,1
inc cl
cmp cl,8
jb L4
jmp over
over:
7.8 现有一个输入设备,其数据端口的地址为FFE0H,状态端口地址为FFE2H。当状态标志 D 0 D_{0} D0=1时,表明一个字节的输入数据就绪。请编写利用查询方式进行数据传送的程序段,要求从该设备读取100个字节保存到BUFFER缓冲区。
代码如下:
mov bx,offset buffer
mov cx,100
L1: mov dx,0ffe2h
L2: in al,dx
test al,01h
jz L2
mov dx,0ffe0h
in al,dx
mov [bx],al
inc bx
loop L1
7.9 现有一个字符输出设备,其数据端口和状态端口的地址均为80H。在读取状态时,标志位 D 7 D_{7} D7=0表明该设备闲,可以接收一个字符。请编写利用查询方式进行数据传送的程序片段,要求将存放于缓冲区ADDR处的一串字符(以0为结束标志)输出给该设备。
代码如下:
mov si,offset ADDR
status:
in al,80h
test al,80h
jnz status
mov al,[si]
cmp al,0
je over
inc si
out 80h,al
jmp status
over:
代码如下:
mov si,offset BUF1
mov cx,1000 ;置计数初值
L1: mov dx,621h ;置状态端口
in al,dx ;读状态口
test al,04h ;检测状态口是否ready? (04h即0000 0100B,如果状态口的D2位高电平就会得到1,否则就jz L1)
jz L1 ;不ready,跳转到L1,接着等待判断
mov dx,620h ;置数据口
in al,dx ;读数据口
cmp al,'a' ;对数据口al的数据作比较
jb L2 ;如果不属于'a'~'z'之间
cmp al,'z' ;就送去L2的[si]
ja L2 ;
sub al,32 ;是小写字母,就减32转换成大写字母(a的ascii码为97,A为65)
L2: mov [si],al ;送数据到si
inc si ;si指针后移
loop L1 ;
一个条件传送的输出接口由两个端口组成,其数据端口、状态端口的地址分别为310H和311H,用状态端口311H的D3位为高电平表示输出设备就绪,利用上述接口电路把数据区中的字节型变量BUF1中的1000个字节输出,要求如果当前字符是小写字母,需要把其转换为大写字母输出,其它字符原样输出。编写程序段实现上述功能(A的ACSII码是65,a的ASCII码是97)。
代码如下:
MOV SI,OFFSET BUFFER1
MOV CX,0
L0: MOV DX,311H ;置状态口
AGAIN: ;循环检测状态口
IN AL,DX ;读状态口
AND AL,0000 1000B ;检测状态口是否READY
JZ AGAIN
MOV AL,[SI] ;READY后取下一个数
CMP AL,'a'
JB L1
CMP AL,'z'
JA L1
SUB AL,32 ;是a~z之间的减32
L1: MOV DX,310H;不是a~z之间到L1输出到数据口
OUT DX,AL
ADD SI,1 ;指针后移
ADD CX,1 ;计数器+1
CMP CX,1000
JE OVER
JMP L0
OVER:
第一种思路:循环过程中每次亮完一个灯,就去判断
K
7
K_{7}
K7是否断开,如果断开灯就全灭,否则接着亮下一个灯。
mov dx,8000h
mov bl,0
mov cl,1
again:
in al,dx
and al,80h
jz next
mov al,bl
out dx,al
mov cl,1
jmp again
next:
mov al,cl
out dx,al
call delay
rol cl,1
jmp again
第二种思路:只要 K 7 K_{7} K7按下就让他循环亮8个灯,亮完之后再去判断开关是否断开,如果断开则灯全灭,否则再全部亮一遍
mov dx,8000h
mov bl,00h
mov cl,01h
again:
in al,dx
and al,80h
jz next
mov al,bl
out dx,al;灯全灭
jmp again
next:
mov cx,8
mov al,cl
next1:
out dx,al
call delay
rol al,1
loop next1
jmp again
第八章 8253 8255
8253
8253的工作方式:
方式2(频率发生器):clk的一个小t和out的低电平的小t相同
方式3(方波发生器):
- 计数初值为偶数的话out产生的高电平和低电平时间一样
- 计数初值为奇数的话out产生高电平比低电平多一个小t
8253控制字
8253例题
-
某个8253芯片中的
0号计数器
的端口号是300H
, c l k 0 clk_{0} clk0的频率是1000赫兹, o u t 0 out_{0} out0连接一个发光二极管, g a t e 0 gate_{0} gate0接+5V。现要求OUT0所连接的发光二极管实现循环“点亮0.5秒、熄灭0.5秒
”功能。请给出计数器0的计数初值(要有计算公式),并写出实现上述功能的汇编程序(设定8253芯片的中0号计数器工作方式和计数初值)。[解]:
f c l k 0 f_{clk_{0}} fclk0=1000Hz
f o u t 0 f_{out_{0}} fout0= 1 0.5 + 0.5 1\over0.5+0.5 0.5+0.51Hz=1Hz
计数器初值为 f c l k 0 f o u t 0 f_{clk_{0}}\over f_{out_{0}} fout0fclk0= 1000 1 1000\over1 11000=1000
汇编代码:
mov dx,303h mov al,00110110B;0号计数器(00),先低后高(11),3号工作方式(011),二进制(0) out dx,al mov dx,300h mov ax,1000 out dx,al mov al,ah out dx,al
-
某个8253芯片中的
0号计数器
的端口号是400H
, c l k 0 clk_{0} clk0的频率是1000赫兹, o u t 0 out_{0} out0连接接一个发光二极管, g a t e 0 gate_{0} gate0接+5V。现要求OUT0所连接的发光二极管实现循环“点亮1秒、熄灭1秒”
功能。请给出计数器0的计数初值(要有计算公式),并写出实现上述功能的汇编程序(设定8253芯片的中0号计数器工作方式和计数初值)。[解]:
f c l k 0 f_{clk_{0}} fclk0=1000Hz
f o u t 0 f_{out_{0}} fout0= 1 1 + 1 1\over1+1 1+11Hz=0.5Hz
计数器初值为 f c l k 0 f o u t 0 f_{clk_{0}}\over f_{out_{0}} fout0fclk0= 1000 0.5 1000\over0.5 0.51000=2000
汇编代码:
mov dx,403h mov al,00110110B;0号计数器(00),先低后高(11),3号工作方式(011),二进制(0) out dx,al mov dx,400h mov al,2000 out dx,al mov al,ah out dx,al
-
某个8253芯片中的
0号计数器
的端口号是500H
,CLK0
的频率是10赫兹
,OUT0连接接一个发光二极管,GATE0接+5V。现要求OUT0所连接的发光二极管实现循环“点亮0.4秒、熄灭0.1秒”
功能。请给出计数器0的计数初值(要有计算公式),并写出实现上述功能的汇编程序(设定8253芯片的中0号计数器工作方式和计数初值)。[解]: t c l k 0 t_{clk_{0}} tclk0= 1 10 1\over10 101=0.1s == t 熄灭 = 0.1 t_{熄灭}=0.1 t熄灭=0.1s,而且点亮0.4s熄灭0.1s所以是方式2
f c l k 0 f_{clk_{0}} fclk0=10Hz
f o u t 0 f_{out_{0}} fout0= 1 0.4 + 0.1 1\over0.4+0.1 0.4+0.11Hz=2Hz
计数初值为: f c l k 0 f o u t 0 f_{clk_{0}}\over f_{out_{0}} fout0fclk0= 10 2 10\over2 210=5
汇编代码:
mov dx,503h mov al,00010100B;0号计数器(00),只低(01),2号工作方式(010),二进制(0) out dx,al mov dx,500h mov al,5 out dx,al
-
某个8253芯片中的
0号计数器的端口号是800H
,CLK0的频率是1000赫兹
,OUT0送到CLK1
,OUT1连接接一个发光二极管
,GATE0和GATE1接+5V。现要求OUT1所连接的发光二极管实现循环“点亮4秒、熄灭1秒”
功能。请给出计数器0和计数器1的计数初值(要有计算公式),并写出实现上述功能的汇编程序(设定8253芯片的中0号计数器和1号计数器的工作方式及计数初值)。[解]:
亮4s灭1s,所以是方式2,所以 t c l k 1 t_{clk_{1}} tclk1== t 熄灭 = 1 s t_{熄灭}=1s t熄灭=1s
f c l k 0 f_{clk_{0}} fclk0=1000Hz f c l k 1 f_{clk_{1}} fclk1== f o u t 0 f_{out_{0}} fout0=1Hz f o u t 1 f_{out_{1}} fout1= 1 4 + 1 1\over4+1 4+11=0.2Hz
计数器0的计数初值为: f c l k 0 f o u t 0 f_{clk_{0}}\over f_{out_{0}} fout0fclk0= 1000 1 1000\over1 11000=1000
计数器1的计数初值为: f c l k 1 f o u t 1 f_{clk_{1}}\over f_{out_{1}} fout1fclk1= 1 0.2 1\over0.2 0.21=5
汇编代码:
mov dx,803h mov al,00110100B;计数器1 out dx,al mov dx,800h mov ax,1000 out dx,al mov al,ah out dx,al mov dx,803h mov al,01010100B;计数器2 out dx,al mov al,5 mov dx,801h out dx,al
8255
8255控制字
8255例习题
简答
1.针对8255芯片工作方式1输出时序,说明数据输出的过程
[答]:
- 中断方式下,处理器响应中断,执行输出OUT指令:输出数据给8255,发出 WR ‾ \overline{\text{WR}} WR 信号.查询方式下,通过端口C的状态确信可以输出数据,处理器执行输出指令。
- WR ‾ \overline{\text{WR}} WR信号一方面清除INTR,另一方面在上升沿使 OBF ‾ \overline{\text{OBF}} OBF有效,通知外设接收数据。实质上 OBF ‾ \overline{\text{OBF}} OBF是外设的选通信号。
- WR ‾ \overline{\text{WR}} WR信号结束后,数据从端口数据线上输出。当外设接收数据后,发出 ACK ‾ \overline{\text{ACK}} ACK响应。
- ACK ‾ \overline{\text{ACK}} ACK信号使 OBF ‾ \overline{\text{OBF}} OBF无效,上升沿又使INTR有效(允许中断的情况),发出新的响应请求。
2.针对8255芯片工作方式1输入时序,说明数据输入的过程
[答]:
- 当外设已经将数据准备好送至8255的端口数据线时,外设将选通信号 STB ‾ \overline{\text{STB}} STB置低有效通知8255.
- 8255利用 STB ‾ \overline{\text{STB}} STB信号把端口数据锁存至输入锁存器,然后置IBF为高有效,告诉外设已将数据读入,并阻止新的数据读入。
- 选通 STB ‾ \overline{\text{STB}} STB信号无效后,如果允许中断,INTR信号就有效,向处理器提出中断请求。
- 处理器响应中断,执行输入IN指令,发出 RD ‾ \overline{\text{RD}} RD读信号,把数据读入处理器。当然,处理器也可以通过读取端口C的有关状态信息,以程序查询方式读入数据。
- 在 RD ‾ \overline{\text{RD}} RD信号有效后经一段时间清除中断请求。
- 当 RD ‾ \overline{\text{RD}} RD信号结束后,数据已读至处理器,IBF变低。IBF变为无效,表示输入锁存器已空,通知外设可以输入新的数据了。
编程题
1.点亮数码管,输入1,2,3……,数码管显示对应数字。led为共阴极,需要高电平亮
8255工作方式0,端口A为输出口,端口号为500h~503h
-
data区
DATAS SEGMENT a1 db 3fh,06h,5Bh,…… DATAS ENDS
-
代码区
mov dx,503h mov al,10000000B;没有用到BC口,直接置为0省事 out dx,al again: mov si,offset a1 mov ah,1 int 21h cmp al,'0' jb again cmp al,'9' ja again sub al,48 mov ah,0 add si,ax;ah高位置零,8位+8位 mov dx,500h mov al,[si] out dx,al jmp again;实现死循环
2.循环点亮数码管,延迟两秒切换数字,led共阴极,需要高电平亮
端口500h~503h,工作方式0,端口A用作输出口
-
data区
DATAS SEGMENT a1 db 3fh,06h,5Bh,…… DATAS ENDS
-
代码区
mov dx,503h mov al,10000000B out dx,al mov dx,500h re: mov cl,10 ;计数器 mov si,offset a1 again: mov al,[si] out dx,al inc si dec cl call delay cmp cl,0 je re ;如果十个数字都亮过了,从头开始循环亮 jmp again