1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765
   | assume cs:code,ds:data data segment bootdata db 510 dup(0)          dw 0aa55h data ends code segment
 
 
 
  ;=======================下面是A盘2至4扇区内容===========================                   ;offset sysbootend-offset sysboot之间的内容是拷贝到A盘2-4扇区的内容。                   ;=======================下面是A盘2至4扇区内容===========================
  sysboot: jmp  near ptr dostart oldint9addr  dw 0,0 ;如果不加offset偏移地址会出错 menudata     dw  offset md0-offset sysboot+7e00h              dw  offset md1-offset sysboot+7e00h              dw  offset md2-offset sysboot+7e00h              dw  offset md3-offset sysboot+7e00h              dw  offset md4-offset sysboot+7e00h md0          db '------ welcome ------',0 md1          db '1) reset pc',0 md2          db '2) start system',0 md3          db '3) clock',0 md4          db '4) set clock',0 timedata     db 20h,2h,18h,17h,51h,0h timeaddr     db 9,8,7,4,2,0 timestr      db '00/00/00 00:00:00',0 timelimitb   db  0, 1, 1, 0, 0,0 timelimita   db 99h,12h,31h,23h,60h,60h focusplaces  db 0,1,3,4,6,7,9,10,12,13,15,16 focus        db 0 color        db 4 functionlist dw offset endloopcore-offset sysboot+7e00h              dw offset showmenu   -offset sysboot+7e00h              dw offset reset      -offset sysboot+7e00h              dw offset startsys   -offset sysboot+7e00h              dw offset showclock  -offset sysboot+7e00h              dw offset setclock   -offset sysboot+7e00h sign         db 1      ;设为0时退出,1,显示菜单,4、时显示时钟 5、设置时钟 stack        db 128 dup (0)          dostart: mov ax,cs;cs=0 mov ds,ax mov ss,ax add ax,offset dostart-offset sysboot+7e00h mov sp,ax
  call setint9    ;捕获键盘,设置9号中断, jmp loopcore    ;循环显示菜单。 ;call saveclock ;调试保存时钟 ;call showclock ;调试显示时钟
  ;================调试时钟设置================ ;mov al,0ah ;call settime ;call showtimedata ;================调试时钟设置================
  mov ax,4c00h int 21h ;ret ;这几行程序一直在循环,相当于微内核================================ ;sign=1时显示菜单,     ;sign=2时调用reset      ;sign=3时调用硬盘第一扇区                     ;sign=4时显示时钟       ;sign=5时设置时钟       ;这几行程序一直在循环,相当于微内核================================ loopcore:                       mov bx,offset sign        -offset sysboot+7e00h                     mov bl,cs:[bx];  取出菜单选择的数字值         mov bh,0                                        cmp bl,dl ; 检测选择键是否改变                je loopcore1            call clear                                      loopcore1:              mov dl,bl; 暂存用于下次比较                   mov di,offset functionlist-offset sysboot+7e00h                     add bl,bl ;functionlist 每个函数的地址是 2 字节。                   add di,bx               call word ptr cs:[di]                         jmp loopcore    ret                     ;=======================这几行程序一直在循环,相当于微内核=================
 
 
 
  ;sign=2 ;重启系统 reset: mov bx,0ffffh push bx mov bx,0 push bx retf
 
  ;sign=3 ;开机,将booter从0面0道1扇区中读出 startsys: mov ax,0 mov es,ax mov bx,7c00h;es:bx内存数据。
  mov dl,80h;硬盘C ; mov dl, 0h ;软盘0 mov dh,0;0面(磁头) mov ch,0;磁道号 mov cl,1;扇区号 mov al,1;扇区数量 mov ah,2;读扇区 int 13h
  mov bx,offset startsys7c00h-offset sysboot+7e00h jmp dword ptr cs:[bx] startsys7c00h dw 7c00h,0 ret
 
  ;sign=4 showclock:         call gettimedata         call showtimedata ret
  ;sign=5 setclock:                call showtimedata ret
  gettimedata: push si push di push ax          mov si,offset timeaddr  - offset sysboot+7e00h     mov di,offset timedata  - offset sysboot+7e00h           mov cx,6     gettimedatas0:         mov al,cs:[si]         out 70h,al         in  al,71h         mov cs:[di],al         inc si         inc di     loop gettimedatas0 pop ax pop di pop si ret
  showtimestr: push si push bx     mov si,offset timestr  - offset sysboot+7e00h     mov bl,32;列     mov bh,13;行          call showstr pop si pop bx ret
  setfocus: push ax push bx push dx push si push di      mov si,offset focus    - offset sysboot+7e00h mov bl,cs:[si] cmp al,4bh jne rightfocus     cmp bl,0     jne focusdec         mov bl,11         jmp showfocus          focusdec:         dec bl         jmp showfocus
 
  rightfocus: cmp al,4dh jne showfocus cmp bl,11     jne focusinc         mov bl,0         jmp showfocus              focusinc:         inc bl         jmp showfocus           showfocus: mov cs:[si],bl;保存移动后的光标索引值       mov di,offset focusplaces - offset sysboot+7e00h mov bh,0 mov dl,cs:[di+bx];取出光标的实际位
  mov ah,2 mov bh,0 mov dh,13;行 add dl,32;列      int 10h ;setfocusquit: pop di pop si pop dx pop bx pop ax          ret
  settime: push si push di push ax push bx push cx push dx push bp
  call scantodigit      mov bp,offset timedata  -offset sysboot +7e00h
 
  mov bx,offset focus     - offset sysboot+7e00h mov bl,cs:[bx]    ;取出光标索引值 mov bh,0
  mov dx,bx and dx,1b ;如果focus单数时,取出timedata[focus/2],用键入值对应timedata[focus/2+1]            shr bx,1
  add bp,bx
  cmp dl,0 jne getts1               ;如果focus是双数时,键入值对应timedata[focus/2],取出timedata[focus/2+1]     mov dh,cs:[bp]     shl al,1     shl al,1     shl al,1     shl al,1     and dh,1111b     or al,dh     jmp gett2      getts1:     ;如果focus是单数时,取timedata[focus/2],用键入值对应timedata[focus/2+1]     mov dh,cs:[bp]     and dh,11110000b     or al,dh             gett2:          mov di,offset timelimitb-offset sysboot +7e00h      mov si,offset timelimita-offset sysboot +7e00h                       mov dl,cs:[di+bx];时钟的最小允许值     mov dh,cs:[si+bx];时钟的最大允许值                      ;用timedata[focus/2][focus/2+1] 与时钟最大允许值,和最小允计值比较                      ;判断键入的时钟最是否可用,如果可用                      ;则把timedata[focus/2][focus/2+1]填入timedata     cmp al,dl     jb quitgettime     cmp al,dh     ja quitgettime     ;call bcdtochar     mov cs:[bp],al           quitgettime: pop bp pop dx pop cx pop bx pop ax pop di pop si ret
  showtimedata: push si push di push ax push bx push cx      mov si,offset timedata  - offset sysboot+7e00h mov di,offset timestr   - offset sysboot+7e00h       mov cx,6 showclocks0:                mov al,cs:[si]     call bcdtochar          mov cs:[di+0],ah     mov cs:[di+1],al     add di,3     inc si loop showclocks0 mov si,offset timestr  - offset sysboot+7e00h mov bl,32;列 mov bh,13;行 call showstr showclockquit: pop cx pop bx pop ax pop di pop si ret
  newint9: push ax push bx push es      in al,60h
  mov bx,0 mov es,bx pushf mov bx,offset oldint9addr-offset sysboot+7e00h call dword ptr es:[bx] call keycapture      pop es pop bx pop ax       iret
  setint9: push di push ax push es push ds      mov ax,0 mov es,ax
  mov bx,offset oldint9addr-offset sysboot+7e00h push es:[9*4] pop es:[bx] push es:[9*4+2] pop  es:[bx+2]
  cli mov word ptr es:[9*4],offset newint9-offset sysboot+7e00h mov word ptr es:[9*4+2],0 sti
  pop ds pop es pop ax pop di
  ret ;在bh行,bl列,显si开始处的中以0结尾的字符 showstr:;9E push es push ax push di push cx push bx push bp      mov ax,0b800h mov es,ax
  mov al,160;每行显示80个字符,显示一个字要两字节内存1每个字符1字节,颜色1字 mul bh   ;dh是行数
  mov cx,bx;保存bx mov bh,0 ;总列数保存在ax
  add ax,bx;计算列数,如果用add al,bl会溢位出错 add ax,bx;计算列数,字符1字节,颜色1字节,所以加两次
  mov di,ax;目标地址 mov bx,cx;恢复bx mov bp,offset color-offset sysboot+7e00h mov ah,cs:[bp];高字节存放颜色 mov ch,0 showstr1:     mov al,cs:[si];低字节是数据     mov es:[di],ax;高字节是颜色        inc si        add di,2     mov cl,al     jcxz showstr2     jmp showstr1 showstr2:  ;D7     pop bp     pop bx     pop cx     pop di     pop ax     pop es ret
  ;展示界面================================================= showmenu: push bx push bp ;在10行,30列显示菜单 ; mov di,160*10+30*2 mov bh,10 mov bl,30 ;保存在直接定址表的绝对位置 mov bp,offset menudata-offset sysboot+7e00h ;菜单有5行 mov cx,5 s1:     ;这里相当于外循环,每次一行     ;获取menudata中每行的保存位置的偏移地址     mov si,ds:[bp]     ;调用内循环函数,输出一行的每个字符     call showstr     ;下一行偏移地址     add bp,2     ;下一行显示     inc bh     loop s1 pop bp pop bx ret
 
  clear: push bx push dx push cx push es       mov bx,0b800h mov es,bx mov bx,0 mov ds,bx
  mov bx,0 mov dx,0700h   ;清屏中对字符属性设置应该为07h,而不是0 mov cx,2000     clear1:     mov es:[bx],dx     add bx,2     loop clear1 pop es pop cx pop dx pop bx ret
  endloopcore:         mov bx,offset sysboot-offset oldint9addr         push es:[bx]         pop es:[9*4]         push  es:[bx+2]         pop es:[9*4+2]         mov ah,4ch         int 21h ret
  saveclock:     push ax     push si     push di     mov di,offset timedata  -offset sysboot +7e00h     mov si,offset timeaddr  -offset sysboot +7e00h          mov cx,6     saveclocks:         mov al,cs:[si]         out 70h,al         mov al,cs:[di]         out 71h,al         inc di         inc si     loop saveclocks          pop di     pop si     pop ax      ret scantodigit:         mov ah,al         cmp al,0bh         jne gettnum1              mov al,0             jmp quitscantodigit         gettnum1:             cmp al,2             jb quitscantodigit                                   cmp al,0bh             ja quitscantodigit                 dec al         quitscantodigit: ret
 
 
  resetfocus:         push ax         push bx         push dx             mov ah,2             mov bh,0             mov dh,25             mov dl,0             int 10h         pop dx         pop bx         pop ax ret
  ;al 是bcd码,返回ah高字符,al低字符 bcdtochar:         push dx                  mov dl,al                        shr al,1             shr al,1             shr al,1             shr al,1             add al,30h             mov ah,al             mov al,dl             and al,1111b             add al,30h               pop dx ret
  keycapture: keycheck:         push ax         push bx         push dx         push di                           mov bx, offset sign-offset sysboot+7e00h         mov ah,cs:[bx]                  cmp al,3bh; F1 改变颜色         jne keyF2         mov bx, offset color-offset sysboot+7e00h         inc byte ptr cs:[bx]         jmp quitkeycheck                                            keyF2:          cmp al,3ch ; 接F2时设置sign=0,退出循环。         jne keymenu         mov byte ptr cs:[bx],0;  endloopcore         jmp quitkeycheck                               ;================================================================            ;1、只在三种状态下接收扫描码 1、sign=1 菜单状态 2、sign =4 显示clock 3、 sign=5 时置clock         ;         ;在菜单状态下,如果按不是1、2、3、4跳转到结束。               keymenu:         mov ah,cs:[bx]         cmp ah,1         jne keyshowclock         cmp al,2         jb quitkeycheck         cmp al,5         ja quitkeycheck
          keymenu1:             mov cs:[bx],al  ;由于键码刚好与sign对应所以直接将sign置为al即可                      jmp quitkeycheck          ;===============================================================         ;在显示时钟状态下只检测esc         keyshowclock:          cmp ah,4         jne keysetclock         cmp al,1         jne quitkeycheck         mov cs:[bx],al                      jmp quitkeycheck         ;===============================================================                           ;===============================================================         ;设置时钟时:         ;1、检测四个按键,左箭头,右箭头 ess,enter         ;2、检测1,2,3,4,5,6,7,8,9,0         ; 4个菜单键检测完成,跳转到结束。         keysetclock:         cmp ah,5         jne quitkeycheck         ;假如键码小于2或大于b则说明不是0-9,改为判断是否为方向键         cmp al,2         jb keyleft          cmp al,0bh         ja keyleft                  call settime                  keyleft:         cmp al,4bh         jne keyright                  call setfocus                  keyright:         cmp al,4dh         jne keyesc                            call setfocus                  keyesc:         cmp al,1         jne keyenter                  mov cs:[bx],al                  keyenter:         cmp al,1ch         jne quitkeycheck                  call saveclock                  ;=================================================================         quitkeycheck:         pop di         pop dx         pop bx         pop ax ret
  sysbootend:nop ;=======================上面是A盘2至4扇区内容===========================                          ;offset sysbootend-offset sysboot之间的内容是拷贝到A盘2-4扇区的内容。                            ;=======================上面是A盘2至4扇区内容===========================
 
 
  ;==========================下面是A盘1扇区内容===========================                                  ;boot:磁盘第一扇区被加载到7c00h                                  ;引导扇区的功能是实现把2,3,4,5扇区的                             ;加载到内7e00h,并把转跳到7e00h.                                         ;=========================下面是A盘1扇区内容============================= boot:                          mov ax,0               mov es,ax              mov bx,7e00h;es:bx内存数据。        
          mov dl,0;0软区         mov dh,0;0面(磁头)                           mov ch,0;磁道号                              mov cl,2;扇区号                              mov al,3;扇区数量                            mov ah,2;读扇区                              int 13h       
          mov bx,offset s7e00-offset boot+7c00h                              jmp dword ptr cs:[bx]                        s7e00 dw 7e00h,0                     endboot:nop            ;====================================================================
  testRun7e00h:
          mov ax,cs         mov ds,ax                  mov si,offset sysboot         mov ax,0h         mov es,ax         mov di,7e00h         mov cx,offset sysbootend-offset sysboot         cld         rep movsb
 
          mov bx,offset s7e00h-offset sysboot         jmp dword ptr cs:[bx]         s7e00h dw 7e00h,0         testRun7e00hEnd:nop              ret
 
  copyToDiskAsector:         mov ax,cs         mov ds,ax    ;ds:si是安装源         mov si,offset boot
          mov ax,data         mov es,ax         mov di,offset bootdata
 
          mov cx,offset endboot-offset boot         cld         rep movsb         
          mov ax,data         mov es,ax         mov bx,offset bootdata;es:bx内存数据。
          mov dl,0;0软区         mov dh,0;0面(磁头)         mov ch,0;磁道号         mov cl,1;扇区号         mov al,1;扇区数量         mov ah,3;写扇区         int 13h
          mov ax,cs         mov es,ax         mov bx,offset sysboot;es:bx内存数据。
          mov dl,0;0软区         mov dh,0;0面(磁头)         mov ch,0;磁道号         mov cl,2;扇区号         mov al,3;扇区数量         mov ah,3;写扇区         int 13h                  mov ax,0         mov es,ax         mov bx,7c00h;es:bx内存数据。
          mov dl,0;0软区         mov dh,0;0面(磁头)         mov ch,0;磁道号         mov cl,1;扇区号         mov al,1;扇区数量         mov ah,2;读扇区         int 13h
          mov bx,offset s7c00h         jmp dword ptr ds:[bx]         s7c00h dw 7c00h,0                  mov ah,4ch         int 21h copyToDiskAsectorEnd:nop
 
  start: call copyToDiskAsector ; call testRun7e00h code ends
  end start
   |