《汇编语言》- 读书笔记 - 第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编译生成多个.class文件的原理和作用

《Java编译生成多个.class文件的原理和作用》作为一名经验丰富的开发者,在Java项目中执行编译后,可能会发现一个.java源文件有时会产生多个.class文件,从技术实现层面详细剖析这一现象... 目录一、内部类机制与.class文件生成成员内部类(常规内部类)局部内部类(方法内部类)匿名内部类二、

Java实现文件图片的预览和下载功能

《Java实现文件图片的预览和下载功能》这篇文章主要为大家详细介绍了如何使用Java实现文件图片的预览和下载功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... Java实现文件(图片)的预览和下载 @ApiOperation("访问文件") @GetMapping("

SpringKafka消息发布之KafkaTemplate与事务支持功能

《SpringKafka消息发布之KafkaTemplate与事务支持功能》通过本文介绍的基本用法、序列化选项、事务支持、错误处理和性能优化技术,开发者可以构建高效可靠的Kafka消息发布系统,事务支... 目录引言一、KafkaTemplate基础二、消息序列化三、事务支持机制四、错误处理与重试五、性能优

SpringIntegration消息路由之Router的条件路由与过滤功能

《SpringIntegration消息路由之Router的条件路由与过滤功能》本文详细介绍了Router的基础概念、条件路由实现、基于消息头的路由、动态路由与路由表、消息过滤与选择性路由以及错误处理... 目录引言一、Router基础概念二、条件路由实现三、基于消息头的路由四、动态路由与路由表五、消息过滤

Spring Boot 3.4.3 基于 Spring WebFlux 实现 SSE 功能(代码示例)

《SpringBoot3.4.3基于SpringWebFlux实现SSE功能(代码示例)》SpringBoot3.4.3结合SpringWebFlux实现SSE功能,为实时数据推送提供... 目录1. SSE 简介1.1 什么是 SSE?1.2 SSE 的优点1.3 适用场景2. Spring WebFlu

基于SpringBoot实现文件秒传功能

《基于SpringBoot实现文件秒传功能》在开发Web应用时,文件上传是一个常见需求,然而,当用户需要上传大文件或相同文件多次时,会造成带宽浪费和服务器存储冗余,此时可以使用文件秒传技术通过识别重复... 目录前言文件秒传原理代码实现1. 创建项目基础结构2. 创建上传存储代码3. 创建Result类4.

Python+PyQt5实现多屏幕协同播放功能

《Python+PyQt5实现多屏幕协同播放功能》在现代会议展示、数字广告、展览展示等场景中,多屏幕协同播放已成为刚需,下面我们就来看看如何利用Python和PyQt5开发一套功能强大的跨屏播控系统吧... 目录一、项目概述:突破传统播放限制二、核心技术解析2.1 多屏管理机制2.2 播放引擎设计2.3 专

一文详解SpringBoot响应压缩功能的配置与优化

《一文详解SpringBoot响应压缩功能的配置与优化》SpringBoot的响应压缩功能基于智能协商机制,需同时满足很多条件,本文主要为大家详细介绍了SpringBoot响应压缩功能的配置与优化,需... 目录一、核心工作机制1.1 自动协商触发条件1.2 压缩处理流程二、配置方案详解2.1 基础YAML

基于Flask框架添加多个AI模型的API并进行交互

《基于Flask框架添加多个AI模型的API并进行交互》:本文主要介绍如何基于Flask框架开发AI模型API管理系统,允许用户添加、删除不同AI模型的API密钥,感兴趣的可以了解下... 目录1. 概述2. 后端代码说明2.1 依赖库导入2.2 应用初始化2.3 API 存储字典2.4 路由函数2.5 应

使用PyTorch实现手写数字识别功能

《使用PyTorch实现手写数字识别功能》在人工智能的世界里,计算机视觉是最具魅力的领域之一,通过PyTorch这一强大的深度学习框架,我们将在经典的MNIST数据集上,见证一个神经网络从零开始学会识... 目录当计算机学会“看”数字搭建开发环境MNIST数据集解析1. 认识手写数字数据库2. 数据预处理的