In the first program in chapter 3 of "writing an operating system by yourself", the author did not take out the program that can be used as the guiding sector and compiled it. But when it is executed in bochs, bochs will prompt that the boot disk is not found, and then disassemble the binfile. After seeing that there is no 0xaa55 mark at the end of the file for the boot disk 510th and 511 bytes, you need to write the 0xaa55 Mark into the boot disk.
I tried a lot of methods. To save space, I will post the last method I used. This method imitates the program posted by the author in the first program in chapter 1, that is, first calculates the length of the Code that was actually implemented before, and then fills the content (510-length) with 0, the last two bytes are written as 0xaa55. The complete program is appended with the following analysis principles.
times 510-(4+(GDTLen1+3)/4*4+(SegCode16Len+3)/4*4+(SegCode32Len)) db 0dw 0xAA55
Of course, in Chapter 3, this program is more complex than in Chapter 1. First, the procedures in Chapter 3 involve sub-sections. Therefore, in chapter 1, the procedure 510-($-$) because $ indicates the beginning of the current section, you need to calculate the length of the three sections separately. The second reason is that the first part of the section is alignment. The following describes the solutions to these two problems.
To get the length of each section, you can simply record it at the beginning and end of the section, as shown below.
[Section. gdt] label_gdt: descriptor 0, 0, 0; empty descriptor: descriptor 0, segcode32len-1, da_c + da_32; inconsistent code snippet: descriptor 0b8000h, 0 ffffh, da_drw; the first display address: gdtlenequ $-label_gdt; gdt length: gdtptrdwgdtlen-1; gdt boundary: dd0; gdt base address: hour-bottom-label_gdtgdtlen1 equ $. gdt]
The first alignment is discussed below. After the first problem was solved, I thought that using the length of each section and to represent the length of the program, the result was wrong, or the boot disk could not be found. Through disassembly, I found the following two problems: one is that the number of 0 supplements is always too large, indicating that the length of the program is missing, second, the code at the beginning of each section of the program is always different from that of the source program after disassembly, which indicates that some additional code is generated between the two sections, causing the anti-assembler to be cheated. The following two pieces of code: the code on the left is the section at the junction of the 16-bit part and the 32-bit part in the source program, the code on the right is the disassembly code at the same position, and the disassembly code in the red area, suspicious code.
mov cr0, eaxjmp dword SelectorCode32:0 , [SECTION .s32][BITS 32]LABEL_SEG_CODE32: mov ax, SelectorVideo mov gs, ax mov edi, (80 * 11 + 79) * 2 |
00007C72 0F22C0 mov cr0,eax00007C75 66EA000000000800 jmp dword 0x8:0x000007C7D 0000 add [bx+si],al00007C7F 0066B8 add [bp-0x48],ah00007C82 1000 adc [bx+si],al00007C84 8EE8 mov gs,ax00007C86 BF7E07 mov di,0x77e |
It is suspicious that there are several consecutive zeros in the red code after disassembly, So I immediately thought about whether it is for the first alignment of the Section. To verify this idea, let's look at the disassembly instruction of the first instruction in this program.
00007C00 E92100 jmp word 0x7c24
This command requires the program to jump to 0x7c24. According to the source code, this is the first address of the 16-bit code. The disassembly code near 0x7c24 is shown below. The source disassembly code is shown in the left figure. The adjusted disassembly code is shown in the figure below, and the corresponding part of the code in the source program is shown in the right figure. 0x7c24 is the starting point of the program. So what is 0x7c24 or above? Or a group of 0. On the Right of the analysis, the blue area is pseudocode, that is, the green area is followed by the Area 0x7 C24. What is the blue area? It is the data. After calculation, the 6-byte data should be 23, which is converted into a hexadecimal system, which is exactly 0x0000000017, as shown in the green part of the graph. Well, there are two bytes between the red and green in the graph. We have more reason to believe that this is an alignment setting, because there is no code and no data in this area, the only feature is that we are at the intersection of two sections, and we are only one step away from the truth. Perform the following calculation to calculate the total number of bytes in the 16 code zone, which is 0x52. It is found that 0x52 is not a multiple of 4, while 0x52 + 2 = 0x54 is a multiple of 4, the added 2 is exactly the two bytes between the red and green areas in the graph. Other lab areas are also established.
The truth is, NASM handles this process when compiling this program: each section is 4 aligned. Therefore, if we simply add the length of all sections together to get the length of the program, the length obtained will inevitably be too small. We should consider the areas that sacrifice for alignment, so we have the formula: actual number of occupied nodes = (number of valid bytes + 3)/4*4, this formula is applied.
00007C1C 17 pop ss00007C1D 0000 add [bx+si],al00007C1F 0000 add [bx+si],al00007C21 0000 add [bx+si],al00007C23 008CC88E add [si-0x7138],cl00007C27 D88EC08E fmul dword [bp-0x7140]00007C2B D0BC0001 sar byte [si+0x100],100007C2F 6631C0 xor eax,eax00007C32 8CC8 mov ax,cs00007C34 66C1E004 shl eax,0x4 |
00007C1C 17 pop ss00007C1D 0000 add [bx+si],al00007C1F 0000 add [bx+si],al00007C21 0000 add [bx+si],al00007C23 0000007C24 8CC88E 00007C27 D88EC08E fmul dword [bp-0x7140]00007C2B D0BC0001 sar byte [si+0x100],100007C2F 6631C0 xor eax,eax00007C32 8CC8 mov ax,cs00007C34 66C1E004 shl eax,0x4 |
Gdtptr DW gdtlen-1; gdt boundary dd 0; gdt base address selectorcode32 equ label_desc_code32-label_gdt Selectorvideo equ label_desc_video-label_gdt Gdtlen1 equ $-label_gdt [section. s16] [bits 16] label_begin: mov ax, CS mov ds, ax mov es, ax mov SS, ax mov sp, 0100 h xor eax, eax mov ax, cs shl eax, 4 |
So far, a major problem of writing the Boot Sector has been solved. The Code 3.1 update is shown below, hoping to help the confused users.
% Include "PM. INC "; constant, Macro, and some descriptions org07c00hhaha_begin: jmplabel_beginqianlen equ $-haha_begin [section. gdt] label_gdt: descriptor 0, 0, 0; empty descriptor: descriptor 0, segcode32len-1, da_c + da_32; inconsistent code snippet: descriptor 0b8000h, 0 ffffh, da_drw; the first memory address: gdtlenequ $-label_gdt; gdt length: gdtptrdwgdtlen-1; gdt boundary: dd0; gdt base address: selectorcode32equlabel_desc_code32 _ Desc_video-label_gdtgdtlen1 equ $-label_gdt [section. s16] [bits16] label_begin: movax, csmovds, axmoves, axmovss, axmovsp, 0100 hxoreax, eaxmovax, csshleax, 4 addeax, role [limit + 2], axshreax, 16 movbyte [forward + 4], almovbyte [forward + 7], ahxoreax, eaxmovax, dsshleax, 4 addeax, label_gdt; eax <-gdt base address movdword [gdtptr + 2], eax; [gdtptr + 2] <- Gdt base address lgdt [gdtptr] cliinal, 92 horal, kernel, almoveax, cr0oreax, 1movcr0, eaxjmpdword selectorcode32: 0; execute this statement to load selectorcode32 into CS and jump to code32selector: segcode16len equ $-label_begin [section. s32] [bits32] label_seg_code32: movax, selectorvideomovgs, ax; video segment Selection Sub-(destination) movedi, (80*11 + 79) x 2; screen 11th rows, 79th columns. Movah, 0ch; 0000: Black Bottom 1100: red letter moval, 'A' mov [GS: EDI], axjmp $ segcode32lenequ $-label_seg_code32; end of [section. s32] times 510-(4 + (gdtlen1 + 3)/4*4 + (segcode16len + 3)/4*4 + (segcode32len) dB 0dw 0xaa55