《汇编语言》- 读书笔记 - 第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

相关文章

使用EasyPoi快速导出Word文档功能的实现步骤

《使用EasyPoi快速导出Word文档功能的实现步骤》EasyPoi是一个基于ApachePOI的开源Java工具库,旨在简化Excel和Word文档的操作,本文将详细介绍如何使用EasyPoi快速... 目录一、准备工作1、引入依赖二、准备好一个word模版文件三、编写导出方法的工具类四、在Export

JS纯前端实现浏览器语音播报、朗读功能的完整代码

《JS纯前端实现浏览器语音播报、朗读功能的完整代码》在现代互联网的发展中,语音技术正逐渐成为改变用户体验的重要一环,下面:本文主要介绍JS纯前端实现浏览器语音播报、朗读功能的相关资料,文中通过代码... 目录一、朗读单条文本:① 语音自选参数,按钮控制语音:② 效果图:二、朗读多条文本:① 语音有默认值:②

C#实现高性能拍照与水印添加功能完整方案

《C#实现高性能拍照与水印添加功能完整方案》在工业检测、质量追溯等应用场景中,经常需要对产品进行拍照并添加相关信息水印,本文将详细介绍如何使用C#实现一个高性能的拍照和水印添加功能,包含完整的代码实现... 目录1. 概述2. 功能架构设计3. 核心代码实现python3.1 主拍照方法3.2 安全HBIT

docker编写java的jar完整步骤记录

《docker编写java的jar完整步骤记录》在平常的开发工作中,我们经常需要部署项目,开发测试完成后,最关键的一步就是部署,:本文主要介绍docker编写java的jar的相关资料,文中通过代... 目录all-docker/生成Docker打包部署文件配置服务A的Dockerfile (a/Docke

录音功能在哪里? 电脑手机等设备打开录音功能的技巧

《录音功能在哪里?电脑手机等设备打开录音功能的技巧》很多时候我们需要使用录音功能,电脑和手机这些常用设备怎么使用录音功能呢?下面我们就来看看详细的教程... 我们在会议讨论、采访记录、课堂学习、灵感创作、法律取证、重要对话时,都可能有录音需求,便于留存关键信息。下面分享一下如何在电脑端和手机端上找到录音功能

Android实现图片浏览功能的示例详解(附带源码)

《Android实现图片浏览功能的示例详解(附带源码)》在许多应用中,都需要展示图片并支持用户进行浏览,本文主要为大家介绍了如何通过Android实现图片浏览功能,感兴趣的小伙伴可以跟随小编一起学习一... 目录一、项目背景详细介绍二、项目需求详细介绍三、相关技术详细介绍四、实现思路详细介绍五、完整实现代码

Python使用FastAPI实现大文件分片上传与断点续传功能

《Python使用FastAPI实现大文件分片上传与断点续传功能》大文件直传常遇到超时、网络抖动失败、失败后只能重传的问题,分片上传+断点续传可以把大文件拆成若干小块逐个上传,并在中断后从已完成分片继... 目录一、接口设计二、服务端实现(FastAPI)2.1 运行环境2.2 目录结构建议2.3 serv

Debian 13升级后网络转发等功能异常怎么办? 并非错误而是管理机制变更

《Debian13升级后网络转发等功能异常怎么办?并非错误而是管理机制变更》很多朋友反馈,更新到Debian13后网络转发等功能异常,这并非BUG而是Debian13Trixie调整... 日前 Debian 13 Trixie 发布后已经有众多网友升级到新版本,只不过升级后发现某些功能存在异常,例如网络转

基于Java和FFmpeg实现视频压缩和剪辑功能

《基于Java和FFmpeg实现视频压缩和剪辑功能》在视频处理开发中,压缩和剪辑是常见的需求,本文将介绍如何使用Java结合FFmpeg实现视频压缩和剪辑功能,同时去除数据库操作,仅专注于视频处理,需... 目录引言1. 环境准备1.1 项目依赖1.2 安装 FFmpeg2. 视频压缩功能实现2.1 主要功

使用Python实现无损放大图片功能

《使用Python实现无损放大图片功能》本文介绍了如何使用Python的Pillow库进行无损图片放大,区分了JPEG和PNG格式在放大过程中的特点,并给出了示例代码,JPEG格式可能受压缩影响,需先... 目录一、什么是无损放大?二、实现方法步骤1:读取图片步骤2:无损放大图片步骤3:保存图片三、示php