首页 > 代码库 > 课程设计2 终结版-未测试

课程设计2 终结版-未测试

公司项目ok了,抽空写完代码,苦于win2000对磁盘有保护,不能直接用int13h,无法测试。代码虽然完成,还要过几天把dos环境塔好再测试。代码反正放这了。 让博客园帮我云存储下。对磁盘结构了解也不多,不知道这代码跑出来是何种结果。至少在主界面输入f3是要屏蔽的。

 

代码如下:


;   display system time. press f1 to change the color displayed, press esc to return main list. f3 exit
;    clear_screen 清空屏幕
;    把磁盘上0道0面1扇区内容移动到0:200处,再把本程序的工作部分代码移动到0道0面1扇区。(暂时未实现)
assume cs:codesg
;stacksg segment
    ;dw 128 dup(0)
;stacksg ends
codesg segment    
start:
        ; 备份0道0面1扇区内容到第0道0面5扇区
        sub ax,ax
        mov es, ax
        mov bx, 200h
        mov al, 1
        mov ch, 0
        mov cl, 1
        mov dl, 80h
        mov dh, 0
        mov ah, 2
        int 13h
        cmp ah, 0
        jne start_main_exit
        mov cl, 5
        mov ah, 3
        mov al, 1
        int 13h
        
        ; 把程序复制到0道0面1-3扇区,理论上用了这个除法,但经过我的计算顶多三个扇区可以存储
        mov ax, offset start_end - offset start_main
        sub dx, dx
        mov bx, 512
        div bx
        
        cmp dx, 0
        je div_al_next
        inc al        ; 除以512余数不为0则再增加一个扇区
div_al_next:
        mov bx, offset start_main
        push cs
        pop es     ;  es:bx指向要写入磁盘的数据
        mov cl, 1
        mov dl, 80h
        mov dh, 0
        mov ah, 3
        int 13h
        
start_main_exit:
    jmp exit
start_main:
    ; 程序开始引导系统,则将位于0道0面5扇区内容复制到内存0:200处,将0道0面2-3扇区内容复制到内存0:7c00+512B(0:7e00)

    jmp short install_begin
    line db 6
    csip dw 0,0
    exitflag db 0    ; f3-2, esc-1. 只有在主界面才能退出,所以每次从时钟返回都会重置此值
    color    db 2
    num    dw 0
    install_begin:
        ;mov ax, stacksg
        ;mov ss, ax
        ;mov sp, 128
        ; 将第5扇区内容写到0:200h
        sub ax,ax
        mov es, ax
        mov bx, 200h
        mov al, 1
        mov ch, 0
        mov cl, 5
        mov dl, 80h
        mov dh, 0
        mov ah, 2
        int 13h
        ; 将2,3扇区内容写到内存0:(7c00+512)外
        mov cl, 2
        mov al, 2
        mov bx, 7c00h
        add bx, 512
        int 13h

        push cs
        pop ds
        
        push es:[9*4]
        pop csip[0]
        push es:[9*4 + 2]
        pop csip[2]
        
        cli
        mov word ptr es:[9*4], offset int9
        mov es:[9*4 + 2], cs
        sti
;###############################################################
main:
        mov exitflag, 0
        mov color, 2
        call display_main_list        ;主菜单
        ;     在主菜单获取输入
get_main_input:
        cmp exitflag, 2
        je main_exit
        ; 1,2,3,4为有效输入,1-clock,2-set clock,3-restart pc,4-start system
        mov ah, 0
        int 16h
        mov color, 2
        cmp ah, 02h     ;  通码 1-9:02-0a
        je main_display_clock
        cmp ah, 03h
        je main_set_clock
        cmp ah, 04h        
        je main_restart
        cmp ah, 05h
        je main_start_system
        ;    其它情况,对比是否有功能键触发事件或忽略无效按键
        jmp get_main_input
main_exit:
        jmp near ptr exit    ; 程序退出
main_display_clock:
    ; 显示时钟,返回后,则显示主界面
        mov ah, 0
        call clock
        jmp near ptr main
main_set_clock:
        mov ah, 1
        call clock
        jmp near ptr main
main_restart:
        mov ax, 0ffffh
        sub bx,bx
        push ax
        push bx
        retf
main_start_system:
        sub ax, ax
        mov bx, 200h
        push ax
        push bx
        retf
        
exit:
        ; 恢复向量表
        push csip[0]
        pop es:[9*4]
        push csip[2]
        pop es:[9*4 + 2]

        mov ax, 4c00h
        int 21h
    ;    主菜单功能
display_main_list:
        jmp  main_list
        mainlist dw display, setclock, resetpc, startsystem, f3exit,escfunctiondes,null
        display db ‘1) clock‘
        setclock db ‘2) set clock‘
        resetpc db ‘3) reset pc‘
        startsystem db ‘4) start system‘
        f3exit    db    ‘press f3 to exit this process‘
        escfunctiondes db ‘press esc to return superior menu on any page‘
        null db 0
    ;    显示主菜单
main_list:
        push cx
        push dx
        push bx
        push si
        push ax
        call clear_screen
        mov cx, 6
        mov dh, line    ; dh 行号
        mov dl, 8        ; 列号主菜单不用变
        mov bx, 0
loop_main_list:
        mov si, mainlist[bx]
        mov di, mainlist[bx + 2]
        sub di, si
        mov num, di
        call strshow
        add bx,2
        inc dh
        loop loop_main_list    
        
        pop ax
        pop si
        pop bx
        pop dx
        pop cx
        ret

        ;    clock子函数,ah 传递功能号, 0- 显示时钟,1- 设置时钟
clock:
        jmp short do_clock
        clocktable dw dis_clock, set_clock
        clock_str    db ‘20yy/mm/dd hh:mm:ss‘
        row    db 9,8,7,4,2,0
        prompot dw year, month, day, hour, minite, second, inputstr
        year db ‘(YY):‘
        month db ‘(MM):‘
        day db ‘(DD):‘
        hour db ‘(HH):‘
        minite db ‘(mm):‘
        second db ‘(ss):‘
        inputstr db 3 dup(0)
        validnum db 99h, 12h, 31h, 23h, 59h, 59h
;    秒: 0  分:2 时: 4 日 : 7 月:8 年:9

do_clock:
        push bx
        push ax
        push si
        push di
        push cx
        push ds
        
        cmp ah, 1
        ja do_clock_exit
        cmp ah, 0
        jb do_clock_exit
        mov bl, ah
        mov bh, 0
        add bx,bx
        jmp word ptr clocktable[bx]
do_clock_exit:
    jmp clock_ret
;    每1s显示一次时钟
dis_clock:
        call clear_screen
        mov dl, 8
        mov dh, line
        mov num, 19
dis_per_second:
        cmp exitflag, 1    ; only esc can return from clock screen
        je dis_clock_ret
        mov di, 2
        mov si, 0
        mov cx, 6
        ; 设置时钟字符串
_dis_get_clock:
        mov al, row[si]
        call _sys_readclock
        mov clock_str[di], ah
        mov clock_str[di + 1], al
        add di, 3
        inc si
        loop _dis_get_clock
        mov si, offset clock_str
        call strshow
        call delay
        jmp short dis_per_second

dis_clock_ret:
        jmp clock_ret

;        设置时钟
set_clock:
        call clear_screen
        mov cx, 6
        sub bx,bx
        mov dh, line
        sub di,di
set_clock_loop:
        mov dl, 8
        ;    打印提示符        
        mov si, prompot[bx]
        mov num, 5

        call strshow
        add dl, 5
        ; 获取两次输入
set_clock_back:
        mov inputstr[0], 0
        mov inputstr[1], 0
        mov inputstr[2], 0
        mov si, offset inputstr
        mov num, 2
        call strshow
        mov num, 0
        ; 获取输入
set_clock_getnum:
        cmp exitflag, 1
        je set_clock_exit
        mov ah, 0
        int 16h
        cmp ah, 02h    ; 小于字符1
        jb set_clock_getnum
        cmp ah, 1ch    ; enter
        je set_clock_getnum_enter    ; 响应回车
        cmp ah, 0eh    ; backspace        ; 退格符
        je set_clock_getnum_backspace
        cmp ah, 0bh ; 0    不符合以上情况下还大于字符0的,则忽略输入
        ja set_clock_getnum
        ;    字符入栈
        jmp near ptr set_clock_getnum_push
        
        
set_clock_getnum_out:
        call strshow
        jmp set_clock_getnum
 
        ;    ah为要设置的数据,al为设置的地址
set_clock_getnum_next:
        mov al, row[di]    ;
        call _sys_setclock
        add bx, 2
        inc dh
        inc di
        loop set_clock_loop
        jmp short clock_ret
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
set_clock_getnum_enter:
        push cx
        mov ah, inputstr[0]
        mov cl, 4
        shl ah, cl
        mov al, inputstr[1]
        and al, 00001111b
        or ah, al
        ;    校验输入是否合法,否则重新输入
        pop cx
        cmp ah, validnum[di]
        ja set_clock_getnum_back
        jmp near ptr set_clock_getnum_next
set_clock_getnum_push:
        cmp num, 2
        je set_clock_getnum_out
        push bx
        mov bx, num
        mov [si][bx], al
        pop bx
        inc num
        jmp short  set_clock_getnum_out
        ;    要输入字符在inputstr[0],[1]中
set_clock_exit:
        jmp clock_ret
set_clock_getnum_backspace:
        ; pop al
        cmp num, 0
        je getnum_backspace_out
        dec num
        push di
        mov di, num
        mov inputstr[di], 0
        pop di
getnum_backspace_out:    
        jmp short set_clock_getnum_out

set_clock_getnum_back:
        jmp set_clock_back
        
        
clock_ret:
        pop ds
        pop cx
        pop di
        pop si
        pop ax
        pop bx
        ret
    ;    al要写入的地址,ah要写入的数据
_sys_setclock:
    push ax
    out 70h, al
    mov al, ah
    out 71h, al
    pop ax
    ret
    ;    input :al ,向70h端口写入的地址
    ;    ouput ah, al,
_sys_readclock:
    push cx
        out 70h, al
        in  al, 71h
        mov ah, al
        mov cl, 4
        shr ah, cl
        add ah, 30h
        and al, 00001111b
        add al, 30h
    pop cx
    ret
    
delay:
        push ax
        push dx
        mov dx, 0BFFh
        mov ax, 0
    s_delay:
        sub ax, 1
        sbb dx, 0
        cmp ax, 0
        jne s_delay
        cmp dx, 0
        jne s_delay
        pop dx
        pop ax
    ret

clear_screen:
        push bx
        push cx
        push es

        mov ax, 0b800h
        mov es, ax
        mov cx, 2000
        mov al, ‘ ‘
        mov ah, 0
        mov bx, 0
s_clear_screen:
        mov es:[bx], ax
        add bx, 2
        loop s_clear_screen
        
        pop es
        pop cx
        pop bx
        ret
;    int9 中断程序替代程序,esc置exitflag为1.f1改变颜色,无脑增加color的值,f3设置exitflag为2
int9:
    push ax
    in al, 60h
    pushf
    call dword ptr csip
    ;    check if equal esc:01, f1:3b, f1 change color. esc exit function
    cmp al, 01h    ;esc
    je _int9_esc
    cmp al, 3bh
    je _int9_f1
    cmp al, 3dh            ;        F3 退出
    je _int9_f3
    mov exitflag, 0
    jmp int9ret
_int9_f1:    inc color
    jmp int9ret
_int9_f3:
    mov exitflag, 2
    jmp int9ret
_int9_esc:
    mov exitflag, 1
int9ret:
        pop ax
        iret

    ;    dh, dl 字符串在屏幕上显示的行与列
    ;    其中color为颜色
    ;    num 传递要打印的字符数,打印bx个字符后或遇到0停止打印
; charstack:    
strshow:
            push bx
            push dx
            push di
            push es
            push ax
            push cx
            
            ;dh  行号,  dl列号,  个数
            mov ax, 0b800h
            mov es, ax
            mov al,160    ; 每行160字节
            sub ah, ah
            mul dh
            add dl, dl       
            sub dh, dh
            add ax, dx
            mov di, ax
            mov ah, color
            sub bx, bx
            mov cx, num
            cmp cx, 0
            je charstack_ret
    charshows:
            mov al, [si][bx]
            cmp al, 0
            jne charstack_print
            mov al, ‘ ‘
    charstack_print:
            mov es:[di], ax
            add di, 2
            inc bx
            loop charshows
    charstack_ret:
            mov byte ptr es:[di], ‘ ‘
            pop cx
            pop ax
            pop es
            pop di
            pop dx
            pop bx
            ret
start_end:
        nop
codesg ends
end start