|
从零学写操作系统三
到现在为止,我现还是在实模式下工作,好像并不能完全发挥出系统的性能.但是想一想我们现在似乎用不到多强的功能!所以,我们这一章还是在实模式下工作.
我们学会了启动一台计算机,并在显示器上显示一些字符.这似乎和DOS很接近了.DOS也只不过是在显示器上显示一些字符而已,虽然那些字符会反映出不同的意义.现在,我们就开始试着做出一个仿DOS的界面--呵,要想仿Widnows似乎对于现在的我们来说还有点太早.
如果前面的你都看得懂的话,相信这里的代码你也一定看的明白:
[bits 16]
[org 0x7c00]
jmp Main
Msg db "Welcome To Tresss Studio......"
db 13,10,"Tresss Studio is Start"
Mturn db 13,10,2,3,">",0
AdrCmd times 20 db 0 ;记住所输命令,最大19个字符
CmdCls db "cls",0
CmdReboot db "reboot",0
ShowMessage:
mov ah,0x0e
mov bh,0x00
.nextchar:
lodsb
or al,al
jz .brs
int 0x10
jmp .nextchar
.brs
ret
Main:
xor ax,ax
mov ds,ax
mov si,Msg
call ShowMessage ;显示欢迎信息
mov si,AdrCmd ;Si来记录命令
xor cl,cl ;Di来记录命令长度
WaitInput: ;等待用户输入
xor ah,ah
int 16h
cmp al,13
jz .Chrturn ;判断如果为回车键,则跳转检查命令
cmp cl,19
jz WaitInput ;命令超长
inc cl
mov [si],al
inc si
mov ah,0eh
int 10h
jmp WaitInput
.Chrturn
push bx
xor al,al
mov [si],al ;命令最后加一个"\0"
mov si,AdrCmd ;所输命令地址
mov di,CmdCls ;对比命令地址
call CmpStr
or bl,bl
jnz Cls ;跳转执行清屏
mov di,CmdReboot
call CmpStr
or bl,bl
jnz Reboot ;跳转重启
ShowHint:
mov si,Mturn ;提示符显示
call ShowMessage
pop bx
xor cl,cl
mov si,AdrCmd
jmp WaitInput
;∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑
;字符串对比函数
;参数:si,di
;返回值:bl,两字串相等返回1,不等返回0
;∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑∑
CmpStr:
xor bl,bl
.CmpStart
cmp BYTE [di],0
jz .CmpEnd ;对比结束
mov al,[di]
cmp al,[si]
jnz .Nequ ;不同,结束
inc si
inc di
mov bl,1
jmp .CmpStart
.Nequ
xor bl,bl
.CmpEnd
ret
Cls:
mov cx,0 ;清屏
mov dh,24
mov dl,79
mov bh,07
mov al,0
mov ah,6
int 10h
mov ah,0fh ;读取当前页号
int 10h
mov ah,2
mov dx,0 ;设置光标位置
int 10h
jmp ShowHint
Reboot:
mov ax,0040h
mov ds,ax
mov word[0072h],0000h
jmp 0ffffh:0000h
times 510-($-$$) db 0
dw 0xaa55
这里的代码比以前要多出了许多,但是涉及到的知识基本和以前一样的.只是多了一个输入中断int 16和int 10h的其它功能,可以查看一下相关的中断说明.
首先,在开头部分,我们新加了三个变量,其中第一个是用来记录用户输入的命令信息,剩下的是定义了两个仿DOS命令.
在call ShowMessage之前,代码和以前的没有什么两样.
接下来的是一个赋值和清零语句,是用来存放用户所输信息,和用来控制用户输入命令的长度的.当用户输入十九个字符后我们便不再响应其输入.这里的长度是你自己控制的,前题是与开头的缓冲区AdrCmd大小相一致.
xor ah,ah
int 16h
这是一个中断.它的参数很简单就是将AH清空.返回值也很简单,就是al里存放着用户按下的字符的Ascii码.如果用户不输入,那么系统会一直停在这里.所以,可以用这个中断来代替前文中的jmp $.
在用户输入每个字符之后,我们都要判断一下是不是回车键.如果是的话,跳转,进行相关的操作.这里我们只判断了回车键,更完善的系统应该判断更多的键,至少还要判断退格键,方向键,功能键等......
cmp cl,19这是检查用户是否输入了十九个字符,如果是的话,我们不再做任何处理直接跳转到WaitInput,等待用户重新输入而不做出任何反应.
如果小于19(此处应该是不等于19),则将此字符存入缓冲区,并显示在屏幕上.再跳转到等待输入部分.
接下来的是对回车以后的操作:
首先,在用户命令之后加上一个字符串结束符.然后将用户所输命令和我们定义的命令分别装入Si,Di,并调用对比功能进行对比,判断是否执行各种命令.
如果与所有命令均不相符,到ShowHint处会显示我们定义的提示符Mturn(包含换行),这里我们定义的是一个笑脸(第二个ASCII码)和一个心形(第三个ASCII码)再加上字符">"来代替DOS中的"C:\>".当然这里你可以定义成其它内容.但是前面的回车换行符是要加上的即13,10.
下面是字符串对比函数的实现,都是一些基本的汇编功能.
接着是CLS清屏命令的执行,主要是int 10调用.还有一个重启系统的跳转.这是整个模拟系统的两个功能主体.
这样,一个简陋的仿DOS界面就完成了,并实现了两个功能.虽然缺点还很多,功能还很少.
缺点中最主要的就是退格键的处理,要对它做的就是,字符的消除及光标位置的限制.
功能上,至少还可以加上Help或About命令.如果你对Fat分区了解的话,还可以加上仿DOS的"dir"命令和Linux上的"Cat"命令,当然这里要做的很多,磁盘扇区读写,分区参数判断等.而且这不是512字节能装下的,所以必须写在另外一个模块中放在磁盘第二或三扇区内,用此模块来读取,执行......
更正:
第一篇中110行处 "masm boot.asm -o boot.bin"这个命令是错误的,应该是:"nasm boot.asm -o boot.bin"
|
|