一、简单程序设计简单程序设计是没有分支,没有循环的直线运行程序,程序执行按照IP内容自动增加的顺序进行。
例1 利用查表法计算平方值。
已知0 ~ 9的平方值连续存在以SQTAB开始的存储区域中,求SUR单元内容X的平方值,并放在DIS单元中。
假定0≤X≤9且为整数。
分析:建立平方表,通过查表完成。
STACK SEGMENTDB 100 DUP(?)STACK ENDSDATA SEGMENTSUR DB ?DIS DB ?SQTAB DB 0,1,4,9,16,25,36,49,64,81 ; 0~9的平方表DATA ENDSCODE SEGMENTASSUME CS:CODE,DS:DATA,SS:STACK,ES:DATA BEGIN:PUSH DSMOV AX,0PUSH AX ;保证返回DOS,MOV AX,DATAMOV DS,AX ;为DS送初值LEA BX,SQTAB ;以下程序部分完成查表求平方值MOV AH,0 ;亦可用查表指令完成(如下程序段)MOV AL,SUR ;AL=X LEA BX, SQTABADD BX,AX ;MOV AL, SURMOV AL,[BX] ;XLATMOV DIS,AL ;MOV DIS, ALCODE ENDSEND BEGIN例2 已知Z=(X+Y)-(W+Z),其中X,Y,Z,W均为用压缩BCD码表示的数,写出程序。
分析:这也是一种典型的直线程序,在这里要注意是BCD数相加,要进行十进制调整。
具体程序如下:MOV AL ,Z MOV BL ,W ADD AL ,BLDAAMOV BL ,AL ; BL=(W+Z ) MOV AL ,X MOV DL ,Y ADD AL ,DL ; AL=(X+Y )DAA ;十进制调整SUBAL ,BL ; AL=(X+Y )-(Z+W )DAS ;十进制调整MOV Z ,AL ;结果送Z 例2 利用表实现分支根据AL 中各位被置位情况,控制转移到8个子程序P1~P8之一中去。
转移表的结构如表3-2所示。
分析:对于这种程序关键要找出每种情况的转移地址,从图中可见表地址=表基地址+偏移量, 而偏移量可由AL 各位所在位置*2求得。
流程图见图3-3。
DATA SEGMENTBASE DW SR0,SR1,SR2,SR3, SR4,SR5,SR6,SR7 DATA ENDS CODESEGMENTASSUME CS :CODE ,DS :DATA ,ES :DATA BEGIN : PUSH DS XORAX ,AXPUSH AXMOV AX ,DATA 图3-3 流程图 MOV DS ,AXLEABX ,BASE ;表头送BX表3-2 子程序R1—R8的入口地址表P1 子程序R1的入口偏移地址 P2 子程序R2的入口偏移地址 P3 子程序R3的入口偏移地址 …… …… ……. ……P7 子程序R7的入口偏移地址 P8子程序R8的入口偏移地址IN AL,PORTGETBIT:RCR AL,1 ;右移一位JC GETAD ;移出位是1?INC BXINC BX ;修改指针JMP GETBIGETAD:JMP WORD PTR[BX] ;实现散转CODE ENDSEND BEGIN根据跳转表构成方法不同,实现分支的方法也有所改变,下面有三个问题希望大家思考:(1) 若跳转表地址由段值和偏移量四个字节构成,程序应如何实现?(2) 若跳转表中的内容由JMP OPRD指令构成,表的结构应如何组织、程序如何实现?(3) 上述程序若不用间接跳转指令,而改为直接跳转,程序如何变动?例3将内存中某一区域的原数据块传送到另一区域中。
分析:这种程序若源数据块与目的数据块之间地址没有重叠,则可直接用传送或串操作实现;若地址重叠,则要先判断源地址+数据块长度是否小于目的地址,若是,则可按增量方式进行,否则要修改指针指向数据块底部,采用减量方式传送。
程序如下:DATA SEGMENTSTR DB 1000 DUP(?)STR1 EQU STR+7STR2 EQU STR+25STRCOUNT EQU 50DATA ENDSSTACK SEGMENT PARA STACK ‘STACK’STAPN DB 100DUP(?)STACK ENDSCODE SEGMENTASSUME CS:CODE,DS:DATA,ES:DATA,SS:STACK GOO PROCPUSH DSSUB AX,AX ;将AX清零PUSH AXMOV AX,DATAMOV DS,AXMOV ES,AXMOV AX,STACKMOV SS,AXMOV CX,STRCOUNTMOV SI,STR1MOV DI,STR2CLD ;将DF置0确定地址修改方向PUSH SI ;将源首地址入栈ADD SI,STRCOUNT-1 ;判断源地址+数据块长度是否小CMP SI,DI ;于目的地址POP SI ;将源首地址弹出堆栈,赋给SIJL OK ;如果源地址+数据;块长度小于目的地址,直接传送数据STD ;如果大于目的地址,将DF置1改变地址修改方向ADD SI,STRCOUNT-1 ;从最后一个存储单元传送数据,以免ADD DI,STRCOUNT-1 ;把源数据中最后几个单元的数据覆盖OK:REP MOVSBRETGOO ENDPCODE ENDSEND GOO例4 设内存BUFF开始的单元中依次存放着30个8位无符号数,求它们的和并放在SUM单元中,试编写程序。
分析:这是一个求累加的程序。
(设计思想同C语言)程序如下:MOV SI,BUFF ;设地址指针MOV CX,30 ;设计数初值XOR AX,AX ;设累加器初值AGAIN:ADD AL,[SI]ADC AH,0INC SIDEC CXJNZ AGAIN ;循环累加MOV SUM,AX例4在给定个数的16位数串中,找出大于零、等于零和小于零的个数,并紧跟着原串存放。
分析:这是一个统计问题,须设定三个计数器分别统计三种情况下的结果。
程序如下:DATA SEGMENTBUFF DW X1,X2,X3, (X)COUNT EQU $-BUFF ;此时,COUNT的值为BUFF所占的字节数PLUSE DB ?ZERO DB ?MINUS DB ?DATA ENDSCODE SEGMENTASSUME CS:CODE,DS:DATAASSUME ES:DATA,SS:STACKBEGIN:MOV AX,DATAMOV DS,AXMOV CX,COUNTSHR CX,1 ;相当于除2,正好为BUFF中的数据个数MOV DX,0 ;设定计数器初值MOV AX,0 ;设定计数器初值LEA BX,BUFFAGAIN:CMP WORD PTR[BX],0JAE PLU ;大于等于0,则转PIUINC AH ;<0,则统计JMP NEXTPLU:JZ ZER ;=0,则转ZERINC DL ;>0,则统计JMP NEXTZER:INC DH ;=0,则统计NEXT:INC BXINC BXLOOP AGAINMOV PLUS,DLMOV ZERO,DHMOV MINUS,AHMOV AX,4C00HINT 21HCODE ENDSEND BEGIN第七章8259A的应用举例例1. IBMPC机中,只有一片8259A,可接受外部8级中断。
在I/O地址中,分配8259A的端口地址为20H和21H,初始化为:边沿触发、缓冲连接、中断结束采用EOI命令、中断优先级采用完全嵌套方式,8级中断源的中断类型分别为08H—0FH,初始化程序为:MOV DX,20HMOV AL,00010011BOUT DX,AL ;写入ICW1MOV DX,21HMOV AL,08HOUT DX,AL ;写入ICW2MOV AL,00001101BOUT DX,AL ;写入ICW4XOR AL,ALOUT DX,AL ;写入OCW1。
STI。
例2.进入和退出特殊屏蔽方式的流程图。
假定,初始化之后,8259A工作于完全嵌套方式,要求对于IR3的中断级,能够允许任何级别的中断中断其中断服务程序,即8259A按特殊屏蔽方式工作。
因而在响应IR3而执行IR3的中断服务程序时,在A处,写入OCW1以屏蔽IR3,然后写入OCW3使ESMM=SMM=1,于是从A处开始,8259A进而特殊屏蔽方式,此后继续执行IR3的中断服务程序。
在中断服务结束之前,再向8259A写入OCW3使ESMM=1,SMM=0,结束特殊屏蔽方式,返回到完全嵌套方式,接着写入OCW1,撤消对IR3的屏蔽,最后写入OCW2,向8259A发出EOI命令。
此例,说明在IR3的中断服务程序的A处至B处,允许任何级别的中断源中断IR3的服务程序。
(除本身之外)。
IR3中断服务程序入口STI 保护现场。
STI 开中断MOV AL,00001000B 服务程序OUT 21H,AL ;OCW1 写入OCW1,使IM3=1MOV AL,01101000B 写入OCW3,使ESMM=SMM=1OUT 20H,AL ;OCW3继续服务。
写入OCW3,使ESMM=1,SMM=0 MOV AL,01001000B 写入OCW1,使IM3=0OUT 20H,AL ;OCW3 写入OCW2,普通的EOI命令MOV AL,00H 中断返回OUT 21H,AL ;OCW1MOV AL,00100111BOUT 20H,AL ;OCW3OUT 21H,AL ;OCW3 EOI命令例3.读8259A相关寄存器的内容。
设8259A的端口地址为20H、21H,请读入IRR、ISR、IMR寄存器的内容,并相继保存在数据段2000H开始的内存单元中;若该8259A为主片,请用查询方式,查询哪个从片有中断请求。
解:MOV AL,xxx01010B 发OCW3,欲读取IRR的内容OUT 20H,ALIN AL,20H 读入并保存IRR的内容MOV (2000H),ALMOV AL,xxx01011B 发OCW3,欲读取ISR的内容OUT 20H,ALIN AL,20H 读入并保存ISR的内容MOV (2001H),ALIN AL,21H 读入并保存ISR的内容MOV (2002H),ALMOV AL,xxx0110xB 发OCW3,欲查询是否有中断请求OUT 20HIN AL,20H 读入相应状态,并判断最高位是否为1TEST AL,80HJZ DONEAND AL,07H 判断中断源的编码…………DONE:HLT第八章接口应用举例例4 将上例中8255A的工作方式改为方式1,采用中断方式将BUFF开始的缓冲区中的100个字符从打印机输出。