《汇编语言》- 读书笔记 - 第16章-实验16 编写包含多个功能子程序的中断例程

本文主要是介绍《汇编语言》- 读书笔记 - 第16章-实验16 编写包含多个功能子程序的中断例程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《汇编语言》- 读书笔记 - 第16章-实验16 编写包含多个功能子程序的中断例程

  • 需求
  • 代码
    • int 7ch 中断例程(安装程序)
    • 分析
      • ORG(Origin)
  • 调用
    • 1. 清屏
    • 2. 设置前景色;
    • 3. 设置背景色;
    • 4. 向上滚动一行。
  • 扩展实现

需求

安装一个新的 int 7ch 中断例程,为显示输出提供如下功能子程序。

功能1. 清屏;
2. 设置前景色;
3. 设置背景色;
4. 向上滚动一行。
参数 ahah 寄存器传递功能号0 表示清屏,1 表示设置前景色,2 表示设置背景色, 3 表示向上滚动一行;
参数 alal 传送颜色值(al){ 0,1,2,3,4,5,6,7 }
用于12号功能

代码

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	颜色值。用于12号功能; 返回:; -------------------------------------------------------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 --------------------; 设置前景色:设置当前屏幕中所有奇列的第012位(前景色); -------------------------------------------------------; 参数:; 返回:; -------------------------------------------------------sub2:push bx			; 备份寄存器push cxpush esmov bx,0b800hmov es,bxmov bx,1						; 设置字符属性从 1 开始mov cx,2000sub2s:	and byte ptr es:[bx],11111000b	; 清空前景色 012or es:[bx],al					; 应用 al 传来的颜色值add bx,2loop sub2spop es			; 备份寄存器pop cxpop	bxret				; 返回; ---------------------- 子程序 sub2 --------------------; =======================================================; =======================================================	; ---------------------- 子程序 sub3 --------------------; 设置背景色:设置当前屏幕中所有奇列的第456位(背景色); -------------------------------------------------------; 参数:; 返回:; -------------------------------------------------------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

分析

本实验的主要练习的是使用直接定址表存四个子程序的入口地址。

其它部分之前都有现成代码可以复用:

  1. 核心业务 屏幕设置部分第16章 16.4 已经实现可以直接用。
  2. 安装中断例程 参考 第13章-实验13
  3. 子程序调用 参考 第11章-实验11 编写子程序

在这里插入图片描述

ORG(Origin)

在x86汇编语言中,ORG指令的全称是Origin,它指示汇编程序从指定地址开始放置汇编指令生成的机器码。在Intel 8086及后续的x86架构中,ORG作为伪指令使用,用于设置汇编源代码中下一条指令的地址标记。

  • 数据标号 table 的地址错误问题
    7ch 中断例程安装时 table 记录的安装程序中它所处的偏移位置
    中断例程 直正调用时 call word ptr table[bx] table[bx] 取值肯定是错的。
    所以这里可以用 org 指定程序的起始地址。

ORG在以下场景中需要用到ORG指令:

  1. 确定程序起始执行地址,如设置引导扇区地址。
  2. 大型项目模块化编程时,给不同模块分配独立的内存地址空间。
  3. 插入或修改代码时,精确调整新代码在内存中的位置。

总的来说,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 例程,实现热键设置屏幕:

热键F1F2F3F4
功能清屏设置前景色设置背景色向上滚动一行
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 编写包含多个功能子程序的中断例程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/777359

相关文章

第10章 中断和动态时钟显示

第10章 中断和动态时钟显示 从本章开始,按照书籍的划分,第10章开始就进入保护模式(Protected Mode)部分了,感觉从这里开始难度突然就增加了。 书中介绍了为什么有中断(Interrupt)的设计,中断的几种方式:外部硬件中断、内部中断和软中断。通过中断做了一个会走的时钟和屏幕上输入字符的程序。 我自己理解中断的一些作用: 为了更好的利用处理器的性能。协同快速和慢速设备一起工作

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

Spring框架5 - 容器的扩展功能 (ApplicationContext)

private static ApplicationContext applicationContext;static {applicationContext = new ClassPathXmlApplicationContext("bean.xml");} BeanFactory的功能扩展类ApplicationContext进行深度的分析。ApplicationConext与 BeanF

JavaFX应用更新检测功能(在线自动更新方案)

JavaFX开发的桌面应用属于C端,一般来说需要版本检测和自动更新功能,这里记录一下一种版本检测和自动更新的方法。 1. 整体方案 JavaFX.应用版本检测、自动更新主要涉及一下步骤: 读取本地应用版本拉取远程版本并比较两个版本如果需要升级,那么拉取更新历史弹出升级控制窗口用户选择升级时,拉取升级包解压,重启应用用户选择忽略时,本地版本标志为忽略版本用户选择取消时,隐藏升级控制窗口 2.

如何编写Linux PCIe设备驱动器 之二

如何编写Linux PCIe设备驱动器 之二 功能(capability)集功能(capability)APIs通过pci_bus_read_config完成功能存取功能APIs参数pos常量值PCI功能结构 PCI功能IDMSI功能电源功率管理功能 功能(capability)集 功能(capability)APIs int pcie_capability_read_wo

Android 10.0 mtk平板camera2横屏预览旋转90度横屏拍照图片旋转90度功能实现

1.前言 在10.0的系统rom定制化开发中,在进行一些平板等默认横屏的设备开发的过程中,需要在进入camera2的 时候,默认预览图像也是需要横屏显示的,在上一篇已经实现了横屏预览功能,然后发现横屏预览后,拍照保存的图片 依然是竖屏的,所以说同样需要将图片也保存为横屏图标了,所以就需要看下mtk的camera2的相关横屏保存图片功能, 如何实现实现横屏保存图片功能 如图所示: 2.mtk

Spring+MyBatis+jeasyui 功能树列表

java代码@EnablePaging@RequestMapping(value = "/queryFunctionList.html")@ResponseBodypublic Map<String, Object> queryFunctionList() {String parentId = "";List<FunctionDisplay> tables = query(parent

《x86汇编语言:从实模式到保护模式》视频来了

《x86汇编语言:从实模式到保护模式》视频来了 很多朋友留言,说我的专栏《x86汇编语言:从实模式到保护模式》写得很详细,还有的朋友希望我能写得更细,最好是覆盖全书的所有章节。 毕竟我不是作者,只有作者的解读才是最权威的。 当初我学习这本书的时候,只能靠自己摸索,网上搜不到什么好资源。 如果你正在学这本书或者汇编语言,那你有福气了。 本书作者李忠老师,以此书为蓝本,录制了全套视频。 试

STM32(十一):ADC数模转换器实验

AD单通道: 1.RCC开启GPIO和ADC时钟。配置ADCCLK分频器。 2.配置GPIO,把GPIO配置成模拟输入的模式。 3.配置多路开关,把左面通道接入到右面规则组列表里。 4.配置ADC转换器, 包括AD转换器和AD数据寄存器。单次转换,连续转换;扫描、非扫描;有几个通道,触发源是什么,数据对齐是左对齐还是右对齐。 5.ADC_CMD 开启ADC。 void RCC_AD