王爽汇编课程设计2(完整代码+虚拟机演示)

终于把完整代码写了,太懒了。

assume cs:code,ds:data,ss:stack

data segment
   db 128 dup(0)
data ends

stack segment
  db 128 dup(0)
stack ends

code segment
    start: mov ax,stack
           mov ss,ax
           mov sp,128

           mov bx,offset Boot_end-offset Boot

           call cpy_introduce_toDiskA
           call cpy_boot_toDiskA

           mov ax,4c00h
           int 21h
;=======================================================
introduce:
          mov bx,0
          mov ss,bx
          mov sp,7c00h

          call sav_old_int9
          call cpy_boot_FromDiskA

          mov bx,0
          push bx
          mov bx,7e00h
          push bx
          retf
;======================================================
cpy_boot_FromDiskA:
          mov bx,0
          mov es,bx
          mov bx,7e00h

          mov al,2    ;读取的扇区数
          mov ch,0    ;磁道号
          mov cl,2    ;扇区号
          mov dl,0    ;驱动器号,0:软驱A
          mov dh,0    ;磁头号(对于软盘即面号,因为一个面用一个磁头来读写)
          mov ah,2    ;2表示读扇区,3表示写扇区
          int 13h
     
          ret
;=======================================================
sav_old_int9:
             mov bx,0
             mov es,bx

             push es:[9*4]
             pop es:[200h]
             push es:[9*4+2]
             pop es:[202h]

             ret


          db 512 dup(0)
         
introduce_end:nop
;=======================================================
cpy_introduce_toDiskA:
            mov bx,cs  
            mov es,bx
            mov bx,offset introduce

            mov al,1   ;读取的扇区数
            mov ch,0   ;磁道号
            mov cl,1   ;扇区号
            mov dl,0   ;磁头号(面号)
            mov dh,0   ;软驱A
            mov ah,3   ;写扇区  ,软驱A 001扇区
            int 13h
            
            ret


;======================================================
 cpy_boot_toDiskA: 
            mov bx,cs
            mov es,bx
            mov bx,offset Boot

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

            ret


;======================================================
Boot:      jmp BOOT_START

;======================================================
;======================================================
;======================================================

OPTION_1     db '1) reset pc ',0      ;show_string
OPTION_2     db '2) start system ',0
OPTION_3     db '3) clock',0
OPTION_4     db '4) set clock ',0


ADDRESS_OPTION dw  offset OPTION_1-offset Boot + 7e00h  ;ADDRESS_OPTION[0]
               dw  offset OPTION_2-offset Boot + 7e00h
               dw  offset OPTION_3-offset Boot + 7e00h
               dw  offset OPTION_4-offset Boot + 7e00h


TIME_CMOS      db 9,8,7,4,2,0
TIME_STYLE     db 'YY/MM/DD HH:MM:SS',0

STRING_STACK   db 12 dup('0'),0  
;======================================================
;======================================================
;======================================================
BOOT_START: call init_reg
            call clear_screen
            call show_option

            jmp choose_option
               
            mov ax,4c00h
            int 21h
;=====================================================
choose_option:
            call clear_buff
            mov ah,0
            int 16h
            cmp al,'1'
            je isChooseOne
            cmp al,'2'
            je isChooseTwo
            cmp al,'3'
            je isChooseThree
            cmp al,'4'
            je isChooseFour
        
            jmp choose_option
;====================================================
isChooseOne:
            mov di,160*3
            mov byte ptr es:[di],'1'
            mov bx,0ffffh
            push bx
            mov bx,0
            push bx
            retf

            jmp choose_option
  
isChooseTwo:
            mov di,160*3
            mov byte ptr es:[di],'2'
            call start_system
            jmp choose_option

isChooseThree:
            mov di,160*3
            mov byte ptr es:[di],'3'
            call show_clock
            jmp BOOT_START    ;返回主屏幕

isChooseFour:
            mov di,160*3
            mov byte ptr es:[di],'4'
            call set_clock
            jmp choose_option

;====================================================
start_system:
             mov bx,0
             mov es,bx
             mov bx,7c00h

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

             mov bx,0
             push bx
             mov bx,7c00h
             push bx
             retf    ;pop ip=7c00h pop cx=0
             ret
;====================================================
set_clock:    call clear_string_stack
              call show_string_stack
              call get_string
              call set_time
              ret
;====================================================
set_time:    mov bx,offset TIME_CMOS-offset Boot +7e00H
             mov si,offset STRING_STACK-offset Boot+7e00h
             mov cx,6

setTime:     mov dx,ds:[si]                      ;ASCII码
             sub dh,30h                          ;ds:[si]=12
             sub dl,30h                          ;dh=2
             shl dl,1                            ;dl=1
             shl dl,1
             shl dl,1
             shl dl,1
             and dh,00001111b                  ;这步可以不要,不影响
             or dl,dh

             mov al,ds:[bx]
             out 70h,al
             mov al,dl
             out 71h,al                         ;把BCD码写入

             add si,2
             inc bx
             loop setTime
             ret
;====================================================

;====================================================
get_string:  mov si,offset STRING_STACK-offset Boot+7e00h
             mov bx,0                       ;Top

getString:   call clear_buff

             mov ah,0
             int 16h

             cmp al,'0'
             jb notNumber
             cmp al,'9'
             ja notNumber
             call char_push
             call show_string_stack

             jmp getString

getStringRet:ret                        ;这里大小写错了,找了20分钟
notNumber:   cmp ah,0eh
             je isBackSpace               ;BackSpace
             cmp ah,1ch
             je getStringRet
             jmp getString

isBackSpace:  call char_pop
              call show_string_stack
              jmp getString
;====================================================
char_pop:     cmp bx,0
              je charPopRet
              dec bx
              mov byte ptr ds:[si+bx],'0'
charPopRet:   ret
;====================================================
char_push:    cmp bx,11   ;记录字符个数,一共11个,最后一个当作0
              ja charPushRet
              mov ds:[si+bx],al
              inc bx
 
charPushRet:  ret

;====================================================
show_string_stack:
              push si
              push di

              mov si,offset STRING_STACK-offset Boot+7e00h
              mov di,160*4

              call show_string
              pop di
              pop si
              ret
;====================================================
clear_string_stack:
                push bx
                push cx
                push es
                push si
                push di

                mov si,offset STRING_STACK-offset Boot +7e00h
                mov dx,3030h

                mov cx,6      ;6*2=12个字符都是0

clearStringStack:
                mov ds:[si],dx
                add si,2
                loop clearStringStack

                pop di
                pop si
                pop es
                pop cx
                pop bx
                ret



;====================================================
show_clock: call show_style

            call set_new_int9

            mov bx,offset TIME_CMOS-offset Boot+7e00h

showTime:   mov si,bx
            mov di,160*20
            mov cx,6

showDate:   mov al,ds:[si]
            out 70h,al
            in al,71h

            mov ah,al
            shr ah,1
            shr ah,1
            shr ah,1
            shr ah,1
            and al,00001111b

            add ah,30h
            add al,30h

            mov es:[di],ah
            mov es:[di+2],al
            
            add di,6
            inc si
            loop showDate
            jmp showTime

showTimeRet:call set_old_int9

            ret
;====================================================
set_old_int9:
            push bx
            push es

            mov bx,0
            mov es,bx

            cli
            push es:[200h]
            pop es:[9*4]
            push es:[202h]
            pop es:[9*4+2]
            sti

            pop es
            pop bx
            ret
;====================================================
set_new_int9:
            push bx
            push es

            mov bx,0
            mov es,bx

            cli
            mov word ptr es:[9*4],offset new_int9-offset Boot+7e00h
            mov word ptr es:[9*4+2],0
            sti

            pop es
            pop bx
            ret
;====================================================
new_int9:  push ax
           
           call clear_buff

           in al,60h   ;把扫描码从60h端口读出
           pushf
           call dword ptr cs:[200h]

           cmp al,01h     ;Esc
           je isEsc
           cmp al,3bh
           jne int9Ret
           call change_time_color

int9Ret:   pop ax
           iret

isEsc:     pop ax
           add sp,4    ;刚开始中断的时候 标志寄存器入栈 if=0,tf=0,CS,IP入栈。所以栈顶要向下移4个字节,才是flag的正确值
           popf      
           jmp showTimeRet

           
;====================================================
change_time_color:
           push bx
           push cx
           push es

           mov bx,0b800h    ;这个地方又写成08b00,哎,真傻。
           mov es,bx
           mov bx,160*20+1

           mov cx,17
changeTimeColor:
           inc byte ptr es:[bx]
           add bx,2
           loop changeTimeColor

           pop es
           pop cx
           pop bx
           ret
;====================================================
show_style:
            mov si,offset TIME_STYLE-offset Boot +7e00h
            mov di,160*20

            call show_string
            ret
;====================================================
clear_buff: mov ah,1       ;用来查询键盘缓冲区,对键盘扫描但不等待
            int 16h        ;并设置ZF标志。若有按键操作(即键盘缓冲区不空),zf=0,无键按下则zf=1
            jz clearBuffRet
            mov ah,0
            int 16h        ;清除键盘缓存区的字符
            jmp clear_buff

clearBuffRet:ret

show_option:
            mov bx,offset ADDRESS_OPTION - offset Boot + 7e00h
            mov di,160*10+30*2
            mov cx,4

showOption: mov si,ds:[bx]  ;si存放了OPTION_n的偏移地址
            call show_string
            add bx,2
            add di,160
            loop showOption

            ret
;=====================================================
show_string:push dx
            push ds
            push es
            push si
            push di

showString: mov dl,ds:[si]
            cmp dl,0
            je showStringRet
            mov es:[di],dl      ;es=0b800h
            add di,2
            inc si
            jmp showString

showStringRet:pop di
              pop si
              pop es
              pop ds
              pop dx
              ret
;=====================================================
clear_screen:
            mov bx,0
            mov dx,0700h   ;07h(黑底白字), 00表示无字符
            mov cx,2000
clearScreen:mov es:[bx],dx
            add bx,2
            loop clearScreen
            ret
;=====================================================
init_reg:   mov bx,0b800h
            mov es,bx
            
            mov bx,0
            mov ds,bx
            ret

            db 512 dup(0)

Boot_end: nop


             
;=======================================================
cpy_Boot:
           mov ax,cs
           mov ds,ax
           mov si,offset Boot

           mov bx,0
           mov es,bx
           mov di,7e00h

           mov cx,offset Boot_end-offset Boot
           cld 
           rep movsb

           ret
code ends
end start

下面是演示视频
在这里插入图片描述
这个程序总体可以分成两部分,一部分是引导程序,另一部分就功能得实现。在然后从上到下,慢慢细分。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值