解决了两个问题,还得再问一个新问题,王爽课程设计2的时钟显示更改程序逻辑后不会自动跳动

feekee 2017-07-01 05:41:01
代码如下,跟第二个问题中的一摸一样。问题部分是因为按照课程设计,按2进入dos界面后,会把之前选择时的按键如3、2、F1等在c:\后显示出来,为了进入dos后不显示这些按键,计划在按2进入dos之前把这些按键对应的键盘缓冲都清掉。
那么,我不明白的是下面红色和绿色两种做法,都可以达到目的。但是如果按照红色的做法,注释掉绿色的部分,按3进入时钟显示界面后,时间会自己一直跳动;如下:

而如果把红色的部分注释掉,使用绿色的部分(即进入自定义的中断例程后一开始就删除键盘的缓冲),那么进入时钟界面后,时钟界面只显示一次当前的时间,时间不会跳动。想请教一下,不知道这个删除键盘缓冲区的位置怎么会对时钟显示有的影响?
assume cs:codesg,ds:datasg,ss:stacksg
datasg segment
db 4 dup (0)
datasg ends
stacksg segment
dw 32 dup (0)
stacksg ends
codesg segment
start:;write to the floppy
mov ax,cs
mov es,ax
mov bx,offset floppy

mov dl,0
mov dh,0
mov cl,1
mov ch,0
mov al,2
mov ah,3
int 13h

mov ax,4c00h
int 21h

org 7c00h
floppy:jmp short beg
origin_int9 dw 0,0
dis_choice db 0
is_clock db 0
format2 db 'YE/MO/DA hh:mm:ss',0
;mov ax,stacksg
;mov ss,ax
;mov sp,32*2
;mov ax,datasg
beg:;将第二个扇区读入内存
mov ax,0
mov es,ax
mov bx,7c00h+200h
mov dx,0
mov cx,2
mov ax,0201h
int 13h

mov dis_choice,1
call display

;替换9号中断
mov ax,0
mov es,ax
mov ax,es:[9*4]
mov origin_int9,ax
mov ax,es:[9*4+2]
mov origin_int9[2],ax

cli
mov word ptr es:[9*4],offset s9_beg
mov word ptr es:[9*4+2],cs
sti

s3:nop
jmp short s3

s9_beg:push bp
mov bp,sp
add bp,2
push ax
push ds
push bx
push si
push cx
push es
push di

in al,60h
mov bl,al
pushf
;mov si,offset origin_int9
call dword ptr origin_int9;here the book use 'cs' register

mov ah,0
int 16h

cmp bl,2h
je reset
cmp bl,3h
je sys
cmp bl,4
je clock
cmp is_clock,1
jne s10
cmp bl,3Bh
je c_f1
cmp bl,1h
jne s10
jmp near ptr c_esc
s10:jmp near ptr s4
reset:mov ax,ss
mov ds,ax
mov word ptr ds:[bp],0
mov word ptr ds:[bp+2],0ffffh
jmp near ptr s4
sys:;
;恢复int 9
mov ax,0
mov es,ax
mov ax,origin_int9
mov es:[9*4],ax
mov ax,origin_int9[2]
mov es:[9*4+2],ax
;删除键盘缓冲区
;mov ah,0
;int 16h

;int 13h 读硬盘
mov dx,0080h
mov cx,0001h
mov bx,7c00h
;es的值已设置过
mov ax,0201h
;模拟int 13h指令
pushf
;pushf
;pop ax
;and ah,11111100b
;push ax
;popf
push es
push bx
mov dis_choice,0
call display
jmp dword ptr es:[13h*4]
clock:mov is_clock,1
;mov ah,0
;int 16h

mov ax,ss
mov ds,ax
mov word ptr ds:[bp],offset clock_dis
mov ax,cs
mov word ptr ds:[bp+2],ax
mov dis_choice,0
call display
jmp short s4
c_f1:;mov ah,0
;int 16h

mov ax,0b800h
mov es,ax
mov di,160*12+62+1
mov si,0
cf1_s1:cmp byte ptr format2[si],0
je s4
add byte ptr es:[di],1
inc si
add di,2
jmp short cf1_s1
c_esc:;mov ah,0
;int 16h

mov is_clock,0
;清除屏幕先
mov ax,0b800h
mov es,ax
mov di,160*12+62
mov si,0
cesc_s1:cmp byte ptr format2[si],0
je cesc_s3
mov es:[di],0720h
inc si
add di,2
jmp short cesc_s1
cesc_s3:mov dis_choice,1
call display
mov ax,ss
mov ds,ax
mov word ptr ds:[bp],offset s3
mov ax,cs
mov word ptr ds:[bp+2],ax
jmp short s4
s4:pop di
pop es
pop cx
pop si
pop bx
pop ds
pop ax
pop bp
iret
s9_se:nop

;dis_choice为参数:1为显示,0为清屏
display:jmp short dis_beg
ad dw f1,f2,f3,f4
f1 db '1) reset pc',0
f2 db '2) start system',0
f3 db '3) clock',0
f4 db '4) set clock',0
dis_beg:push ax
push es
push di
push cx
push si
push bx
push dx
mov ax,0b800h
mov es,ax
mov cx,0 ;行数计数器
mov si,0 ;每行地址的指针
next:mov di,10*160+32*2
mov ax,160
mul cx
add di,ax

mov bx,ad[si]
add si,2
s0:mov al,cs:[bx]
cmp al,0 ;一行是否结束
je s1
add bx,1
;display功能选择
cmp dis_choice,1
je s2
mov byte ptr es:[di],' '
jmp short s5
s2:mov es:[di],al
s5:add di,2
jmp short s0
s1:add cx,1
cmp cx,4
je dis_end
jmp short next
dis_end:pop dx
pop bx
pop si
pop cx
pop di
pop es
pop ax
ret

clock_dis:jmp short s7
format db 'YE/MO/DA hh:mm:ss',0
position db 9,8,7,4,2,0
s7:mov bx,0
mov si,0
mov cx,6
s9:mov al,position[bx]
out 70h,al
in al,71h
mov ah,al
push cx
mov cl,4
shr ah,cl
pop cx
and al,00001111b

add ah,30h
add al,30h

mov format[si],ah
mov format[si+1],al
add si,3
inc bx
loop s9

mov ax,0b800h
mov es,ax
mov di,160*12+62
mov si,0
s8:cmp byte ptr format[si],0
je s7
mov al,format[si]
mov es:[di],al
inc si
add di,2
jmp short s8
codesg ends
end start

另外附上我在标号s7的地方加上下面的代码进行过的一次调试
mov ax,0b800h
mov es,ax
inc byte ptr es:[160*24+158]
观察按3以后s7是不是一直在执行。结果是右下角的符号每次按3会快速变化一下,然后就不变了。比如第一次按3后显示'G',按esc退出第二次按3进去,变成一个乱码,然后再按esc再按3进入,又是变了一下就停了,如图。为啥每次都是只执循环限次数呢?这就是上面的问题
...全文
677 2 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
feekee 2017-08-04
  • 打赏
  • 举报
回复
这不是个好问题,有点超出设计本身的范围了,先扔这里了,哪位大大路过看到了,帮俺解决了到时再结贴
feekee 2017-07-01
  • 打赏
  • 举报
回复
发现这样代码看上不去不清晰,但是使用[code]格式发的话,又没法对代码进行着色,所以按照代码格式再发一遍,大家可以对照位置看下面的代码,多谢

assume cs:codesg,ds:datasg,ss:stacksg
datasg segment
  db 4 dup (0)
datasg ends
stacksg segment
  dw 32 dup (0)
stacksg ends
codesg segment
  start:;write to the floppy
  		mov ax,cs
  		mov es,ax
  		mov bx,offset floppy
  		
  		mov dl,0
  		mov dh,0
  		mov cl,1
  		mov ch,0
  		mov al,2
  		mov ah,3
  		int 13h
  		
  		mov ax,4c00h
  		int 21h
 
 org 7c00h
 floppy:jmp short beg
origin_int9 dw 0,0
dis_choice db 0
is_clock db 0
format2 db 'YE/MO/DA hh:mm:ss',0
 		;mov ax,stacksg
  		;mov ss,ax
  		;mov sp,32*2
  		;mov ax,datasg
  	beg:;将第二个扇区读入内存
  		mov ax,0
  		mov es,ax
  		mov bx,7c00h+200h
  		mov dx,0
  		mov cx,2
  		mov ax,0201h
  		int 13h
  		
  		mov dis_choice,1
  		call display
  		
  		;替换9号中断
  		mov ax,0
   		mov es,ax
  		mov ax,es:[9*4]
  		mov origin_int9,ax
  		mov ax,es:[9*4+2]
  		mov origin_int9[2],ax
  		
  		cli
  		mov word ptr es:[9*4],offset s9_beg
   		mov word ptr es:[9*4+2],cs
   		sti
  		
   	 s3:nop
   		jmp short s3
   		
 s9_beg:push bp
 		mov bp,sp
 		add bp,2
 		push ax
 		push ds
 		push bx
 		push si
 		push cx
 		push es
 		push di
 		
 		in al,60h
		mov bl,al
 	 	pushf
 		;mov si,offset origin_int9
  		call dword ptr origin_int9;here the book use 'cs' register

  		mov ah,0
  		int 16h
  		cmp bl,2h
 		je reset
 		cmp bl,3h
 		je sys
 		cmp bl,4
 		je clock
 		cmp is_clock,1
 		jne s10
 		cmp bl,3Bh
 		je c_f1
 		cmp bl,1h
 		jne s10
 		jmp near ptr c_esc
 	s10:jmp near ptr s4
  reset:mov ax,ss
  		mov ds,ax
  		mov word ptr ds:[bp],0
  		mov word ptr ds:[bp+2],0ffffh
  		jmp near ptr s4
    sys:;
    	;恢复int 9
    	mov ax,0
    	mov es,ax
    	mov ax,origin_int9
  		mov es:[9*4],ax
  		mov ax,origin_int9[2]
  		mov es:[9*4+2],ax
  		;删除键盘缓冲区
  		;mov ah,0
  		;int 16h
  		;int 13h 读硬盘
    	mov dx,0080h
    	mov cx,0001h
    	mov bx,7c00h
    	;es的值已设置过
    	mov ax,0201h
    	;模拟int 13h指令
    	pushf
    	;pushf
    	;pop ax
    	;and ah,11111100b
    	;push ax
    	;popf
    	push es
    	push bx
    	mov dis_choice,0
    	call display
    	jmp dword ptr es:[13h*4]
  clock:mov is_clock,1
  		;mov ah,0
  		;int 16h
  		mov ax,ss
  		mov ds,ax
  		mov word ptr ds:[bp],offset clock_dis
  		mov ax,cs
  		mov word ptr ds:[bp+2],ax
  		mov dis_choice,0
  		call display
  		jmp short s4
   c_f1:;mov ah,0
  		;int 16h
   		mov ax,0b800h
        mov es,ax
        mov di,160*12+62+1
        mov si,0
 cf1_s1:cmp byte ptr format2[si],0
        je s4
        add byte ptr es:[di],1
        inc si
        add di,2
        jmp short cf1_s1
  c_esc:;mov ah,0
  		;int 16h
  		mov is_clock,0
		;清除屏幕先
  		mov ax,0b800h
        mov es,ax
        mov di,160*12+62
        mov si,0
cesc_s1:cmp byte ptr format2[si],0
        je cesc_s3
        mov es:[di],0720h
        inc si
        add di,2
        jmp short cesc_s1
cesc_s3:mov dis_choice,1
		call display
  		mov ax,ss
  		mov ds,ax
  		mov word ptr ds:[bp],offset s3
  		mov ax,cs
  		mov word ptr ds:[bp+2],ax
  		jmp short s4
     s4:pop di
     	pop es
     	pop cx
     	pop si
  		pop bx
  		pop ds
  		pop ax
  		pop bp
  		iret
  s9_se:nop
  
  ;dis_choice为参数:1为显示,0为清屏
  display:jmp short dis_beg
  ad dw f1,f2,f3,f4
  f1 db '1) reset pc',0
  f2 db '2) start system',0
  f3 db '3) clock',0
  f4 db '4) set clock',0  
  dis_beg:push ax
  	      push es
  	      push di
  	      push cx
  	      push si
  	      push bx
  	      push dx
  		  mov ax,0b800h
  		  mov es,ax
  		  mov cx,0	;行数计数器
  		  mov si,0	;每行地址的指针
  	 next:mov di,10*160+32*2
	      mov ax,160
	 	  mul cx
	      add di,ax

  	      mov bx,ad[si]
  		  add si,2
  	   s0:mov al,cs:[bx]
  		  cmp al,0	;一行是否结束
  		  je s1
  		  add bx,1
  		  ;display功能选择
  		  cmp dis_choice,1
  		  je s2
  		  mov byte ptr es:[di],' '
  		  jmp short s5
  	   s2:mov es:[di],al
  	   s5:add di,2
  		  jmp short s0
	   s1:add cx,1
	      cmp cx,4
	      je dis_end
	      jmp short next
  dis_end:pop dx
  		  pop bx
  		  pop si
  		  pop cx
  		  pop di
  		  pop es
  		  pop ax
  		  ret
  		  
clock_dis:jmp short s7
format db 'YE/MO/DA hh:mm:ss',0
position db 9,8,7,4,2,0
     s7:mov bx,0
        mov si,0
        mov cx,6
     s9:mov al,position[bx]
        out 70h,al
        in al,71h
        mov ah,al
        push cx
        mov cl,4
        shr ah,cl
        pop cx
        and al,00001111b
        
        add ah,30h
        add al,30h
        
        mov format[si],ah
        mov format[si+1],al
        add si,3
        inc bx
        loop s9
        
        mov ax,0b800h
        mov es,ax
        mov di,160*12+62
        mov si,0
     s8:cmp byte ptr format[si],0
        je s7
        mov al,format[si]
        mov es:[di],al
        inc si
        add di,2
        jmp short s8
codesg ends
end start
【内容简介】 汇编语言是各种CPU所提供的机器指令的助记符的集合,人们可以用汇编语言直接控制硬件系统进行工作。汇编语言是很多相关课程(如:数据结构、操作系统、微机原理等)的重要基础。为了更好地引导、帮助读者学习汇编语言,作者以循序渐进的方式精心创作了这本书。本书具有如下特点:采用全的结构对课程的内容进行了组织,对知识进行最小化分割,为读者构造了循序渐进的学习线索;在深入本质的层面上对汇编语言进行讲解;对关键环节进行深入的剖析。 本书可用作大学计算机专业本科生的汇编教材及希望深入学习计算机科学的读者的自学教材。 【目录信息】 第1章基础知识 1.1 机器语言 1.2 汇编语言的产生 1.3 汇编语言的组成 1.4 存储器 1.5 指令和数据 1.6 存储单元 1.7 CPU对存储器的读写 1.8 地址总线 1.9 数据总线 1.10 控制总线 1.11 内存地址空间(概述) 1.12 主板 1.13 接口卡 1.14 各类存储器芯片 1.15 内存地址空间 第2章寄存器(CPU工作原理) 2.1 通用寄存器 2.2 字在寄存器中的存储 2.3 几条汇编指令 2.4 物理地址 2.5 16位结构的CPU 2.6 8086CPU给出物理地址的方法 2.7 "段地址x16+偏移地址=物理地址"的本质含义 2.8 段的概念 2.9 段寄存器 2.10 CS和IP 2.11 修改CS.IP的指令 2.12 代码段 实验1 查看CPU和内存,用机器指令和汇编指令编程 第3章寄存器(内存访) 3.1 内存中字的存储 3.2 DS和[address] 3.3 字的传送 3.4 mov.add.sub指令 3.5 数据段 3.6 栈 3.7 CPU提供的栈机制 3.8 栈顶超界的 3.9 push.pop指令 3.10 栈段 实验2 用机器指令和汇编指令编程 第4章第1个程序 4.1 一个源程序从写出到执行的过程 4.2 源程序 4.3 编辑源程序 4.4 编译 4.5 连接 4.6 以简化的方式进行编译和连接 4.7 1.exe的执行 4.8 可执行文件中的程序装入内存并运行的原理 4.9 程序执行过程的跟踪 实验3 编程.编译.连接.跟踪 第5章[bx]和loop指令 5.1 [bx] 5.2 Loop指令 5.3 在Debug中跟踪用loop指令实现的循环程序 5.4 Debug和汇编编译器Masm对指令的不同处理 5.5 loop和[bx]的联合应用 5.6 段前缀 5.7 一段安全的空间 5.8 段前缀的使用 实验4 [bx]和loop的使用 第6章包含多个段的程序 6.1 在代码段中使用数据 6.2 在代码段中使用栈 6.3 将数据.c代码.c栈放入不同的段 实验5 编写,调试具有多个段的程序 第7章更灵活的定位内存地址的方法 7.1 and和or指令 7.2 关于ASCII码 7.3 以字符形式给出的数据 7.4 大小写转换的 7.5 [bx+idata] 7.6 用[bx+idata]的方式进行数组的处理 7.7 SI和DI 7.8 [bx+si]和[bx+di] 7.9 [bx+si+idata]和[bx+di+idata] 7.10 不同的寻址方式的灵活应用 实验6 实践课程中的程序 第8章数据处理的两个基本 8.1 bx,si,di,bp 8.2 机器指令处理的数据所在位置 8.3 汇编语言中数据位置的表达 8.4 寻址方式 8.5 指令要处理的数据有多长? 8.6 寻址方式的综合应用 8.7 div指令 8.8 伪指令dd 8.9 dup 实验7寻址方式在结构化数据访中的应用 第9章转移指令的原理 9.1 操作符offset 9.2 jmp指令 9.3 依据位移进行转移的jmp指令 9.4 转移的目的地址在指令中的jmp指令 9.5 转移地址在寄存器中的jmp指令 9.6 转移地址在内存中的jmp指令 9.7 jcxz指令 9.8 loop指令 9.9 根据位移进行转移的意义 9.10 编译器对转移位移超界的检测 实验8 分析一个奇怪的程序 实验9 根据材料编程 第10章call和ret指令 10.1 ret和retf 10.2 call指令 10.3 依据位移进行转移的call指令 10.4 转移的目的地址在指令中的call指令 10.5 转移地址在寄存器中的call指令 10.6 转移地址在内存中的call指令 10.7 all和ret的配合使用 10.8 mul指令 10.9 模块化程序设计 10.10 参数和结果传递的 10.11 批量数据的传递 10.12 寄存器冲突的 实验10 编写子程序 课程设计1 第11章标志寄存器 11.1 ZF标志 11.2 PF标志 11.3 SF标志 11.4 CF标志 11.5 OF标志 11.6 adc指令 11.7 sbb指令 11.8 cmp指令 11.9 检测比较结果的条件转移指令 11.10 DF标志和串传送指令 11.11 pushf和popf 11.12 标志寄存器在Debug中的表示 实验11 编写子程序 第12章内中断 12.1 内中断的产生 12.2 中断处理程序 12.3 中断向量表 12.4 中断过程 12.5 中断处理程序 12.6 除法错误中断的处理 12.7 编程处理0号中断 12.8 安装 12.9 do0 12.10 设置中断向量 12.11 单步中断 12.12 响应中断的特殊情况 实验12 编写0号中断的处理程序 第13章int指令 13.1 int指令 13.2 编写供应用程序调用的中断例程 13.3 对int iret和栈的深入理解 13.4 BIOS和DOS所提供的中断例程 13.5 BIOS和DOS中断例程的安装过程 13.6 BIOS中断例程应用 13.7 DOS中断例程应用 实验13 编写应用中断例程 第14章端口 14.1 端口的读写 14.2 CMOS RAM芯片 14.3 shl和shr指令 14.4 CMOS RAM中存储的时间信息 实验14访CMOS 第15章外中断 15.1 接口芯片和端口 15.2 外中断信息 15.3 PC机键盘的处理过程 15.4 编写int 9中断例程 15.5 安装的int 9中断例程 实验15 安装的int 9中断例程指令系统总结 第16章直接定址表 16.1 描述了单元长度的标号 16.2 在其他段中使用数据标号 16.3 直接定址表 16.4 程序入口地址的直接定址表 实验16 编写包含多个功能子程序的中断例程 第17章使用BIOS进行键盘输入和磁盘读写 17.1 int 9中断例程对键盘输入的处理 17.2 使用int 16h中断例程读取键盘缓冲区 17.3 字符串的输入 17.4 应用int 13h中断例程对磁盘进行读写 实验17 编写包含多个功能子程序的中断例程 课程设计2

21,497

社区成员

发帖
与我相关
我的任务
社区描述
汇编语言(Assembly Language)是任何一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。
社区管理员
  • 汇编语言
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧