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

相关文章

Java使用Thumbnailator库实现图片处理与压缩功能

《Java使用Thumbnailator库实现图片处理与压缩功能》Thumbnailator是高性能Java图像处理库,支持缩放、旋转、水印添加、裁剪及格式转换,提供易用API和性能优化,适合Web应... 目录1. 图片处理库Thumbnailator介绍2. 基本和指定大小图片缩放功能2.1 图片缩放的

深度解析Spring Security 中的 SecurityFilterChain核心功能

《深度解析SpringSecurity中的SecurityFilterChain核心功能》SecurityFilterChain通过组件化配置、类型安全路径匹配、多链协同三大特性,重构了Spri... 目录Spring Security 中的SecurityFilterChain深度解析一、Security

MySQL多实例管理如何在一台主机上运行多个mysql

《MySQL多实例管理如何在一台主机上运行多个mysql》文章详解了在Linux主机上通过二进制方式安装MySQL多实例的步骤,涵盖端口配置、数据目录准备、初始化与启动流程,以及排错方法,适用于构建读... 目录一、什么是mysql多实例二、二进制方式安装MySQL1.获取二进制代码包2.安装基础依赖3.清

Java实现预览与打印功能详解

《Java实现预览与打印功能详解》在Java中,打印功能主要依赖java.awt.print包,该包提供了与打印相关的一些关键类,比如PrinterJob和PageFormat,它们构成... 目录Java 打印系统概述打印预览与设置使用 PageFormat 和 PrinterJob 类设置页面格式与纸张

MySQL 8 中的一个强大功能 JSON_TABLE示例详解

《MySQL8中的一个强大功能JSON_TABLE示例详解》JSON_TABLE是MySQL8中引入的一个强大功能,它允许用户将JSON数据转换为关系表格式,从而可以更方便地在SQL查询中处理J... 目录基本语法示例示例查询解释应用场景不适用场景1. ‌jsON 数据结构过于复杂或动态变化‌2. ‌性能要

JAVA中安装多个JDK的方法

《JAVA中安装多个JDK的方法》文章介绍了在Windows系统上安装多个JDK版本的方法,包括下载、安装路径修改、环境变量配置(JAVA_HOME和Path),并说明如何通过调整JAVA_HOME在... 首先去oracle官网下载好两个版本不同的jdk(需要登录Oracle账号,没有可以免费注册)下载完

Qt使用QSqlDatabase连接MySQL实现增删改查功能

《Qt使用QSqlDatabase连接MySQL实现增删改查功能》这篇文章主要为大家详细介绍了Qt如何使用QSqlDatabase连接MySQL实现增删改查功能,文中的示例代码讲解详细,感兴趣的小伙伴... 目录一、创建数据表二、连接mysql数据库三、封装成一个完整的轻量级 ORM 风格类3.1 表结构

mysql表操作与查询功能详解

《mysql表操作与查询功能详解》本文系统讲解MySQL表操作与查询,涵盖创建、修改、复制表语法,基本查询结构及WHERE、GROUPBY等子句,本文结合实例代码给大家介绍的非常详细,感兴趣的朋友跟随... 目录01.表的操作1.1表操作概览1.2创建表1.3修改表1.4复制表02.基本查询操作2.1 SE

Golang如何用gorm实现分页的功能

《Golang如何用gorm实现分页的功能》:本文主要介绍Golang如何用gorm实现分页的功能方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录背景go库下载初始化数据【1】建表【2】插入数据【3】查看数据4、代码示例【1】gorm结构体定义【2】分页结构体

Java Web实现类似Excel表格锁定功能实战教程

《JavaWeb实现类似Excel表格锁定功能实战教程》本文将详细介绍通过创建特定div元素并利用CSS布局和JavaScript事件监听来实现类似Excel的锁定行和列效果的方法,感兴趣的朋友跟随... 目录1. 模拟Excel表格锁定功能2. 创建3个div元素实现表格锁定2.1 div元素布局设计2.