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
|