手机版 | 登陆 | 注册 | 留言 | 设首页 | 加收藏
当前位置: 网站首页 > 音响设备技术 > 文章 当前位置: 音响设备技术 > 文章

汇编自启动可装载运行其它小程序操作系统

时间:2009-08-12    点击: 次    来源:本站原创    作者:佚名 - 小 + 大

实验一   最简单的监控程序

一实验题目与要求

监控程序是最早的、最简单的操作系统。监控程序最基本的功能就是启动程序的执行和处理程序的结束。在这个实验中,我们给前面的自启程序(参见附录)增加一点功能,使之成为一个最简单的监控程序:该自启程序启动执行后,在屏幕上显示一个简单的菜单:

  1. 执行程序1
  2. 执行程序2
  3. 退出

然后,等待并接收用户的选择,并加载、启动相应的程序1或2,当程序1或2结束后,回到该自启程序,重复显示菜单并接收新的选择,如此重复……
其中,程序1和程序2是由你预先编制好并与自启程序在同一张软盘上连续、静态地存放着的用户程序。它们的功能可以很简单,如help、echo、helloworld等。
不要求中文输入和显示,菜单项可以是具体的程序名,如直接用 help、echo、shutdown等。

二总的设计思想、环境语言、工具等

工具:

二进制文件编辑器(010Editor.exe),虚拟机(Vmware),汇编程序编辑器(RadASM),编译工具(NASM)

环境语言:

windowsXP,汇编

总的设计思想:

  1. 分模块:首先要有一个引导程序来带领计算机进入监控程序,所以引导程序负责加载监控程序进内存并把控制权交给监控程序。监控程序负责在屏幕上打印菜单并接受用户输入,并根据用户输入所相应程序加载进内存并执行它,执行完后返回监控程序。所以把实验程序分成三大模块:引导程序,监控程序,各小程序。
  2. 攻难点:本实验要攻破的难点有:把三大模块数据准确放到软盘指定位置、准确地从软盘指定位置读数据到内存指定位置、运行内存中指定位置的程序。为了做到准确,每个程序占一个扇区(512字节),分别放在软盘中的第0面0磁道第1个扇区(引导程序),第2个扇区(监控程序),第3~n个扇区(各种小程序)。读到内存中的地址分别为07c00h(引导程序),07e00h(监控程序),08100h(各种小程序)
  3. 分步骤:用RadASM编写四个程序(引导程序,监控程序,程序1,程序2),并用NASM编译成二进制文件,用010Editor.exe新建一个空二进制文件,把之前编译好的四个二进制文件按顺序放进(插入)新建的二进制文件中的相应位置中(引导程序一定要在最前面),并保存(命名为LisaSystem)。用Vmware中虚拟机的软驱映射到这个二进制文件(LisaSystem)。启动Vmware中的虚拟机, 测试。

三数据结构与模块说明

本实验分三大模块:引导程序,监控程序,其他小程序,它们的结构和关系如下图
1
其中,最主要的是监控程序,监控程序也分几大模块。监控程序的模块结构如下图:
2

四源程序(要有适当注释)

1、LisaBoot.asm

org  07c00h
mov       ax,cs
mov       ds,ax
mov       es,ax
call LoadData
jmp        07e00h    ;进入监控程序
;******************利用BIOS中断int 13h来读软盘************************
LoadData:
xor ah,ah       ;复位软驱
xor dl,dl ;
int   13h        ;
mov       ch,0 ;要读的柱面(磁道)号:0
mov       dh,0 ;要读的磁头号:0
mov       al,1  ;要读的扇区数:1
mov      cl,2  ;要读数据的起始扇区号:2
mov       dl,0  ;要读的驱动器号:0(A盘即软盘)
mov       bx,07e00h      ;把监控程序加载到内存07e00h位置
mov       ah,02h     ;
int   13h
ret
;******************LoadData结束************************
times 510-($-$$) db 0
dw 0xaa55

2、LisaTest.asm

org  07e00h
mov       ax,cs
mov       ds,ax
mov       es,ax
call DispStr
jmp        $
DispStr:
mov       ax,BootMessage
mov       bp,ax
mov       cx,16      ;16个字符
mov       ax,01301h
mov       bx,000ch
mov      dx,0        ;第一行打印字符串
int   10h
ret
BootMessage:  db "Hello,OS World!"
times 512-($-$$) db 0    ;填满整个扇区

3、MonitorMenuMode.asm

org 07e00h
mov       ax,cs
mov       ds,ax
mov       es,ax

;******************显示菜单************************
DisMenu:
mov        ah,06h
xor         al,al
xor         bh,bh
int   10h         ;清窗口

mov       cx,18      ;18个字符
mov       ax,p1
mov       dx,0000h ;第0行打印字符串
call DispStr
mov       ax,p2
mov       dx,0100h ;第1行打印字符串
call DispStr
mov       cx,7
mov       ax,pexit
mov       dx,0200h ;第2行打印字符串
call DispStr

mov       cx,54
mov       ax,inMsg
mov       dx,0300h ;第3行打印字符串
call DispStr

;******************接受用户输入************************
Selete:
xor         ah,ah
int           16h
sub         al,30h
cmp        al,1
jz            RightInput      ;选择程序1
cmp        al,2
jz            RightInput      ;选择程序2
cmp        al,3
jnz          DisMenu        ;无效输入
;退出系统
mov       cx,19
mov       ax,exitMsg
mov       dx,0500h ;第5行打印字符串
call DispStr
SureExit:
xor         ah,ah
int           16h
cmp        al,'n'
jz            DisMenu        ;不退出
cmp        al,'y'       
jnz          SureExit  ;无效输入

;******************退出************************
mov       ax,5300h
xor        bx,bx
int          15h

mov      ax,5301h
xor       bx,bx
int        15h

mov      ax,530eh
xor       bx,bx
mov      cx,101h
int        15h

mov      ax,530fh
mov      bx,1
mov      cx,bx
int        15h

mov      ax,5308h
mov      bx,1
mov      cx,bx
int        15h

mov      ax,5307h
mov      bx,1
mov      cx,3
int        15h

;******************加载程序并运行************************
RightInput:
add         al,2
call  LoadingPro     ;加载程序进内存

;mov              ah,06h
;xor        al,al
;xor        bh,bh
;int 10h         ;清窗口
jmp         08100h           ;运行程序
jmp         DisMenu

;******************加载程序进内存************************
;入口参数:al要读的起始扇区号
;出口参数:无
LoadingPro:
xor ah,ah              ;
xor dl,dl        ;复位软驱
int   13h               ;
mov        cl,al        ;要读数据的起始扇区号
mov       bx,08100h      ;把监控程序加载到内存08100h位置
mov       ch,0        ;要读的柱面(磁道)号:0
mov       al,1         ;要读的扇区数:1
mov       dl,0         ;要读的驱动器号:0(A盘即软盘)
mov        dh,0        ;要读的磁头号:0
mov       ah,02h            ;
int   13h
ret

;******************显示字符串************************
;入口参数:es:ax字符串地址,cx字符串长度(字符数),dx显示位置(dh行dl列)
;出口参数:无
DispStr:
mov       bp,ax
mov       ax,01301h
mov       bx,000ch
int   10h
ret

;**数据区**
p1:          db "(1)Run Program One"
p2:          db "(2)Run Program Two"
pexit:       db "(3)Exit"
inMsg:     db "Please enter the number of the program you want to run"
exitMsg:db "Sure to exit? (y/n)"
;loadPro:db "Loading Program..."  ;测试用的
;runPro: db "Running Program..."  ;测试用的
;println:db ""                                      ;测试用的
times      512-($-$$) db 0     ;填满整个扇区

4、p1.asm

org 08100h
mov       ax,cs
mov       ds,ax
mov       es,ax

mov       cx,70
mov       ax,p1Message
mov       dx,0700h ;第7行打印字符串
call DispStr
mov        cx,33
mov        ax,println
mov        dx,0900h ;第9行打印字符串
call  DispStr
xor         ah,ah
int           16h
jmp         07e00h           ;退出时返回监控程序

;******************显示字符串************************
;入口参数:es:ax字符串地址,cx字符串长度(字符数),dx显示位置(dh行dl列)
;出口参数:无
DispStr:
mov       bp,ax
mov       ax,01301h
mov       bx,000ch
int   10h
ret
p1Message:     db "Hello,Lisa,Welcom to OS World!",10,13,"Now you are running the first program."
println:           db "press any key to exit the program"
times 512-($-$$) db 0    ;填满整个扇区

5、p2.asm

org 08100h
mov       ax,cs
mov       ds,ax
mov       es,ax

mov       cx,71
mov       ax,p1Message
mov       dx,0700h ;第7行打印字符串
call DispStr
mov        cx,33
mov        ax,println
mov        dx,0900h ;第9行打印字符串
call  DispStr
xor         ah,ah
int           16h
jmp         07e00h           ;退出时返回监控程序

;******************显示字符串************************
;入口参数:es:ax字符串地址,cx字符串长度(字符数),dx显示位置(dh行dl列)
;出口参数:无
DispStr:
mov       bp,ax
mov       ax,01301h
mov       bx,000ch
int   10h
ret
p1Message:     db "Hello,Lisa,Welcom to OS World!",10,13,"Now you are running the second program."
println:           db "press any key to exit the program"
times 512-($-$$) db 0    ;填满整个扇区

6、MonitorCmdMode.asm

org 07e00h
mov       ax,cs
mov       ds,ax
mov       es,ax

;******************显示命令提示符************************
DisCmd:
mov        ax,0600h
xor         bh,bh
int   10h         ;清窗口
mov        cx,80
mov        ax,inCmd
xor         dx,dx
clearing:
push       cx
mov        cx,1
call  DispStr
inc          dl
pop         cx
loop clearing   ;清命令行

pop         dx
mov       cx,5 ;18个字符
mov       ax,inCmd
mov       dx,0000h ;第0行打印字符串
call DispStr
;******************接受用户输入************************
Selete:
mov        si,0
input:
mov        ah,00h
int           16h
cmp        al,0dh      ;输入回车结束
jz            endinput
cmp        al,08h
jnz          notbackSpace ;撤消输入
cmp        si,0
jz            input
dec         si
mov        al,' '
mov        [cmd+si],al
mov        cx,si
inc          cx
mov        ax,cmd
mov        dx,0005h
call  DispStr   ;显示用户的输入
jmp         input
notbackSpace:
mov        [cmd+si],al
inc          si
mov        cx,si
mov        ax,cmd
mov        dx,0005h
call  DispStr   ;显示用户的输入
jmp         input
endinput:        ;输入结束
mov        cx,si       ;比较字符长度
cmp        si,4
jz            cmpexit
cmp        si,5
jz            cmpp1
cmp        si,6
jz            cmpp2
jmp         DisCmd
cmpexit:
mov        si,cmd
mov        di,pexit
rep          cmpsb
jnz          DisCmd
jmp         Exit
cmpp1:
mov        si,cmd
mov        di,p1
rep          cmpsb
jnz          DisCmd
mov        al,1
jmp         RightInput
cmpp2:
mov        si,cmd
mov        di,p2
rep          cmpsb
jnz          DisCmd
mov        al,2
jmp         RightInput

;退出系统
Exit:
mov       cx,19
mov       ax,exitMsg
mov       dx,0500h ;第5行打印字符串
call DispStr
SureExit:
xor         ah,ah
int           16h
cmp        al,'n'
jz            DisCmd          ;不退出
cmp        al,'y'       
jnz          SureExit  ;无效输入

;******************退出************************
mov       ax,5300h  
xor bx,bx  
int   15h

mov      ax,5301h  
xor       bx,bx  
int        15h  

mov      ax,530eh  
xor       bx,bx  
mov      cx,101h  
int        15h  

mov      ax,530fh  
mov      bx,1  
mov      cx,bx  
int        15h  

mov      ax,5308h  
mov      bx,1  
mov      cx,bx  
int        15h  

mov      ax,5307h  
mov      bx,1  
mov      cx,3  
int        15h  

;******************加载程序并运行************************
RightInput:
add         al,2
call  LoadingPro     ;加载程序进内存

;mov              ah,06h
;xor        al,al
;xor        bh,bh
;int 10h         ;清窗口
jmp         08100h           ;运行程序
jmp         DisCmd

;******************加载程序进内存************************
;入口参数:al要读的起始扇区号
;出口参数:无
LoadingPro:
xor ah,ah              ;
xor dl,dl        ;复位软驱
int   13h               ;
mov        cl,al        ;要读数据的起始扇区号
mov       bx,08100h      ;把监控程序加载到内存08100h位置
mov       ch,0        ;要读的柱面(磁道)号:0
mov       al,1         ;要读的扇区数:1
mov       dl,0         ;要读的驱动器号:0(A盘即软盘)
mov        dh,0        ;要读的磁头号:0
mov       ah,02h            ;
int   13h
ret

;******************显示字符串************************
;入口参数:es:ax字符串地址,cx字符串长度(字符数),dx显示位置(dh行dl列)
;出口参数:无
DispStr:
mov       bp,ax
mov       ax,01301h
mov       bx,000ch
int   10h
ret

;**数据区**
blank:      db " "
p1:          db "first"
p2:          db "second"
pexit:       db "exit"
inCmd:    db "Lisa>"
exitMsg:db "Sure to exit? (y/n)"
cmd:       db ' '
times      512-($-$$) db 0;填满整个扇区

五运行结果与运行情况

1、攻破难关一,加载程序入内存,然后运行。

把显示"Hello,OS World!"的代码变成一个独立的程序(LisaTest.asm)编译后(LisaTest.bin)放在软盘的第2个扇区,引导程序(LisaBoot.asm)加载它到内存07e00h的位置,然后用jmp 07e00h跳过去,从下面的运行结果可知,跳转成功,但显示的是乱码。
3
这是怎么回事?查看了一下LisaTest.asm,开头处没有org 07e00h 这一句,这句和乱码有什么关系?加进去试了一下,一句漂亮的” Hello,OS World!”显示了出来,这就怪了。用010Editor.exe查看了一个LisaTest.bin,发现第14个字节由原来的00h变成后来的7eh,这就是问题所在了,原来org 07e00h这句代码是告诉编译器这段代码将要被加载到内存偏移地址07e00h处的。成功的运行结果如下:
4

2、攻破难关二,实现并运行监控程序。

难关一通过,只要把LisaTest.asm改成监控程序(MonitorMenuMode.asm)就没问题了。
运行结果如下:
5

3、攻破难关三,加载并运行小程序

进入监控程序后,提示说输入你想要运行的程序号。
输入1,结果如下。再按一下键盘,又回到了上面那个画面,说明监控程序正确加载了程序1,退出程序1时又成功返回了监控程序。以下是运行了p1.asm的结果
6
输入2,结果如下。再按一下键盘,又回到了上面那个画面,说明监控程序正确加载了程序2,退出程序2时又成功返回了监控程序。以下是运行了p2.asm的结果
7

4、攻破难关四,退出(关机)

其实关掉电源就好了,但心理不爽,明明有个“Exit”选项却不用,这不正常。但汇编没有关机指令,所以要实现这一点还真是煞费苦心,具体方法见(MonitorMenuMode.asm中退出部分)。下面是输入3后的运行结果:
8
输入y当然就关机了,输入n又回到监控程序最开始的页面,输入其它无效果。到此,这个最简单的监控程序告一段落了。

六自我评析与总结

1、自我打分

80分

2、为你哪些地方做得比较好或比较出色

思路、模块、结构很清晰;
目标明确、重点突出、难点攻破;

3、为你哪些地方做得不够好、哪些地方可以做得更好、进一步的工作

做得不够好:

  1. 规定每个程序占一个扇区,这样做灵活性极差。因为有的程序可能一个扇区装不下,安全性极差。
  2. 内存管理粗糙,所有小程序都放在08100h处,每运行一次程序都要重新加载一次,并覆盖掉原来的内存,这样使得内存使用效率不高,且浪费时间。
  3. 一次只能运行一个程序,万一程序运行一半死掉了,系统也就崩溃了。

可以的做得更好和进一步工作:

  1. 可以尝试内存分段:划出一块内存存放分段信息(大小与具体情况有关),监控程序主要从这一块内存获得内存的分配情况。段信息长度固定(与具体情况有关),主要信息包括:段起始地址、段长度(段界限)。这样,内存的使用会更有效率。
  2. 为软盘引入文件系统:划出软盘的一块存储区域存放文件的索引,采用链似结构,方便文件的读取和修改(类似FAT文件系统),以一个扇区为最小单位,这样就可以放入大于一个扇区的程序。
  3. 引入进程的概念。

4、实验得到的收获

  1. 对软盘的结构有所了解,知道了软盘有一个盘片,两面,每面80磁道, 每磁道18扇区^_^
  2. 对BIOS的各中断有所了解,并灵活能应用^_^
  3. 对系统的自启过程有了深入的认识^_^
  4. 初尝了亲手制作一个能运行程序的监控程序的快乐,对以后的学习充满信心^_^
  5. 收集了很不错的工具,像010Editor,RadASM等,为以后的实验准备条件^_^
  6. 尝试着了解文件系统、保护模式的概念,认识到引入这些概念的重要性。如果像我本次实验这样来管理存储和运行程序,还不累死人,气死人?^_^

5、本题的其他方法

把监控程序的初始菜单改成模式选择:菜单模式、命令行模式。菜单模式如以上所做的,命令行模式则如进一步(可选)要求。还可加入滚屏效果。

6、验题的评价和改进意见

暂时没有想到。

进一步(可选):

要求:
实现一个命令解释器,代替上述的菜单选择方式。即自启程序启动后,不是显示上述菜单,而是显示命令提示符(如DOS中的 >   ),等待用户键入命令,用户敲入相应命令后则加载、启动相应的命令程序,程序执行结束后,再显示命令行提示符,等待用户输入下一个命令,如此重复……
功能结构类似菜单模式。很粗糙,有很多不足之处,只是一个尝试。
监控程序(MonitorCmdMode.asm)运行结果:
9
运行了p1.asm的结果
10
运行了p2.asm的结果
11

上一篇:MIB Browser 1.08

下一篇:操作系统引导探究

备案ICP编号  |   QQ:285250603  |  地址:湛江市  |  电话:15322199012  |  
Copyright © 2026 天人文章管理系统 版权所有,授权www.yajiupc.top使用 Powered by 55TR.COM