用汇编编写一个可以开机自行启动的软件(纯DOS环境下)

  开机后,CPU自动进入到FFFF:0单元处执行,此处有一条跳转指令。CPU执行该指令后,转去执行BIOS中的硬件系统检测和初始化程序。 初始化程序将建立BIOS所支持的中断向量,即将BIOS提供的中断例程的入口地址登记在中断向量表中。 硬件系统检测和初始化完成后,调用int 19h进行操作系统的引导。 如果设为从软盘启动操作系统,则int 19h将主要完成以下工作。 

  (1)控制0号软驱,读取软盘0道0面1扇区的内容到0:7c00; 

  (2)将CS:IP指向0:7c00。 

  软盘的0道0面1扇区中装有操作系统引导程序。int 19h将其装到0:7c00处后,设置CPU从0:7c00开始执行此处的引导程序,操作系统被激活,控制计算机。 如果在0号软驱中没有软盘,或发生软盘I/O错误,则int 19h将主要完成以下工作。 

  (1)读取硬盘C的0道0面1扇区的内容到0:7c00; 

  (2)将CS:IP指向0:7c00。 

  这次课程设计的任务是编写一个可以自行启动的计算机,不需要在现有操作系统环境中运行的程序。 

该程序的功能如下: 

  (1)列出功能选项,让用户通过键盘进行选择,界面如下 

     1) reset pc          ;重新启动计算机 

     2) start system      ;引导现有的操作系统 

     3) clock             ;进入时钟程序 

     4) set clock         ;设置时间 

  (2)用户输入"1"后重新启动计算机(提示:考虑ffff:0单元) 

  (3)用户输入"2"后引导现有的操作系统(提示:考虑硬盘C的0道0面1扇区)。 

  (4)用户输入"3"后,执行动态显示当前日期、时间的程序。 

  显示格式如下:年/月/日 时:分:秒 

  进入此项功能后,一直动态显示当前的时间,在屏幕上将出现时间按秒变化的效果(提示: 循环读取CMOS)。 

  当按下F1键后,改变显示颜色;按下Esc键后,返回到主选单(提示:利用键盘中断)。 

  (5)用户输入"4"后可更改当前的日期、时间,更改后返回到主选单(提示:输入字符串)。

assume cs:code

code segment
;将程序写在扇区
begin:  mov ax,0
        mov es,ax
        mov bx,offset start

        mov al,1
        mov ch,0
        mov cl,1
        mov dl,0
        mov dh,0
        mov ah,3
        int  13h

        add bx,512
        mov al,1
        mov ch,0
        mov cl,2
        mov dl,0
        mov dh,0
        mov ah,3
        int  13h

        mov ax,4c00h
        int 21h

start:  jmp main

        ;显示菜单
        menu dw cmd0,cmd1,cmd2,cmd3,cmd4,cmd5
        cmd0 db "Command: ",0
        cmd1 db "1) reset pc",0
        cmd2 db "2) start system",0
        cmd3 db "3) clock",0
        cmd4 db "4) set clock",0
        cmd5 db "Enter command: ",0

        ;显示年月日(y/m/d)
        clockstr dw cl1,cl2,cl3
        clockcolor db 02h
        cl1 db '00/00/00 00:00:00',0
        cl2 db 'ESC - return menu!',0
        cl3 db 'F1 - change color!',0
        cltable db 9,8,7,4,2,0

        ;更改日期
        points dw pointsInput,pointsEnd
        pointsInput db "Enter new date in format YYMMDDHHMMSS: ",0
        pointsEnd db "You have changed date successfully.",0

        ;功能模块
        func dw ResetPC,StartSystem,Clock,SetClock

;主程序
main:    ;重启时从磁盘读取程序到0:7c00h
        mov ax,0
        mov es,ax
        mov bx,7c00h

        mov al,1
        mov ch,0
        mov cl,1
        mov dl,0
        mov dh,0
        mov ah,3
        int  13h

        mov bx,7c00h+512
        mov al,1
        mov ch,0
        mov cl,1
        mov dl,0
        mov dh,0
        mov ah,3
        int  13h

        call CleanScreen
        mov bx,0
        mov cx,6
        mov di,0
        mov dl,7
;显示菜单
ShowMenu:   push bx
            mov bx,menu[bx]
            call ShowData
            add di,160
            pop bx
            add bx,2
            loop ShowMenu

        call MoveCursor
        call ReadCMD

        mov ax,4c00h
        int 21h

;清除当前屏幕
CleanScreen:    push ax
                push cx
                push es
                push di

                mov ax,0b800h
                mov es,ax
                mov di,0
                mov cx,2000

     CSloop:    mov byte ptr es:[di],0
                add di,2
                loop CSloop

                pop di
                pop es
                pop cx
                pop ax
                ret

;显示数据
;bx为偏移地址,di指向显示位置
ShowData:   push es
            push di
            push cx
            push ax
            push si
            push dx

            mov si,0
            mov ch,0
            mov ax,0b800h
            mov es,ax

  SDloop:   mov cl,cs:[bx+si]
            jcxz SDend
            mov es:[di],cl
            inc di
            mov es:[di],dl
            inc si
            inc di
            jmp short SDloop

   SDend:   pop dx
            pop si
            pop ax
            pop cx
            pop di
            pop es
            ret

;移动光标
MoveCursor: push ax
            push bx
            push dx

            mov ah,2
            mov bh,0
            mov dh,5
            mov dl,15
            int 10h

            pop dx
            pop bx
            pop ax
            ret

;读取命令
ReadCMD:    push ax
            push bx

CMDLoop:    mov ah,0
            int 16h
            cmp al,'1'
            jb ReadCMD
            cmp al,'4'
            ja ReadCMD
            sub al,'1'
            mov ah,0
            push ax
            pop bx
            add bx,bx
            call word ptr func[bx]

            pop bx
            pop ax
            jmp main

;重启PC
ResetPC:    mov ax,0ffffh
            push ax
            mov ax,0
            push ax
            retf

;引导操作系统
StartSystem:    mov al,1
                mov ch,0
                mov cl,1
                mov dl,80h
                mov dh,0
                mov ah,2
                int 13h

                mov ax,0
                push ax
                mov ax,7c00h
                push ax
                retf

Clock:  push ax
        push bx
        push cx
        push dx
        push si
        push di
        push dx

        call CleanScreen
ClockB: mov dl,1
        mov dh,8
ClockS: mov si,0
        mov di,0
        mov cx,6

Cloop:  push cx
        mov al,cltable[di]

        out 70h,al        
        in al,71h
        mov ah,al        
        mov cl,4       
        shr ah,cl        
        and al,00001111b   
        add ah,30h        
        add al,30h
        
        mov byte ptr cl1[si],ah  
        mov byte ptr cl1[si+1],al

        add si,3
        inc di
        pop cx
        loop Cloop

ShowBeg:    mov bx,0
            mov di,0
            mov cx,3

ShowClock:  push bx
            mov bx,clockstr[bx]
            call ShowData
            add di,160
            pop bx
            add bx,2
            loop ShowClock

            ;改变颜色或返回
            in al,60h
            cmp al,01h      ;ESC
            je ClockRet
            cmp al,3bh      ;F1
            je ChangeColour
            jmp short ClockS

ChangeColour:   shl dl,1
                cmp dl,dh
                je ClockB
                jmp short ClockS

ClockRet:   pop dx
            pop di
            pop si
            pop dx
            pop cx
            pop bx
            pop ax
            ret

;设置时钟
SetClock:   push ax
            push bx
            push cx
            push dx
            push es
            push di

            call CleanScreen
            mov bx,0
            mov bx,points[bx]
            mov di,0
            call ShowData

            mov cx,6
            mov bx,0
            mov ax,0b800h
            mov es,ax
            mov di,39*2

Input:      push cx
Input1:     mov ah,0
            int 16h
            cmp al,'0'
            jb Input1
            cmp al,'9'
            ja Input1
            mov es:[di],al
            add di,2
            
            sub al,'0'
            mov cl,4
            shl al,cl
            mov ch,al

Input2:     mov ah,0
            int 16h
            cmp al,'0'
            jb Input2
            cmp al,'9'
            ja Input2
            mov es:[di],al
            add di,2

            sub al,'0'
            and al,00001111b
            add al,ch

            push ax
            mov al,cltable[bx]
            inc bx

            out 70h,al
            pop ax
            out 71h,al
            pop cx
            loop Input

            mov bx,2
            mov bx,points[bx]
            mov di,160
            call ShowData
            call Delay

            pop di
            pop es
            pop dx
            pop cx
            pop bx
            pop ax
            ret

Delay:      push ax
            push dx
            mov dx,0ch
            mov ax,0
s1:         sub ax,1
            sbb dx,1
            cmp ax,0
            jne s1
            cmp dx,0
            jne s1
            pop dx
            pop ax
            ret
code ends
end begin

 

posted @ 2020-07-31 15:11  CSULuyao  阅读(536)  评论(0编辑  收藏  举报