汇编终极boss
这是迄今为止我编写的最复杂的程序(其实也没编过什么),即王爽汇编最后一个课程设计。
这次课程设计的任务是编写一个可以自行启动计算机,不需要在现有操作系统环境中运行的程序。
该程序的功能如下:
1)列出功能选项,让用户通过键盘进行选择,界面如下:
1. reset pc :重新启动计算机
2. start system :引导现有操作系统
3. clock :进入时钟程序
4. setclock :设置时间
2)用户输入“1”后重新启动计算机。
3)用户输入“2”后引导现有操作系统。
4)用户输入“3”后,执行动态显示当前日期、时间的程序,按下f1键后,改变显示颜色;按下esc键,返回主选单。
5)用户输入“4”后可更改当前的日期,时间,更改后返回到主选单
断断续续的大概用了两天时间,这里面主要有以下几个方面比较困难:
一是,如何安装程序,即将功能程序安装在软盘中,程序明显大于512字节,因此软盘的0面0道1扇区应该负责将后面扇区的程序读入内存。问题是如何确保将功能程序安装在第二扇区。 我这里采用了两次写软盘的方式,第一次将引导程序写入0道0面1扇区,第二次将功能程序写入以后的扇区
二是,功能四比较麻烦,需要处理字符的显示,以及转化后写入cmos ram的问题。第二次输入时间会显示上次时间,需要在enter字程序中将top清零,指向字符栈顶。
三是,运行环境的问题。我用的是vmware虚拟机。里面装了一个dos。主机和虚拟机之间的文件传递问题一直困扰着我。刚开始我想通过ftp来传递,新装的dos里面干干净净,哪有什么ftp, 网络连接都不一定有,共享文件什么就更不用想了。上网搜了一下,发现有人使用虚拟软驱,vfloppy,下来一个看看,没弄清到底如何用在虚拟机里面。最后,使用了一个软件,叫ultraiso, 利用它将编译好的文件压制成iso格式的,然后通过虚拟光驱传送到dos下。
以下是源程序:
assume cs:code
code segment
begin: mov ax,cs
mov es,ax
mov bx,offset be1
mov al,1
mov ch,0
mov cl,1
mov dl,0
mov dh,0
mov ah,3
int 13h ; 引导程序写入0面0道1扇区
mov bx,offset be2
mov al,3
mov ch,0
mov cl,2
mov dl,0
mov dh,0
mov ah,3
int 13h ;将功能程序写入以后的三个扇区中。
mov ax,4c00h
int 21h
;以下为写入软盘1扇区中的内容
be1:mov ax,0
mov ss,ax
mov sp,7c00h ;设置个堆栈,
mov es,ax
mov bx,7e00h
mov al,3
mov ch,0
mov cl,2
mov dl,0
mov dh,0
mov ah,2
int 13h ; 将功能程序读入0:7e00处。
mov ax,0
push ax
mov ax,7e00h
push ax
retf ;设置cs:ip为0:7e00
;以下为0道0面2扇区及以后的内容
org 7e00h
be2:
jmp short start
table dw resetpc,startsystem,clock,setclock
s1: db '1.reset pc',0
s2: db '2.start system',0
s3: db '3.clock',0
s4: db '4.set clock',0
start: call clear
mov ax,0
mov ds,ax
mov dh,5
mov dl,20
mov cl,2
mov si,offset s1
call showstr
mov dh,6
mov si,offset s2
call showstr
mov dh,7
mov si,offset s3
call showstr
mov dh,8
mov si,offset s4
call showstr ;就这四句,懒得用直接定址表了
stt1: mov al,0
mov ah,0
int 16h
cmp al,'1'
jb stt1
cmp al,'4'
ja stt1
sub al,31h
mov bl,al
mov bh,0
add bx,bx
jmp word ptr table[bx]
jmp short stt1 ;循环,如果输入1-4则转止相应功能子程序
resetpc:mov ax,0ffffh
push ax
mov ax,0
push ax
retf ;重启
startsystem: mov ax,0
mov es,ax
mov bx,7c00h
mov ah,2
mov al,1
mov ch,0
mov cl,1
mov dh,0
mov dl,80h
int 13h
mov ax,0
push ax
mov ax,7c00h
push ax
retf ;从硬盘启动
clock: call clear
mov cx,1 ;设置初始颜色
jmp short clock1
clockstr: db '??/??/?? ??:??:??',0
clocktab db 9,8,7,4,2,0
clock1: mov bx,0
mov di,0
push cx
mov cx,6
clock2:
push cx
mov al,clocktab[di]
out 70h,al
in al,71h
mov ah,al
mov cl,4
shr al,cl
and ah,00001111b ;高地址放入bcd码的低四位
add ax,3030h
mov word ptr clockstr[bx],ax
add bx,3
inc di
pop cx
loop clock2 ;获取时间,并转换为ascii码
pop cx
mov si,offset clockstr
mov dh,7
mov dl,20
call showstr
mov al,0
in al,60h
cmp al,01h
je return ;直接跳至start距离太远,来个中转站。
cmp al,3bh
jne clock1
inc cl
call showstr
jmp short clock1
return: jmp start
setclock: call clear
jmp short setclocks
sample : db 'input time: yymmddttmmss',0
charbuffer db '????????????',0
setclocks: mov bx,0
mov di,0
mov cx,6
sets1:mov al,clocktab[di]
out 70h,al
in al,71h
mov ah,al
shr al,1
shr al,1
shr al,1
shr al,1
and ah,00001111b
add ax,3030h
mov word ptr clockstr[bx],ax
add bx,3
inc di
loop sets1
mov si,offset clockstr
mov dh,7
mov dl,20
mov cl,2
call showstr ;显示当前时间
mov si,offset sample
mov dh,8
call showstr
mov ah,2
mov bh,0
mov dh,9
mov dl,20
int 10h ;设置光标位置,没多大作用,
mov si,offset charbuffer
call getstr ;处理字符串的输入,及显示问题。返回时charbuffer中即为输入的数字
mov bx,0
mov di,0
mov cx,3
sets2: mov al,clocktab[di]
out 70h,al
mov ah,charbuffer[bx]
mov al,charbuffer[bx+1]
sub ax,3030h
shl ah,1
shl ah,1
shl ah,1
shl ah,1
and al,00001111b
add al,ah
out 71h,al
add bx,2
inc di
loop sets2 ;更改时间
jmp start
showstr:push ax
push es
push di
push cx
push si
push dx
mov ax,0b800h
mov es,ax
mov ah,0
mov al,160
mul dh
mov di,ax
add dl,dl
mov dh,0
add di,dx
mov ch,0
mov ah,cl
showstr1:mov cl,[si]
jcxz showstrok
mov al,cl
mov es:[di],ax
inc si
add di,2
jmp short showstr1
showstrok:pop dx
pop si
pop cx
pop di
pop es
pop ax
ret ;显示以0结尾的字符串的子程序,
clear: push bx
push es
push cx
mov bx,0b800h
mov es,bx
mov bx,0
mov cx,2000
cles: mov byte ptr es:[bx],' '
add bx,2
loop cles
pop cx
pop es
pop bx
ret ;清屏子程序
charstack: jmp short charstart
chartable dw charpush,charpop,charshow
top dw 0
charstart: push bx
push dx
push di
push es
cmp ah,2
ja sret
mov bl,ah
mov bh,0
add bx,bx
jmp word ptr chartable[bx]
charpush: mov bx,top
mov [si][bx],al
inc top
jmp sret
charpop: cmp top,0
je sret
dec top
mov bx,top
mov al,[si][bx]
jmp sret
charshow: mov bx,0b800h
mov es,bx
mov al,160
mov ah,0
mul dh
mov di,ax
add dl,dl
mov dh,0
add di,dx
mov bx,0
charshows: cmp bx,top
jne noempty
mov byte ptr es:[di],' ' ;此处确保清除上次显示的字符
jmp sret
noempty: mov al,[si][bx]
mov es:[di],al
mov byte ptr es:[di+2],' '
inc bx
add di,2
jmp charshows
sret: pop es
pop di
pop dx
pop bx
ret
getstr: push ax
getstrs: mov ah,0
int 16h
cmp al,30h
jb nochar
cmp al,39h
ja getstrs ;只接收数字
mov ah,0
call charstack
mov ah,2
call charstack
jmp getstrs
nochar: cmp ah,0eh
je backspace
cmp ah,1ch
je enter
jmp getstrs
backspace: mov ah,1
call charstack
mov ah,2
call charstack
jmp getstrs
enter: mov al,0
mov ah,0
call charstack
mov ah,2
call charstack
mov ax,0
mov top,ax ;返回前设置字符栈栈顶
pop ax
ret
code ends
end begin

这么长的汇编,有点晕了。我的汇编废了。。。
[Reply]
哇 三百多行汇编~~shit 这几个月总共写得都才这么多哦~~
我们也要做这个设计实验~~~ 开始以看题目就是魔头不知闹~
看了这个还是有点帮助 谢了~~
[Reply]