Wang Shuang course design of assembly language 2
- The most important thing to master a programming language is practice. Wang Shuang's teacher's Curriculum Design II, if you write 400 to 800 lines of code completely, and complete this curriculum design independently, you will be proficient in 16 bit assembly and master the essence of 8086 assembly. This course design is not convenient for debugging. It will take a little time to complete independently. You may think that assembly is out of date and there is no need to waste time to study it carefully. However, learning assembly language is a shortcut to understand the principle of computer, and assembly language is the foundation of all languages. If you only know high-level language, you can only design things for others. You can only use API to give functions. If you learn to assemble and learn to program again, you will feel "Tao" in your heart, long sword in your hand. There is a kind of world where you can wield your passion and desire. There is no limit to your imagination and conception because of any function of a certain language. After learning assembly, you will know how lovely C language is as a hello world. Complete the course design of Professor Wang Shuang. 2. You will not learn the concept of object-oriented, because in the process of typing hundreds of lines of messy code, you will feel that one thing you urgently need is "Object-Oriented". Completed the course design 2, for the concept of pointer, you will never be confused, the opposite will feel more cordial, because you and his father pointer are already good friends, and the pointer his mother intimate contact, advertising so far, thank teacher Wang Shuang again!
1, Design requirements:
-
Write a self bootable computer that does not need to run in an existing operating system environment
After power on, the CPU automatically enters the FFF0:0 unit for execution, where there is a jump instruction. After the CPU executes the instruction, it turns to execute the hardware system detection and initialization program in BIOS.The initialization program will establish the interrupt vector supported by BIOS, that is, the entry address of the interrupt history provided by BIOS is registered in the interrupt vector table.
After the completion of hardware system detection and initialization, INT 19H is called to boot the operating system.
If it is set to start the operating system from floppy disk, INT 19H will mainly complete the following work:
(1) Control floppy drive 0, read the contents of sector 1 of 0 channel 0 side to 0:7C 00.
(2) Point CS:IP to 0:7C 00.
The 0-channel 0-side 1 sector of the floppy disk contains the operating system boot program. After INT 19H installs it at 0:7C 00, the CPU is set to execute the boot program from 0:7C 00, and the operating system is activated to control the computer.
If there is no floppy disk in No.0 floppy drive, or there is a floppy I/O error, INT 19H will mainly complete the following work;
(1) Read the contents of 0 channel, 0 plane and 1 sector of hard disk C to 0:7C 00;
(2) Point CS:IP to 0:7C 00.
The task of this course design is to write a program that can start the computer by itself without running in the existing operating system environment.
The functions of the program are as follows:
(1) List the function options and let the user select through the keyboard. The interface is as follows:
1) reset pc; restart the computer
2) Start system; boot the existing operating system
3) Clock; enter clock program
4) Srt clock; set time
(2) Restart the computer after the user enters "1". (Note: consider FFFF:0)
(3) Boot the existing operating system after the user enters "2". (Note: consider 0-channel, 0-plane and 1 sector of hard disk C)
(4) After the user enters "3", the program of dynamic reality current date and time is executed.
The actual format is as follows: year / month / day hour: minute: Second
1. Show main menu
2. Display and second refresh clock
3. Set clock, left and right arrows to adjust cursor, esc exit, enter to save
2, Implementation steps
1. Write boot area
Write 512 bytes of boot program to the first sector of A disk. Most computers have no soft driver, which is implemented by vmware virtual machine.
Byte 511 ends with 0aa55h, which is the boot flag.
Write A disk boot area code
mov ax,data mov es,ax mov bx,offset bootdata;es:bx Memory data. mov dl,0;0Soft zone mov dh,0;0Noodles(head) mov ch,0;Track number mov cl,1;Fan area code mov al,1;Sector size mov ah,3;Write Sector int 13h ;====================================================================
The boot sector is the sector 1 of 0-lane-0 side of the disk, which is 512 words and ends with 0aa55h. The above ones can't be exactly 510 bytes, so write the memory area with the size of 512 words and end with 0aa55h first.
data segment bootdata db 510 dup(0) dw 0aa55h data ends ;=========================== ;...... ;=========================== mov ax,cs mov ds,ax ;ds:si Installation source mov si,offset boot mov ax,data mov es,ax mov di,offset bootdata mov cx,offset endboot-offset boot cld rep movsb
2. Boot on load
After power on, the CPU will automatically load the first sector of 0 plane 0 channel 0 of the guide disk to 7c00h of memory. After loading, cs:ip will point to 0:7c00h.
Code to write to sector 1 of 0-plane 0-channel
This code is also the generation that the boot is automatically loaded to 7c00h memory.
;=========================Below is A disc1Sector content============================= boot: mov ax,0 mov es,ax mov bx,7e00h;es:bx Memory data. mov dl,0;0Soft zone mov dh,0;0Noodles(head) mov ch,0;Track number mov cl,2;Fan area code mov al,3;Sector size mov ah,2;Read sector int 13h mov bx,offset s7e00-offset boot+7c00h jmp dword ptr cs:[bx] s7e00 dw 7e00h,0 endboot:nop ;====================================================================
3. Two functions of boot code
1. Load the remaining boot code on the disk into memory.
mov ax,0 mov es,ax mov bx,7e00h;es:bx Memory data. mov dl,0;0Soft zone mov dh,0;0Noodles(head) mov ch,0;Track number mov cl,2;Fan area code mov al,3;Sector size mov ah,2;Read sector int 13h
2. Give control to the rest of the boot code
mov bx,offset s7e00-offset boot+7c00h jmp dword ptr cs:[bx] s7e00 dw 7e00h,0
3, Implementation of core code
1. Design a loop kernel
Because there are three interfaces according to the design requirements
1) Show menu
2) Display and refresh the clock interface
3) Clock setting interface
There are 5 functions in total: display menu, restart, boot from C disk again, display clock, set clock
In order to implement these five functions, a single byte digital sign is designed to mark
1) The scan code of display menu sign=1 ESC is 1, so set sign=1 when the scan code is 1 captured with int 9h
2) Restart sign=2, the scan code of number key 1 is 2, so set sign=2 when the scan code is 2 captured with int 9h
3) Boot sign=3 from disk C again as above
4) Display clock sign=4
5) Set clock sign=5
So the loop kernel only detects the value of sign. sign=1 will refresh the display menu all the time, restart when sign=2, start a new boot when sign=3, refresh the display clock all the time when sign=4, and set the clock when sign=5.
Cyclic code
color db 4 functionlist dw offset endloopcore-offset do0+7e00h dw offset showmenu -offset do0+7e00h dw offset reset -offset do0+7e00h dw offset startsys -offset do0+7e00h dw offset showclock -offset do0+7e00h dw offset setclock -offset do0+7e00h sign db 5 ;Set as0Exit from time to time.1,Display menu,4,Time display clock 5,set clock ;These lines of programs are looping all the time, equivalent to microkernel================================ ;sign=1The menu is displayed, ;sign=2Time call reset ;sign=3Call the first sector of the hard disk ;sign=4Time display clock ;sign=5Time setting clock ;These lines of programs are looping all the time, equivalent to microkernel================================ loopcore: mov bx,offset sign -offset sysboot+7e00h mov bl,cs:[bx]; Take out the numerical value of menu selection mov bh,0 cmp bl,dl ; Check whether the selection key changes je loopcore1 call clear loopcore1: mov dl,bl; Staging for next comparison mov di,offset functionlist-offset sysboot+7e00h add bl,bl ;functionlist The address of each function is 2 Byte. add di,bx call word ptr cs:[di] jmp loopcore ret ;=======================These lines of programs are looping all the time, equivalent to microkernel=================
2. Keyboard capture
There are three states to capture
1) When sgin=1, it is the menu status, and the number 1, 2, 3 and 4 keys are captured.
For example, when you press key 1, the scan code is 2, that is, when you capture the scan code is 2, set sgin=2. The keyboard capture module only sets the value of sign, and does not call other functions. If you call complex functions, int 9 will make unexpected errors. When the value of sign changes, loopcore calls the corresponding function.
2) When sgin=4, it is the clock display state. Only esc key is captured and sgin=1 is set
3) When sgin=5, 1. To capture the number 0 to 9, set the clock. 2. Left and right arrow keys to adjust the cursor position. 3. The ese key exits. 4. Enter saves the clock.
Keyboard capture code
color db 4 sign db 5 ;Set as0Exit from time to time.1,Display menu,4,Time display clock 5,set clock keycheck: push ax push bx push dx push di mov bx, offset sign-offset do0+7e00h mov ah,cs:[bx] cmp al,3bh; F1 Color change jne keyF2 mov bx, offset color-offset do0+7e00h inc byte ptr cs:[bx] jmp quitkeycheck keyF2: cmp al,3ch ; meet F2 Time setting sign=0,Exit the loop. jne keymenu mov byte ptr cs:[bx],0; endloopcore jmp quitkeycheck ;================================================================ ;1,Receive scan code only in three states 1,sign=1 Menu status 2,sign =4 display clock 3, sign=5 Time setting clock ; ;In the menu state, if you press no1,2,3,4Jump to the end. keymenu: mov ah,cs:[bx] cmp ah,1 jne keyshowclock cmp al,2 jb quitkeycheck cmp al,5 ja quitkeycheck mov cs:[bx],al jmp quitkeycheck ;=============================================================== ;Only detect when the clock is displayed esc keyshowclock: cmp ah,4 jne keysetclock cmp al,1 jne quitkeycheck mov cs:[bx],al jmp quitkeycheck ;=============================================================== ;=============================================================== ;When setting the clock: ;1,Test four buttons, left arrow, right arrow ess,enter ;2,Testing1,2,3,4,5,6,7,8,9,0 ; 4Menu key detection completed, jump to the end. keysetclock: cmp ah,5 jne quitkeycheck 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
3. Clock settings
timestr db '00/00/00 00:00:00',0 timedata db 6 dup (0) timelimitb db 0, 1, 1, 0, 0,0 timelimita db 99h,12h,31h,23h,60h,60h
Timedata is a 6-byte memory used to save time data. Instead of putting the clock data directly into timestr, it uses the maximum allowable value of time data, timelimit a, and the minimum allowable value, timelimit B, to check whether it is the allowable value of time setting. If the time data that meets the requirements is put into timedata, you will see that the number is displayed. If the time data that does not meet the requirements is not put into timedata Will not be displayed or saved.
Time setting code
timedata db 6 dup (0) 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 3 settime: push si push di push ax push bx push cx push dx push bp call scantodigit mov bp,offset timedata -offset do0 +7e00h mov bx,offset focus - offset do0+7e00h ;[focusplaces]= 0,1,3,4,6,7,9,10,12,13,15,16 mov bx,cs:[bx] ;Fetch cursor index value mov dx,bx and dx,1b ;If focus When singular, take out timedata[focus/2],Replace with typed value timedata[focus/2+1] shr bx,1 add bp,bx cmp dl,0 jne getts1 ;If focus When double, type a value to replace timedata[focus/2],take out timedata[focus/2+1] mov dh,cs:[bp] shl al,1 shl al,1 shl al,1 shl al,1 and dh,1111b add al,dh jmp gett2 getts1: ;If focus When singular, take timedata[focus/2],Replace with typed value timedata[focus/2+1] mov dh,cs:[bp] and dh,11110000b add al,dh gett2: mov di,offset timelimitb-offset do0 +7e00h mov si,offset timelimita-offset do0 +7e00h mov dl,cs:[di+bx] mov dh,cs:[si+bx] 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
4, Operating environment
Operating system: windows10
Debugging environment: DOSBox 0.74-3
Last operating environment: VMware Workstation Pro15
The complete course design 2 writes data to the floppy disk boot area. If you do not need any tools, you can write data to the floppy disk by running it once under Dos, and then boot the floppy disk drive.
You can see the demonstration effect by running it directly in VMWare DOS. You can see the real boot interface when you reboot.
Operation steps:
1. In the DOS environment of VMWare, compile connection runs.
2. Set the floppy drive boot.
3. Restart to see the boot interface
VMWare settings
1. Edit virtual machine in shutdown state
2. Add floppy
3. Setting up floppy drive boot
5, Debugging of course design 2
1. Debugging of single module
Because the second course is boot code, which leads code data from disk to disk, and a keyboard interrupt code, it is very inconvenient to debug.
You can debug the function of a single module on line 55.
2. Demonstration effect debugging
-
In order to achieve the demonstration effect, when debugging, you can first write the import code to sectors 0, 0 and 1 of disk A, and the rest of the boot code to sectors 2, 3 and 4. Then write the code to simulate int 19h, read the boot code from the boot sector to memory 7c00h, and then point cs:ip to 0:7c00h. If the following code works normally, you can boot normally.
Demo code
copyToDiskAsector: mov ax,cs mov ds,ax ;ds:si Installation source 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 Memory data. mov dl,0;0Soft zone mov dh,0;0Noodles(head) mov ch,0;Track number mov cl,1;Fan area code mov al,1;Sector size mov ah,3;Write Sector int 13h mov ax,cs mov es,ax mov bx,offset sysboot;es:bx Memory data. mov dl,0;0Soft zone mov dh,0;0Noodles(head) mov ch,0;Track number mov cl,2;Fan area code mov al,3;Sector size mov ah,3;Write Sector int 13h mov ax,0 mov es,ax mov bx,7c00h;es:bx Memory data. mov dl,0;0Soft zone mov dh,0;0Noodles(head) mov ch,0;Track number mov cl,1;Fan area code mov al,1;Sector size mov ah,2;Read sector int 13h mov bx,offset s7c00h jmp dword ptr ds:[bx] s7c00h dw 7c00h,0 mov ah,4ch int 21h copyToDiskAsectorEnd:nop
6, About offset addresses
1. All offset label s of the code segment are based on the current CS, that is, the segment is the current CS, and the offset value of the code segment is 0.
2. The difference between jmp label and jmp word ptr [offset label]: suppose that the address represented by the label is A, the former directly jumps to the label to execute the code, and the execution result is IP=A, the latter takes out the address B of double bytes stored in A, and then jumps to B, and the execution effect is IP=B. So is call.
mov bx,offset address -offset boot jmp dword ptr cs:[bx] call dword ptr cs:[bx] address: dw 2000h,0 ;cs:[offset address -offset boot]It can accurately locate address,Not afraid to copy back and forth. ;jmp or call You can jump to0: 2000h
7, Complete code
assume cs:code,ds:data data segment bootdata db 510 dup(0) dw 0aa55h data ends code segment ;=======================Below is A disc2to4Sector content=========================== ;offset sysbootend-offset sysboot The content between is copied to A disc2-4The contents of the sector. ;=======================Below is A disc2to4Sector content=========================== sysboot: jmp near ptr dostart oldint9addr dw 0,0 ;If not offset Error in offset address 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 dw offset md5-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 md5 db 'copyright @ 2020 LiuJianKun,Inc.All rights reserved.',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 5 ;Set as0Exit from time to time.1,Display menu,4,Time display clock 5,set clock 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 ;Capture keyboard, settings9No. interrupt. jmp loopcore ;Cycle through the menu. ;call saveclock ;Debug save clock ;call showclock ;Debug display clock ;================Debug clock settings================ ;mov al,0ah ;call settime ;call showtimedata ;================Debug clock settings================ mov ax,4c00h int 21h ;ret ;These lines of programs are looping all the time, equivalent to microkernel================================ ;sign=1The menu is displayed, ;sign=2Time call reset ;sign=3Call the first sector of the hard disk ;sign=4Time display clock ;sign=5Time setting clock ;These lines of programs are looping all the time, equivalent to microkernel================================ loopcore: mov bx,offset sign -offset sysboot+7e00h mov bl,cs:[bx]; Take out the numerical value of menu selection mov bh,0 cmp bl,dl ; Check whether the selection key changes je loopcore1 call clear loopcore1: mov dl,bl; Staging for next comparison mov di,offset functionlist-offset sysboot+7e00h add bl,bl ;functionlist The address of each function is 2 Byte. add di,bx call word ptr cs:[di] jmp loopcore ret ;=======================These lines of programs are looping all the time, equivalent to microkernel================= ;sign=2 reset: push bx mov bx,offset rebootdata-offset sysboot+7c00h jmp dword ptr cs:[bx] rebootdata dw 0,0ffffh pop bx ret ;sign=3 startsys: mov ax,0 mov es,ax mov bx,7c00h;es:bx Memory data. mov dl,80h;Hard diskC mov dh,0;0Noodles(head) mov ch,0;Track number mov cl,1;Fan area code mov al,1;Sector size mov ah,2;Read sector 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;column mov bh,13;That's ok 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;Save cursor index value after move mov di,offset focusplaces - offset sysboot+7e00h mov bh,0 mov dl,cs:[di+bx];Take out the actual position of the cursor mov ah,2 mov bh,0 mov dh,13;That's ok add dl,32;column 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] ;Fetch cursor index value mov bh,0 mov dx,bx and dx,1b ;If focus When singular, take out timedata[focus/2],Corresponding with the entered value timedata[focus/2+1] shr bx,1 add bp,bx cmp dl,0 jne getts1 ;If focus When it is a double number, type the value corresponding to timedata[focus/2],take out 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: ;If focus If it is singular, take timedata[focus/2],Corresponding with the entered value 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];Minimum allowable value of clock mov dh,cs:[si+bx];Maximum allowed value of clock ;use timedata[focus/2][focus/2+1] Compare with the maximum allowable value and the minimum allowable value of clock ;Determine whether the clock you type is the most available, if available ;Then put timedata[focus/2][focus/2+1]Fill 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;column mov bh,13;That's ok 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 ;stay bh That's ok, bl Column, show si At the beginning0Ending character showstr:;9E push es push ax push di push cx push bx push bp mov ax,0b800h mov es,ax mov al,160;Per row display80Characters, two bytes of memory is required to display a word1Each character1Bytes, color1word mul bh ;dh Row number mov cx,bx;Preservation bx mov bh,0 ;Total column data saved ax add ax,bx;Calculate the number of columns, if usingadd al,bl Overflow error add ax,bx;Count columns, characters1Bytes, color1Byte, so add twice mov di,ax;Destination address mov bx,cx;recovery bx mov bp,offset color-offset sysboot+7e00h mov ah,cs:[bp];High byte storage color mov ch,0 showstr1: mov al,cs:[si];Low byte is data mov es:[di],ax;High byte is color 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 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 ;The character property should be set to07h,Instead of0 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 yes bcd Code, return ah High character, al Low character 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 setcolor: push ax push bx mov bx,offset color-offset sysboot+7e00h mov al,cs:[bx] inc al mov cs:[bx],al pop bx pop ax ret sysbootend:nop ;=======================Above is A disc2to4Sector content=========================== ;offset sysbootend-offset sysboot The content between is copied to A disc2-4The contents of the sector. ;=======================Above is A disc2to4Sector content=========================== ;==========================Below is A disc1Sector content=========================== ;boot:The first sector of the disk is loaded into7c00h ;The function of boot sector is to realize2,3,4,5Sector ;Load into7e00h,And jump to7e00h. ;=========================Below is A disc1Sector content============================= boot: mov ax,0 mov es,ax mov bx,7e00h;es:bx Memory data. mov dl,0;0Soft zone mov dh,0;0Noodles(head) mov ch,0;Track number mov cl,2;Fan area code mov al,3;Sector size mov ah,2;Read sector 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 Installation source 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 Memory data. mov dl,0;0Soft zone mov dh,0;0Noodles(head) mov ch,0;Track number mov cl,1;Fan area code mov al,1;Sector size mov ah,3;Write Sector int 13h mov ax,cs mov es,ax mov bx,offset sysboot;es:bx Memory data. mov dl,0;0Soft zone mov dh,0;0Noodles(head) mov ch,0;Track number mov cl,2;Fan area code mov al,3;Sector size mov ah,3;Write Sector int 13h mov ax,0 mov es,ax mov bx,7c00h;es:bx Memory data. mov dl,0;0Soft zone mov dh,0;0Noodles(head) mov ch,0;Track number mov cl,1;Fan area code mov al,1;Sector size mov ah,2;Read sector 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