百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分析 > 正文

《汇编语言 第三版》实验17 - 编写包含多个功能子程序的中断例程

liebian365 2024-11-27 17:07 11 浏览 0 评论

?《汇编语言 第三版》实验17 - 编写包含多个功能子程序的中断例程

by bingshuizhilian

2020年2月26日

0x0 写在前面

  • 本实验需要在虚拟机中安装msdos并且使用虚拟软盘才能完成实践,可参考笔者另一篇文章《汇编语言》实验环境搭建来搭建实验环境
  • 书中介绍的内容以3.5英寸软盘为例,虽然这种存储介质已经过时了,但是原理是通用的,稍加改动就能应用到U盘或硬盘上

0x1 必知必会

  • 3.5英寸软盘
  • 3.5英寸软盘拥有上下两面,每面有80个磁道,每个磁道分为18个扇区,每个扇区的大小为512个字节
  • 对位于不同的磁道、面上的所有扇区进行统一编号,编号从0开始,一直到2879,称这个编号为逻辑扇区编号
  • 面号和磁道号从零开始编号,扇区号从1开始编号
  • 逻辑扇区号(LBA寻址方式)转为物理编号(CHS寻址方式)的方法 用描述性运算符int()表示取商,rem()表示取余数,则:
  • 逻辑扇区号 = (面号 * 80 + 磁道号) * 18 + 扇区号 - 1
  • 面号 = int(逻辑扇区号 / 1440)
  • 磁道号 = int(rem(逻辑扇区号 / 1440) / 18)
  • 扇区号 = rem(rem(逻辑扇区号 / 1440) / 18) + 1
  • BIOS提供的访问磁盘的中断例程int 13h常用的读写功能参数
    入口参数:
      -> (ah)=int i3h的功能号(2表示读扇区、3表示写扇区)
      -> (al)=读取/写入的扇区数
      -> (ch)=磁道号
      -> (cl)=扇区号
      -> (dh)=磁头号(对于软盘即面号,因为一个面用一个磁头来读写)
      -> (dl)=驱动器号(软驱从0开始,0:软驱A,1:软驱B;硬盘从80h开始,80h:硬盘C,81h:硬盘D) 
      -> es:bx在读时指向接收从扇区读入数据的内存区,在写时指向将写入磁盘的数据的内存区
    返回参数:
      -> 操作成功:(ah)=0,(al)=读取/写入的扇区数
      -> 操作失败:(ah)=错误码

0x2 源代码

所有源码均可在笔者的github仓库中(github.com/bingshuizhilian/assembly)查看并下载。

安装程序

安装程序源代码

assume cs:code, ss:stack
stack segment
db 128 dup (0)
stack ends

code segment
start:
mov ax, stack
mov ss, ax
mov sp, 128
push cs
pop ds
mov si, offset floppydiskrw
mov ax, 0
mov es, ax
mov di, 200h

; 安装中断程序
mov cx, offset floppydiskrwend - offset floppydiskrw
cld
rep movsb

; 设置中断向量
cli
mov word ptr es:[7ch*4], 200h
mov word ptr es:[7ch*4+2], 0
sti

; 主程序退出
mov ax, 4c00h
int 21h

; 名称:floppydiskrw
; 功能:7ch号中断处理程序,实现通过逻辑扇区号对软盘进行读写
; 参数:(1)用ah寄存器传递功能号:0表示读,1表示写
;           (2)用dx寄存器传递要读写的扇区的逻辑扇区号
;           (3)用es:bx指向存储读出数据或写入数据的内存区
; 返回:无
floppydiskrw:
cmp ah, 1
ja exit
push ax
push bx
push dx
push bp
mov bp, sp
; 计算:(逻辑扇区号 / 1440); 计算结果:(ax)=int(逻辑扇区号 / 1440),(dx)=rem(逻辑扇区号 / 1440)
mov ax, dx
xor dx, dx
mov bx, 1440
div bx
push ax         ; [bp-2]: int(逻辑扇区号 / 1440)
; 计算:rem(逻辑扇区号 / 1440) / 18; 计算结果:(ax)=int(rem(逻辑扇区号 / 1440) / 18),(dx)=rem(rem(逻辑扇区号 / 1440) / 18)
mov ax, dx
xor dx, dx
mov bx, 18
div bx

; int 13h参数填写
mov ch, al      ; ->磁道号(从0开始编号)
mov cl, dl      ; ->扇区号(从1开始编号)
inc cl
mov dh, [bp-2]   ; ->磁头号,即面号(从0开始编号)
mov dl, 0            ; 驱动器号(软驱从0开始,0:软驱A)
mov ah, [bp+7]  ; 功能号(int 13h的ah参数中:2为读取,3为写入,而本中断例程中0为读取,1为写入,故加2即可)
add ah, 2
mov al, 1       ; 读取/写入的扇区数
int 13h

pop ax
pop bp
pop dx
pop bx
pop ax
exit:
iret

floppydiskrwend:
nop

code ends
end start

安装程序要点分析

  • 安装程序,顾名思义是安装一个新的中断程序,中断号是0x7c,安装位置是内存中0:200处,关于安装新的中断例程的方法可参考 公众号主界面->技术->汇编->《汇编语言第三版》实验12-编写0号中断的处理程序
  • 用逻辑扇区号计算物理编号的核心算法是两个除法,第一个除法算出面号并入栈,因为面号一定为0或1,所以新入栈的内容的低字节就是面号,所以后面的 mov dh,[bp-2]代码就是将面号送入dh寄存器;第二个除法计算磁道号和扇区号并分别送入ch、cl寄存器;功能号是通过 mov ah,[bp+7]来获取的,因为程序入口参数使用ah寄存器传递功能号,而ax寄存器在程序开始处首先入栈了,观察ax和bp的入栈顺序可计算ax的内容可通过 ss:[bp+6]来获取,且可通过 ss:[bp+7]单独获取ah的值

应用程序

应用程序源代码

assume cs:code, ds:data, ss:stack
data segment
db 'This is a int 13h floppy disk read/write testcase, 20200217@harbin', 0
data ends

stack segment
db 128 dup (0)
stack ends

code segment
start:
mov ax, stack
mov ss, ax
mov sp, 128
mov ax, data
mov ds, ax

; 调用的int 7ch的参数说明
; 功能:7ch号中断处理程序,实现通过逻辑扇区号对软盘进行读写
; 参数:(1)用ah寄存器传递功能号:0表示读,1表示写;
(2)用dx寄存器传递要读写的扇区的逻辑扇区号;       (3)用es:bx指向存储读出数据或写入数据的内存区; int 7ch写入测试push dspop esxor bx, bxmov ah, 1mov dx, 1int 7chcall delay; int 7ch读取测试mov ax, 2000hmov es, axxor bx, bxmov ah, 0mov dx, 0int 7ch; 主程序退出mov ax, 4c00hint 21hdelay:push axpush dxmov dx, 20h  ; 大概3秒左右           mov ax, 0delays:sub ax, 1sbb dx, 0cmp ax, 0jne delayscmp dx, 0jne delayspop dxpop axretcode endsend start

应用程序要点分析

  • 将ex:bx指向数据段的预设字符串,调用此前安装的新的0x7c中断例程将字符串写入软盘的逻辑扇区1
  • 写入完成后延时一段时间,并把软盘的逻辑扇区0的内容读取到内存中2000:0处

0x3 验证程序运行结果

软盘内容

内存内容

运行结果说明

  • 截图中的41、42分别是笔者使用的安装程序和应用程序,输入名字代表运行它们
  • 虚拟的软盘文件中0h和200h分别是逻辑0、1扇区的起始位置,对比200h处运行前后的内容可得知成功将内存中的字符串数据写入到了虚拟的软盘文件中,因为读取或写入操作最低都是以一个扇区512字节为单位,所以也有可能会读取内存中一些无意义的数据到软盘中,可以忽略这些无意义数据
  • 内存0:1f0处是0x7c号中断的中断向量,这里起始的4个字节存储着7ch中断例程的地址,观察运行后的截图可发现此处存储内容为00020000,即cs=0h,ip=200h,正是我们安装程序的地址
  • 0:1f0的下一行即为0:200,41.exe运行后这个地址中就存储着安装程序的机器码
  • 观察运行2000:0处内容可发现软盘逻辑0扇区我们预设的32字节内容已经成功写入到内存中,此外可能与debug环境设置有关,2000:0起始处还有一些其它数据,然后才是我们读入的数据,这里也暂可忽略

0x4 总结

通过本实验,可以理解软盘等存储介质的低级io操作,实际上u盘或硬盘的低级操作均与此类似,只要改动下驱动器号即可实现,但注意实验时不要在真实系统环境中去写硬盘,以免将硬盘中的系统关键信息覆盖而引起异常甚至系统崩溃。


每篇技术文章的末尾,笔者都会分享非常短的文学性内容,可能是一句话,也可能是一首诗,和文章内容大都不相关,只为放松下神经和增加些许文艺气息。

本期分享: 投我以木桃,报之以琼瑶。

相关推荐

4万多吨豪华游轮遇险 竟是因为这个原因……

(观察者网讯)4.7万吨豪华游轮搁浅,竟是因为油量太低?据观察者网此前报道,挪威游轮“维京天空”号上周六(23日)在挪威近海发生引擎故障搁浅。船上载有1300多人,其中28人受伤住院。经过数天的调...

“菜鸟黑客”必用兵器之“渗透测试篇二”

"菜鸟黑客"必用兵器之"渗透测试篇二"上篇文章主要针对伙伴们对"渗透测试"应该如何学习?"渗透测试"的基本流程?本篇文章继续上次的分享,接着介绍一下黑客们常用的渗透测试工具有哪些?以及用实验环境让大家...

科幻春晚丨《震动羽翼说“Hello”》两万年星间飞行,探测器对地球的最终告白

作者|藤井太洋译者|祝力新【编者按】2021年科幻春晚的最后一篇小说,来自大家喜爱的日本科幻作家藤井太洋。小说将视角放在一颗太空探测器上,延续了他一贯的浪漫风格。...

麦子陪你做作业(二):KEGG通路数据库的正确打开姿势

作者:麦子KEGG是通路数据库中最庞大的,涵盖基因组网络信息,主要注释基因的功能和调控关系。当我们选到了合适的候选分子,单变量研究也已做完,接着研究机制的时便可使用到它。你需要了解你的分子目前已有哪些...

知存科技王绍迪:突破存储墙瓶颈,详解存算一体架构优势

智东西(公众号:zhidxcom)编辑|韦世玮智东西6月5日消息,近日,在落幕不久的GTIC2021嵌入式AI创新峰会上,知存科技CEO王绍迪博士以《存算一体AI芯片:AIoT设备的算力新选择》...

每日新闻播报(September 14)_每日新闻播报英文

AnOscarstatuestandscoveredwithplasticduringpreparationsleadinguptothe87thAcademyAward...

香港新巴城巴开放实时到站数据 供科技界研发使用

中新网3月22日电据香港《明报》报道,香港特区政府致力推动智慧城市,鼓励公私营机构开放数据,以便科技界研发使用。香港运输署21日与新巴及城巴(两巴)公司签署谅解备忘录,两巴将于2019年第3季度,开...

5款不容错过的APP: Red Bull Alert,Flipagram,WifiMapper

本周有不少非常出色的app推出,鸵鸟电台做了一个小合集。亮相本周榜单的有WifiMapper's安卓版的app,其中包含了RedBull的一款新型闹钟,还有一款可爱的怪物主题益智游戏。一起来看看我...

Qt动画效果展示_qt显示图片

今天在这篇博文中,主要实践Qt动画,做一个实例来讲解Qt动画使用,其界面如下图所示(由于没有录制为gif动画图片,所以请各位下载查看效果):该程序使用应用程序单窗口,主窗口继承于QMainWindow...

如何从0到1设计实现一门自己的脚本语言

作者:dong...

三年级语文上册 仿写句子 需要的直接下载打印吧

描写秋天的好句好段1.秋天来了,山野变成了美丽的图画。苹果露出红红的脸庞,梨树挂起金黄的灯笼,高粱举起了燃烧的火把。大雁在天空一会儿写“人”字,一会儿写“一”字。2.花园里,菊花争奇斗艳,红的似火,粉...

C++|那些一看就很简洁、优雅、经典的小代码段

目录0等概率随机洗牌:1大小写转换2字符串复制...

二年级上册语文必考句子仿写,家长打印,孩子照着练

二年级上册语文必考句子仿写,家长打印,孩子照着练。具体如下:...

一年级语文上 句子专项练习(可打印)

...

亲自上阵!C++ 大佬深度“剧透”:C++26 将如何在代码生成上对抗 Rust?

...

取消回复欢迎 发表评论: