(2011.11.09)汇编_王爽_第16章_学习小结

 

(2011.11.09)汇编_王爽_第16章_学习小结

本章内容:

1. seg操作符,取得某一标号的段地址。offset操作符,取得某一标号的偏移地址。

2. 如何使用数据标号,描述了单元长度的标号。

3. 数值+30h = 对应字符的ASCII代码。

4. 直接定址表

 

|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||

; 程序名称:实验16_setscreen_编写多个功能子程序的中断例程.asm
; 程序功能:1. 清屏 2. 设置前景色 3.设置背景色 4. 向上滚动一行

; ------------------------------------------------------------------------------------------------ the whole program start---
assume cs:code

;  -------------------------------------------------------------------------------------------statement start ---
; 段名:ss:stack
; 功能: 用于临时保存各个寄存器的数据
; 大小:共占用了128个字节,即64个字
; ---------statement end------------------------

stack segment
	db 128 dup (0) 
	db 128 dup (0)
stack ends
;-------------------------------------------------------------------------------------------- program end---

; -------------------------------------------------------------------------------------------statement start ---
; 段名: ds:data
; 功能:用于保存int9中断例程的入口地址
; 大小:共占用两个字,即四个字节
; ---------- statement end --------------------------------
data segment
	dw 0, 0
data ends
; ------------------------------------------------------------------------------------------- program end ---

code segment
start2:
; 设置中断入口
	mov ax, stack			; 先设置好堆栈的地址
	mov ss, ax			; 让ss:sp指向stack段的末端
	mov sp, 256

	mov ax, data			; 然后设置ds的地址,让其指向data段
	mov ds, ax			; 目的是存放原中断向量表的地址

	mov ax, 0				; 之后是设置es的地址,令es作为段地址可以指向中断向量表
	mov es, ax

	push es:[9*4]			; 将中断向量表中int9的地址放入堆栈中
	pop ds:[0]			; 再将地址取出放入data段中
	push es:[9*4+2]
	pop ds:[2]			; 将原来的int 9中断例程的入口地址保存在ds:0, ds:2单元中

	mov word ptr es:[9*4], offset int9
	mov es:[9*4+2], cs		; 在中断向量表中设置新的int 9中断例程的入口地址

; 新的中断入口设置完成
; 下面开始主程序

	mov ax, 0b800h
	mov es, ax
	mov ah, 'a'
	mov bx, 0
	mov cx, 2000
sss:	
	mov es:[bx], ah
	call delay
	add bx, 2
	loop sss

; 主程序执行完
; 下面开始将中断向量表的int 9中断例程恢复为原来的地址

	push ds:[0]
	pop es:[9*4]
	push ds:[2]
	pop es:[9*4+2]
    

	mov ax, 4c00h
	int 21h
; 主程序执行完成。


; --------------------------------------------------------------------------------------------statement start ---
; 子程序名称:delay
; 子程序的功能:不断地执行空循环,目的是时间延迟
; ---------------------statement end ---
delay: 
	push ax
	push dx
	push cx 
	
	mov cx, 9fffh
clop:
	mov dx, 0				   ; 循环次数2X次。
	mov ax, 0
s1:
	inc dx
	add ax, dx
	cmp ax, 9fffH			; 此处设置重复的X次
	jne s1
s2:
	dec dx
	cmp dx, 0
	jne s2
	loop clop 
    
    pop cx
	pop dx
	pop ax
	ret
; -----------------------------------------------------------------------------------------------program end ----	


; --------------------------------------------------------------------------------------------statement start ---
; 子程序名称:新int 9中断例程段
; 子程序功能:设置新的int9例程,并模拟中断过程。
; 子程序分析:子程序一共分为四大步骤
;			  1. 标志寄存器入栈  2. IF = 0, TF = 0  3. CS、IP入栈 
;			  4. (IP) = ((ds)*16+0), (CS) = ((ds)*16 +2)
; -------------statement end ---------------------------------

int9:	
	push ax
	push bx
	push es
	push cx
	push ds
  
    
	in al, 60h				; 此处为了引发9号中断
						; 当键盘的输入到达60h端口时
						; 相关的芯片就会向CPU发出中断类型码为9的可屏蔽中断信息
						; 如果IF = 1, 则响应中断,转去执行int9中断例程
	
	pushf				; 此步模拟第1步,标志寄存器入栈
	pushf				; 此处开始第2步,将IF及TF置零
	pop bx				; 将flag寄存器中的数据从堆栈中取出,并且下面进行修改
	and bh, 11111100b		; 将IF和TF置0
	push bx				; 第2 步结。修改以后再将flag寄存器中的数据放回堆栈中
	popf					; 第1步结.
	call dword ptr ds:[0]	; 第3步,CS:IP入栈.对int指令进行模拟,调用原来的int 9中断指令

	cmp al, 0Bh
	je functions			; 等于零 

	cmp al, 02
	jb int9ret				; 小于1
	cmp al, 04
	ja int9ret				; 大于3

functions:
    mov ah, 0               ; 扫描码转化成数字
    cmp al, 0Bh
    je ss3
    cmp al, 02
    je ss2
    cmp al, 03
    je ss1
    cmp al, 04
    je ss0
ss0:
    inc ah
ss1:
    inc ah
ss2:
    inc ah
ss3:    

    mov al, 0101b
	call setscreen

int9ret:
	pop ds
	pop cx
	pop es
	pop bx
	pop ax
	iret
; ----------------------------------------------------------------------------------------------------program end ----------------


; ---------------------------------------------------------------------------------------- statement start ------
; 子程序名称:setscreen
; 子程序功能:将0.清屏,1.设置前景色,2.设置背景色,3.向上滚动一行 四种功能封装在这函数中。
; 子程序参数:ah为功能号0,1,2,3, al为颜色值(对于1,2功能的)
;			  功能号*2 = 对应的功能子程序在地址表中的偏移。	
; -----------------------------------------------------------------------------------------statement end -----

setscreen:	
		jmp short set
table   dw sub1, sub2, sub3, sub4

set:
		push bx			; 因为下面要用到bx,为了防止对其它子程序造成影响,先将bx放入堆栈中。

		cmp ah, 3			; 判断功能号是否大于3,大于3则不执行任何操作
		ja sret
		mov bl, ah
		mov bh, 0
		add bx, bx		; 根据ah中的功能号按*2计算在table中的地址

		call word ptr table[bx]	; 调用相对应的功能子程序

sret:	
		pop bx
		ret
;--------------------------------------------------------------------------------------------------------------- program end -----

; ------------------------------------------------------------------------------------------ statement start -----
; 子程序名称:sub1
; 子程序功能:清屏:将显存中当前屏幕中的字符设为空格符。
; --------------------------------------- statement end --------

sub1: 
		push bx
		push cx
		push es
		mov bx, 0b800h
		mov es, bx		; 设置显示区域的地址
		mov bx, 0
		mov cx, 2000		;  一屏有80*25 = 2000 个字符

sub1s:
		mov byte ptr es:[bx], ' '
		add bx, 2			; 高位存放字符,低位存放属性,所以步进为2
		loop sub1s
		
		pop es
		pop cx
		pop bx
		ret
;---------------------------------------------------------------------------------------------------------------- program end -----

; ---------------------------------------------------------------------------------------------statement start -----
; 子程序名称:sub2
; 子程序功能:设置前景色,设置显存中当前屏幕中处于奇地址的属性字节的第0, 1, 2位
; --------------------------------------- statement end --------

sub2: 
		push bx
		push cx
		push es
		
		mov bx, 0b800h
		mov es, bx
		mov bx, 1			; 字符属性区域从下标1开始
		mov cx, 2000		; 一屏需要设置2000个属性

sub2s:	
		and byte ptr es:[bx], 11111000b	; 在使用颜色设置时,先将该属性清零
		or es:[bx], al					; 结合al,设置前景色
		add bx, 2						; 步进为2,原因为2个字节存放一个字符
		loop sub2s

		pop es
		pop cx
		pop bx
		ret
;---------------------------------------------------------------------------------------------------------------- program end -----

; ---------------------------------------------------------------------------------------------statement start -----
; 子程序名称:sub3
; 子程序功能:设置背景色,设置显存中当前屏幕中处于奇地址的属性字节的第4, 5, 6位
; --------------------------------------- statement end --------
sub3:
		push bx
		push cx
		push es

		mov cl, 4
		shl al, cl			; 将属性左移至正确的位置
		mov bx, 0b800h
		mov es, bx
		mov bx, 1			; 字符属性区域从下标1开始
		mov cx, 2000		; 一屏需要设置2000个属性
sub3s:	
		and byte ptr es:[bx], 10001111b  ;将背景色属性清零
		or es:[bx], al		; 结合al,设置背景色
		add bx, 2			; 步进为2,原因为2个字节存放一个字符
		loop sub3s
		
		pop es
		pop cx
		pop bx
		ret
;---------------------------------------------------------------------------------------------------------------- program end -----

; ---------------------------------------------------------------------------------------------statement start -----
; 子程序名称:sub4
; 子程序功能:使屏幕显示向上滚动一行:依次将第n+1行的内容复制到第n行处:最后一行为空。
; --------------------------------------- statement end --------
sub4:
		push cx
		push si
		push di
		push es
		push ds

		mov si, 0b800h
		mov es, si
		mov ds, si			
		mov si, 160			; ds:si指向第n+1行
		mov di, 0				; es:di指向第n行
							; 将下一行移上, mov es:[di], byte ptr ds:[si]
		cld					; 设置正方向递增, DF = 0
		mov cx, 24			; 共复制24行

sub4s:
		push cx				; 此处需要内嵌循环,先将cx存放
		mov cx, 160
		rep movsb			; 复制160列
		pop cx
		loop sub4s			; 再复制21行

		mov cx, 80
		mov si, 0
sub4s1:
		mov byte ptr[160*24+si], ' '	 ; 将最后一行清空
		add si, 2
		loop sub4s1

		pop ds
		pop es
		pop di
		pop si
		pop cx
		ret
;---------------------------------------------------------------------------------------------------------------- program end -----

code ends
end start2
;---------------------------------------------------------------------------------------------------------------- the whole program end -----

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值