本文主要是介绍《汇编语言》- 读书笔记 - 第16章-实验16 编写包含多个功能子程序的中断例程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
《汇编语言》- 读书笔记 - 第16章-实验16 编写包含多个功能子程序的中断例程
- 需求
- 代码
- int 7ch 中断例程(安装程序)
- 分析
- ORG(Origin)
- 调用
- 1. 清屏
- 2. 设置前景色;
- 3. 设置背景色;
- 4. 向上滚动一行。
- 扩展实现
需求
安装一个新的 int 7ch
中断例程,为显示输出提供如下功能子程序。
功能 | 1. 清屏; 2. 设置前景色; 3. 设置背景色; 4. 向上滚动一行。 |
---|---|
参数 ah | 用 ah 寄存器传递功能号 : 0 表示清屏,1 表示设置前景色,2 表示设置背景色, 3 表示向上滚动一行; |
参数 al | 用 al 传送颜色值 ,(al) ∈ { 0,1,2,3,4,5,6,7 } 。用于 1 、2 号功能 |
代码
int 7ch 中断例程(安装程序)
assume cs:code
code segmentstart: ; ---------------- 安装(复制数据) ----------------mov ax,csmov ds,axmov si,offset i7ch ;设置 ds:si 指向源地址mov ax,0mov es,axmov di,200h ;设置 es:di 指向目的地址mov cx,offset i7chend -offset i7ch ;设置 cx为传输长度cld ;设置传输方向为正。movsb中si,di递增rep movsb ;重复复制数据次数由 cx 控制; ---------------- 安装(复制数据) ----------------; ----------------- 设置中断向量 -----------------mov ax,0mov es,ax ; 段地址 0cli ; 临时屏蔽中断mov word ptr es:[7ch*4],200h ; 设置【中断处理程序】的:偏移地址mov word ptr es:[7ch*4+2],0 ; 设置【中断处理程序】的:段地址sti ; 恢复中断响应; ----------------- 设置中断向量 -----------------mov ax,4c00hint 21h; =======================================================
; --------------------- 中断处理程序 --------------------
; 设置显示效果
; -------------------------------------------------------
; -------------------------------------------------------org 200h ; ORG 指定下面代码从一个特定地址开始编译i7ch: ; ======================================================= ; ------------------- 子程序 setscreen -----------------; 设置显示效果; -------------------------------------------------------; 参数: ah 功能号:0 表示清屏,1 表示设置前景色,2 表示设置背景色, 3 表示向上滚动一行;; 参数: al 颜色值。用于1、2号功能; 返回: 无; -------------------------------------------------------setscreen:jmp short set;; 0:21D 0:238 0:256 0:278 table dw sub1, sub2, sub3, sub4 ; d 0:202 209set:push bx ; 备份寄存器cmp ah,3 ; 判断功能号是否大于3ja sretmov bl,ahmov bh,0add bx,bx ; 根据 ah 中的功能号计算对应子程序在 table 表中的偏移call word ptr table[bx];sret: pop bx ; 还原寄存器iret ; 返回; -------------------- 子程序 setscreen -----------------; =======================================================; ======================================================= ; ---------------------- 子程序 sub1 --------------------; 清屏:; 将显存中当前屏幕中的字符设为空格符; -------------------------------------------------------; 参数: 无; 返回: 无; -------------------------------------------------------sub1:push bx ; 备份寄存器push cxpush esmov bx,0b800hmov es,bxmov bx,0mov cx,2000sub1s: mov byte ptr es:[bx],' ' ; 当前屏全设为空格add bx,2loop sub1spop es ; 备份寄存器pop cxpop bxret ; 返回; ---------------------- 子程序 sub1 --------------------; =======================================================; ======================================================= ; ---------------------- 子程序 sub2 --------------------; 设置前景色:设置当前屏幕中所有奇列的第0、1、2位(前景色); -------------------------------------------------------; 参数: 无; 返回: 无; -------------------------------------------------------sub2:push bx ; 备份寄存器push cxpush esmov bx,0b800hmov es,bxmov bx,1 ; 设置字符属性从 1 开始mov cx,2000sub2s: and byte ptr es:[bx],11111000b ; 清空前景色 0、1、2or es:[bx],al ; 应用 al 传来的颜色值add bx,2loop sub2spop es ; 备份寄存器pop cxpop bxret ; 返回; ---------------------- 子程序 sub2 --------------------; =======================================================; ======================================================= ; ---------------------- 子程序 sub3 --------------------; 设置背景色:设置当前屏幕中所有奇列的第4、5、6位(背景色); -------------------------------------------------------; 参数: 无; 返回: 无; -------------------------------------------------------sub3:push bx ; 备份寄存器push cxpush esmov cl,4shl al,cl mov bx,0b800hmov es,bxmov bx,1 ; 设置字符属性从 1 开始mov cx,2000sub3s: and byte ptr es:[bx],10001111b ; 清空 4 ~ 6or es:[bx],al ; 应用 al 传来的颜色值add bx,2loop sub3spop es ; 备份寄存器pop cxpop bxret ; 返回; ---------------------- 子程序 sub3 --------------------; =======================================================; ======================================================= ; ---------------------- 子程序 sub4 --------------------; 向上滚动一行:依次将第 n+1 行的内容复制到第n行处;最后一行为空。; -------------------------------------------------------; 参数: 无; 返回: 无; -------------------------------------------------------sub4:push cx ; 备份寄存器push sipush dipush espush dsmov si,0b800hmov es,simov ds,simov si,160 ; ds:si 指向第 n+1 行mov di,0 ; es:di 指向第 n 行cldmov cx,24 ; 共复制 24 行sub4s: push cxmov cx,160rep movsb ; 复制pop cxloop sub4smov cx,80mov si,0sub4s1:mov byte ptr [160*24+si],' 'add si,2loop sub4s1pop ds ; 备份寄存器pop espop dipop sipop cxret ; 返回; ---------------------- 子程序 sub4 --------------------; =======================================================i7chend: nop
; --------------------- 中断处理程序 --------------------
; =======================================================
code ends
end start
分析
本实验的主要练习的是使用直接定址表
存四个子程序的入口
地址。
其它部分之前都有现成代码可以复用:
- 核心业务
屏幕设置
部分第16章 16.4 已经实现可以直接用。 安装中断例程
参考 第13章-实验13子程序调用
参考 第11章-实验11 编写子程序
ORG(Origin)
在x86汇编语言中,ORG
指令的全称是Origin
,它指示汇编程序从指定地址开始放置汇编指令生成的机器码。在Intel 8086及后续的x86架构中,ORG
作为伪指令使用,用于设置汇编源代码中下一条指令的地址标记。
- 数据标号
table
的地址错误问题
当7ch
中断例程安装时table
记录的安装程序
中它所处的偏移位置
。
而中断例程
直正调用时call word ptr table[bx]
这table[bx]
取值肯定是错的。
所以这里可以用org
指定程序的起始地址。
ORG
在以下场景中需要用到ORG
指令:
- 确定程序起始执行地址,如设置引导扇区地址。
- 大型项目模块化编程时,给不同模块分配独立的内存地址空间。
- 插入或修改代码时,精确调整新代码在内存中的位置。
总的来说,ORG
用于在汇编过程中控制代码在内存中的布局和定位。
调用
1. 清屏
assume cs:code
code segmentstart: mov ah,0int 7chmov ax,4c00hint 21h
code ends
end start
2. 设置前景色;
assume cs:code
code segmentstart: mov ah,1mov al,3int 7chmov ax,4c00hint 21h
code ends
end start
3. 设置背景色;
assume cs:code
code segmentstart: mov ah,2mov al,6int 7chmov ax,4c00hint 21h
code ends
end start
4. 向上滚动一行。
assume cs:code
code segmentstart: mov ah,3int 7chmov ax,4c00hint 21h
code ends
end start
扩展实现
重写 int 09h
例程,实现热键设置屏幕:
热键 | F1 | F2 | F3 | F4 |
---|---|---|---|---|
功能 | 清屏 | 设置前景色 | 设置背景色 | 向上滚动一行 |
assume cs:code
stack segmentdb 128 dup(0)
stack endscode segmentstart: mov ax,stack ; 设置栈段和栈顶位置mov ss,axmov sp,128;----------- 打个小补丁。避免重复运行后搞丢 int9 导致输入瘫痪 -----------mov ax,0mov ds,axmov ax,ds:[2B4h]cmp ax,5350h ; 判断 ds:[2B4]=5053 则已安装过(值是调试运行查的)je ok; -------- 安装: 复制中断例程到目标内存 -------mov ax,cs ;设置 ds:si 指向源地址mov ds,axmov si,offset int9mov ax,0 ;设置 es:di 指向目的地址mov es,axmov di,2B4h mov cx,offset int9end-offset int9 ;设置 cx为传输长度cld ;设置传输方向为正。movsb中si,di递增rep movsb ;重复复制数据次数由 cx 控制; -------- 安装: 复制中断例程到目标内存 -------; ---------- 备份原 int9 入口到 [0:200~0203] ----------push es:[9*4]pop es:[2B0h]push es:[9*4+2]pop es:[2B0h+2h]; ---------- 备份原 int9 入口到 [0:200~0203] ----------; ---------- 设置中断向量表 ----------cli ; 临时屏蔽中断mov word ptr es:[9*4],2B4h ; 设置的偏移地址mov word ptr es:[9*4+2],0 ; 设置的段地址sti ; 恢复中断; ---------- 设置中断向量表 ----------ok: mov ax,4c00hint 21h; =======================================================
; --------------------- 子程序 int 9 -------------------
; 调用 F1=清屏; F2=设置前景色; F3=设置背景色; F4=向上滚动一行;
; -------------------------------------------------------
; 参数: 无
; 返回: 无
; -------------------------------------------------------
int9:push ax ; 备份寄存器push bxpush cxpush esmov ax,0b800hmov es,axin al,60h ; 从60h端口读取数据; 模拟 int 指令,用 call 调用原 int 9pushf ; 进入中断后 IF、TF已经是0 直接入栈即可call dword ptr cs:[2B0h] ; 调用原来的 int 9 中断例程cmp al,3Bh ; 判断是 F1je s1cmp al,3Ch ; 判断是 F2je s2 cmp al,3Dh ; 判断是 F3je s3cmp al,3Eh ; 判断是 F4je s4jmp int9rets1: mov ah,0 ; F1=清屏int 7chjmp int9rets2: mov ax,es:[1] ; F2=设置前景色and al,00000111binc almov ah,1int 7chjmp int9ret s3: mov ax,es:[1] ; F3=设置背景色and al,01110000bmov cl,4shr al,clinc aland al,00000111bmov ah,2int 7chjmp int9rets4: mov ah,3 ; F4=向上滚动一行int 7chint9ret:pop es ; 还原寄存器pop cxpop bxpop axiret ; 返回
int9end:nop; --------------------- 子程序 int 9 ------------------
; =======================================================
code ends
end start
这篇关于《汇编语言》- 读书笔记 - 第16章-实验16 编写包含多个功能子程序的中断例程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!