当前位置:网站首页>Assembly instance analysis -- boot program, kernel program, user program, load disk file
Assembly instance analysis -- boot program, kernel program, user program, load disk file
2022-07-19 00:32:00 【raindayinrain】
1.1. Bootstrap
First of all 16 In bit real mode , Then open A20, Enter protection mode .
Install segment descriptor , Load the kernel program from disk to physical memory .
Install segment descriptors for kernel programs & to update gdt, Complete segment relocation for the kernel program .
; Master bootstrap : Located in logical sector 0
; kernel : Located in logical sector 1
; application : Located in logical sector 50
; Apply the disk data to be loaded : Located in logical sector 100
; Specify a specific value for the label
; It looks like the meaning of the starting physical location of the kernel process in the physical memory
core_base_address equ 0x00040000
; The number of the first sector of the kernel program on the disk
; Specify a specific value for the label
core_start_sector equ 0x00000001
; Just enter the main boot program
; The process is located in physical memory 0x0000:0x7c00 It's about ,cs The content is 0x0000
mov ax,cs
; Set stack register
mov ss,ax
; Set the stack top register , The highest position of the stack
mov sp,0x7c00
; Will specify the beginning of physical memory 4 Bytes are loaded into registers
mov eax,[cs:pgdt+0x7c00+0x02]
; take edx Zero clearing
xor edx,edx
; Set up ebx by 16
mov ebx,16
; edx:eax / 16, merchant eax, remainder edx
div ebx
; This is a 4 Segment address of byte physical memory location
mov ds,eax
; This is a 4 Intra segment offset of byte physical memory location
mov ebx,edx
; 8 Byte data expansion
; 0x00 0xcf 0x92 0x00 0x00 0x00 0xff 0xff
; High position <----- Low position
; Segment base address 31~24 G D/B L AVL Segment boundary 19~16 P DPL S TYPE Segment base address 23~16 Segment base address 15~0 Segment boundary 15~0
; Segment base address :0x00 0x00 0x00 0x00, It means that the segment base address is 0x0000 0000
; G by 1, It means that the segment boundary is in pages
; D/B by 1, It means that the data in the segment is 32 Bit
; L by 0, Retain
; AVL by 0, Reserved for software
; Segment boundary 0xf 0xff 0xff,0xfffff,
; P by 1, Indicates that the contents of the segment are already in physical memory
; DPL by 0, The privilege level of the segment
; S by 1, Non system segment
; TYPE by 0x2, Indicates that the segment is readable , Writable data segments
mov dword [ebx+0x08],0x0000ffff
mov dword [ebx+0x0c],0x00cf9200
; 8 Byte data expansion
; 0x00 0x40 0x98 0x00 0x7c 0x00 0x01 0xff
; High position <----- Low position
; Segment base address 31~24 G D/B L AVL Segment boundary 19~16 P DPL S TYPE Segment base address 23~16 Segment base address 15~0 Segment boundary 15~0
; Segment base address :0x00 0x00 0x7c 0x00, It means that the segment base address is 0x0000 7c00
; G by 0, It means that the segment boundary is in bytes
; D/B by 1, It means that the data in the segment is 32 Bit
; L by 0, Retain
; AVL by 0, Reserved for software
; Segment boundary 0x0 0x01 0xff,0x001ff,
; P by 1, Indicates that the contents of the segment are already in physical memory
; DPL by 0, The privilege level of the segment
; S by 1, Non system segment
; TYPE by 0x8, The representation segment is an execution only code segment
mov dword [ebx+0x10],0x7c0001ff
mov dword [ebx+0x14],0x00409800
; 8 Byte data expansion
; 0x00 0xcf 0x96 0x00 0x7c 0x00 0xff 0xfe
; High position <----- Low position
; Segment base address 31~24 G D/B L AVL Segment boundary 19~16 P DPL S TYPE Segment base address 23~16 Segment base address 15~0 Segment boundary 15~0
; Segment base address :0x00 0x00 0x7c 0x00, It means that the segment base address is 0x0000 7c00
; G by 1, It means that the segment boundary is in pages
; D/B by 1, It means that the data in the segment is 32 Bit
; L by 0, Retain
; AVL by 0, Reserved for software
; Segment boundary 0xf 0xff 0xfe,0xffffe,
; P by 1, Indicates that the contents of the segment are already in physical memory
; DPL by 0, The privilege level of the segment
; S by 1, Non system segment
; TYPE by 0x6, Indicates that the segment is readable , Writable stack segment
mov dword [ebx+0x18],0x7c00fffe
mov dword [ebx+0x1c],0x00cf9600
; 8 Byte data expansion
; 0x00 0x40 0x92 0x0b 0x80 0x00 0x7f 0xff
; High position <----- Low position
; Segment base address 31~24 G D/B L AVL Segment boundary 19~16 P DPL S TYPE Segment base address 23~16 Segment base address 15~0 Segment boundary 15~0
; Segment base address :0x00 0x0b 0x80 0x00, It means that the segment base address is 0x000b 8000
; G by 0, It means that the segment boundary is in bytes
; D/B by 1, It means that the data in the segment is 32 Bit
; L by 0, Retain
; AVL by 0, Reserved for software
; Segment boundary 0x0 0x7f 0xff,0x07fff,
; P by 1, Indicates that the contents of the segment are already in physical memory
; DPL by 0, The privilege level of the segment
; S by 1, Non system segment
; TYPE by 0x2, Indicates that the segment is readable , Writable data segments
mov dword [ebx+0x20],0x80007fff
mov dword [ebx+0x24],0x0040920b
; Set the specified physical memory location 2 Byte is the specified value
mov word [cs: pgdt+0x7c00],39
; take gdt Size , The starting physical location informs the processor
lgdt [cs: pgdt+0x7c00]
; open a20 Address line , So the process can use 32 Bit address space
in al,0x92
or al,0000_0010B
out 0x92,al
; No interruptions
cli
; Enter protection mode
mov eax,cr0
or eax,1
mov cr0,eax
; A jump instruction is used to realize the transition from real mode to protected mode
jmp dword 0x0010:flush
[bits 32]
flush:
; The corresponding segment selector is 1
mov eax,0x0008
; This is a base address 0x00000000, Have 4GB Data segment of addressing space
mov ds,eax
; The corresponding segment selector is 3
mov eax,0x0018
; This is the base address 0x7c00, Downward growing stack segment
mov ss,eax
; Initial execution high address
; The starting position +esp That's the physical address
; Segment limit value in descriptor *0x1000 + 0xFFF + 1 <= [ESP- Operand length ] <= 0xFFFFFFFF
; 0xffffe*0x1000+0xFFF+1 = 0xFFFFF000
; The actual physical address = Stack base address +ESP
; Valid address range :
; 0x7c00+0xFFFFF000 = 00006c00
; Valid address range :
; 0x7c00+0xFFFFFFFF = 00007bFF
; Stack address range [0x00006c00, 0x00007bFF]
; The initial time :0x7c00
xor esp,esp
mov esp, 0xffffffff
; The disk block is offset within the segment of the starting position of physical memory
; Marked 4 Byte settings edi
mov edi,core_base_address
; Logical number of the disk block
; Marked 4 Byte settings eax
mov eax,core_start_sector
; Set up ebx,ebx Is the physical memory offset
mov ebx,edi
; Trigger function call
call read_hard_disk_0
; Remove from the disk block located in physical memory 4 Put the bytes in eax
mov eax,[edi]
; Zero clearing edx
xor edx,edx
mov ecx,512
; edx:eax / 512, merchant eax, remainder edx
; eax The regular value of the number of disk sectors corresponding to the process size is stored
; The process already has a disk sector in physical memory
div ecx
or edx,edx
; If edx No 0, It indicates that the number of disk sectors occupied by the process is eax+1
jnz @1
; If edx yes 0, It indicates that the number of disk sectors occupied by the process is eax
dec eax
; Come here ,eax On behalf of , The number of disk sectors occupied by the rest of the process
@1:
or eax,eax
; If the process has been completely copied to physical memory
jz setup
; ecx Is the number of disk sectors
mov ecx,eax
mov eax,core_start_sector
; eax Is the first logical number in the disk sector to be copied
inc eax
@2:
; Copy the data of several sectors specified on the disk to the corresponding location of physical memory
call read_hard_disk_0
; Update the logical sector code
inc eax
; Specify the number of cycles
loop @2
; At this time, all processes have been copied to physical memory
setup:
; This is a gdt Starting physical location
mov esi,[0x7c00+pgdt+0x02]
; 4 Kernel size of bytes
; 4 Byte public routine segment start assembly address
; 4 Byte kernel data segment start assembly address
; 4 Byte kernel code segment start assembly address
; Kernel entry point 【 paragraph , The offset 】
; 4 Byte common routine segment start assembly address
mov eax,[edi+0x04]
; 4 Byte kernel data segment start assembly address
mov ebx,[edi+0x08]
; Distance between segments
sub ebx,eax
; Distance between segments minus 1, What is calculated in this way is the segment boundary
dec ebx
; edi Represents the starting physical address of the kernel
; eax Represents the starting assembly address of the common routine segment
; After adding, the starting physical address of the public routine segment
add eax,edi
; take ecx Set to 4 Byte value
; Segment base address 31~24 G D/B L AVL Segment boundary 19~16 P DPL S TYPE Segment base address 23~16 Segment base address 15~0 Segment boundary 15~0
; G D/B L AVL yes 0b0100
; P DPL S TYPE yes 0b1001 1000
; This is a G by 0,D/B by 1,L,AVL by 0, Segment boundaries are in bytes , The label value in the segment is 32 Bit
; This is a P by 1,DPL by 0,S by 1, Segment is already in physical memory , Non system segment
; TYPE by 8, Execute only code snippets
mov ecx,0x00409800
; eax Is the starting physical location of the segment
; ebx It's a boundary
; ecx The effect is unknown
; Function call
call make_gdt_descriptor
; kernel gdt
; 8 Empty descriptor of bytes
; 8 Global data segment of bytes
; 8 Initial code segment of bytes
; 8 Initial stack segment of bytes
; 8 Byte text mode video memory
; 8 Byte common routine segment
; 8 Byte core data segment
; 8 Byte core code segment
; This is the setup 8 Byte descriptor
; eax It's low 4 byte
; edx It's high 4 byte
; constitute 8 Byte kernel common routine segment
mov [esi+0x28],eax
mov [esi+0x2c],edx
; eax yes
mov eax,[edi+0x08]
mov ebx,[edi+0x0c]
sub ebx,eax
; ebx Is the segment boundary of the kernel data segment
dec ebx
; eax Is the starting physical location of the kernel data segment
add eax,edi
; Segment base address 31~24 G D/B L AVL Segment boundary 19~16 P DPL S TYPE Segment base address 23~16 Segment base address 15~0 Segment boundary 15~0
; G D/B L AVL yes 0b0100
; P DPL S TYPE yes 0b1001 0010
; This is a G by 0,D/B by 1,L,AVL by 0, Segment boundaries are in bytes , The label value in the segment is 32 Bit
; This is a P by 1,DPL by 0,S by 1, Segment is already in physical memory , Non system segment
; TYPE by 2, Read only , Writable data segments
mov ecx,0x00409200
call make_gdt_descriptor
; constitute 8 Byte core data segment
mov [esi+0x30],eax
mov [esi+0x34],edx
mov eax,[edi+0x0c]
mov ebx,[edi+0x00]
sub ebx,eax
; ebx Is the segment boundary of the kernel code segment
dec ebx
; eax Is the starting physical location of the kernel code segment
add eax,edi
; Segment base address 31~24 G D/B L AVL Segment boundary 19~16 P DPL S TYPE Segment base address 23~16 Segment base address 15~0 Segment boundary 15~0
; G D/B L AVL yes 0b0100
; P DPL S TYPE yes 0b1001 0010
; This is a G by 0,D/B by 1,L,AVL by 0, Segment boundaries are in bytes , The label value in the segment is 32 Bit
; This is a P by 1,DPL by 0,S by 1, Segment is already in physical memory , Non system segment
; TYPE by 8, Executable only code segment
mov ecx,0x00409800
call make_gdt_descriptor
; constitute 8 Byte core code segment
mov [esi+0x38],eax
mov [esi+0x3c],edx
; gdt Size
mov word [0x7c00+pgdt],63
; take gdt Size , The starting physical location informs the processor
lgdt [0x7c00+pgdt]
; Take out the entry point segment , Entry point offset , To jump , This will jump to the kernel entry point to transfer from the main boot program to the kernel
jmp far [edi+0x10]
; eax Is the starting logical sector of the disk
; ebx The disk data to be copied is offset within the segment of the physical memory segment
; A functional process
read_hard_disk_0:
; Save the register that will be polluted by the function first , For subsequent recovery
push eax
push ecx
push edx
push eax
mov dx,0x1f2
mov al,1
; towards 0x1f2 Port write 1
; Tell the disk the number of sectors to be transferred
out dx,al
inc dx
; eax Stack recovery
pop eax
; towards 0x1f3 Port write eax Low position 1 byte
out dx,al
inc dx
mov cl,8
;
shr eax,cl
; towards 0x1f4 Port write eax Lower order of 1 byte
out dx,al
inc dx
shr eax,cl
; towards 0x1f5 Port write eax The second low of 1 byte
out dx,al
inc dx
shr eax,cl
; Keep it high 4 position 0x1110
or al,0xe0
; towards 0x1f6 Port write 1 byte , high 4 Is it 0x1110, low 4 Is it 28 High of bit logical sector code 4 position
out dx,al
inc dx
mov al,0x20
; towards 0x1f7 Port write 0x20, Tell the disk to start transferring data
out dx,al
.waits:
; from 0x1f7 Read 1 byte
in al,dx
; Keep only the first one 7 position , The first 3 position 【 from 0 Calculation 】
and al,0x88
; The disk is not busy , Data transmission is equal when the disk is ready
cmp al,0x08
; The cycle waiting condition holds
jnz .waits
; Complete the movement of a disk block from the disk to the specified location of physical memory
; Frequency control
mov ecx,256
; 0x1f0
mov dx,0x1f0
.readw:
; From port 0x1f0 Read 2 Byte to register
in ax,dx
; take 2 Byte data is stored in physical memory
mov [ebx],ax
add ebx,2
loop .readw
pop edx
pop ecx
pop eax
ret
; eax Is the starting physical position of the segment
; ebx It's a boundary
; ecx The effect is unknown
; return
; eax It's constructed 8 Low bit descriptor 4 position
; edx It's constructed 8 The height of the bit descriptor 4 position
; 8 Byte data expansion
; 0x00 0x40 0x92 0x0b 0x80 0x00 0x7f 0xff
; High position <----- Low position
; Segment base address 31~24 G D/B L AVL Segment boundary 19~16 P DPL S TYPE Segment base address 23~16 Segment base address 15~0 Segment boundary 15~0
; Segment base address :0x00 0x0b 0x80 0x00, It means that the segment base address is 0x000b 8000
; G by 0, It means that the segment boundary is in bytes
; D/B by 1, It means that the data in the segment is 32 Bit
; L by 0, Retain
; AVL by 0, Reserved for software
; Segment boundary 0x0 0x7f 0xff,0x07fff,
; P by 1, Indicates that the contents of the segment are already in physical memory
; DPL by 0, The privilege level of the segment
; S by 1, Non system segment
; TYPE by 0x2, Indicates that the segment is readable , Writable data segments
make_gdt_descriptor:
; take eax Store in edx
mov edx,eax
; eax high 16 Bit is now the original low 16 position -->eax The height of 16 Bit is the segment base address low 16 position
shl eax,16
; eax It's low 16 Bit adoption ebx It's low 16 position --》eax It's low 16 Bits are segment boundaries 15~0
or ax,bx
; Retain edx The height of 16 position , What remains is the original eax The height of 16 position
and edx,0xffff0000
; high 8 Bit is the base address 23~16, low 8 Bit is the base address 31~24
rol edx,8
; After byte Exchange , high 8 Bit is the base address 31~24, low 8 Bit is the base address 23~16
bswap edx
; take bx Set to 0
xor bx,bx
; edx The height of 16 Low bit 4 Bit is set to the height of the segment boundary 4 position
or edx,ebx
; edx The height of 16 Low bit 8 The height of a bit 4 Bit is set to ecx The value in ,edx It's low 16 The height of a bit 8 Bit adoption ecx The value in
or edx,ecx
ret
pgdt dw 0
dd 0x00007e00
times 510-($-$$) db 0
db 0x55,0xaa1.2. Kernel program
Continue installing the descriptor of the kernel segment , to update gdt
Load user programs from disk into physical memory ,
Construct segment descriptors for each segment of the user program & to update gdt,
Complete segment relocation for user program ,
Complete symbol relocation for the symbol table of the user program ,
Transfer control to the user program .
About stack segment 8 Bit descriptor construction :
1. Base address +ESP The highest address of the initial pointing segment
2. With 4KB Is the segment of the boundary , Segment boundary calculation method = 0xFFFFF - Particle size 【 How many? 4KB】
The proof process is omitted .
Other considerations :
1. Some assembly instructions are only supported on specific machines , such as cmovnz Not supported on this computer .
2. Stack segment ESP The initial setting is 0x0000000, Some machines will report errors , Some won't .
; Set the label to the specified value
core_code_seg_sel equ 0x38
; Set the label to the specified value
core_data_seg_sel equ 0x30
; Set the label to the specified value
sys_routine_seg_sel equ 0x28
; Set the label to the specified value
video_ram_seg_sel equ 0x20
; Set the label to the specified value
core_stack_seg_sel equ 0x18
; Set the label to the specified value
mem_0_4_gb_seg_sel equ 0x08
; The above setting label value does not occupy the actual physical memory space and disk space
; 4 Kernel size of bytes
core_length dd core_end
; 4 Byte kernel common routine segment offset 【 The offset between the starting position of the kernel common segment and the starting position of the kernel process 】
sys_routine_seg dd section.sys_routine.start
; 4 Byte kernel segment offset
core_data_seg dd section.core_data.start
; 4 Byte kernel code segment offset
core_code_seg dd section.core_code.start
; The entry point of the kernel
; 4 Byte entry point offset
core_entry dd start
; 2 Segment offset of bytes -- The selector is 7, This selector corresponds to the descriptor of the kernel code segment
dw core_code_seg_sel
; Just mark , The kernel code snippet is 32 Bit
[bits 32]
; Kernel common routine segment
SECTION sys_routine vstart=0
; This is a function
; Display string to screen
; Input :
; ebx The intra segment offset of the first character to be displayed
put_string:
; preservation ecx Existing value
push ecx
.getc:
mov cl,[ebx]
or cl,cl
; If the character value is 0, Indicates the terminator
jz .exit
; On the screen cl
call put_char
; take ebx Move to the offset of the next character to be displayed
inc ebx
jmp .getc
.exit:
; recovery ecx
pop ecx
; Out of the stack , The process jump callback is used in the next position
retf
; Yes cl Chinese characters are processed
put_char:
; perform pushad, In turn EAX、ECX、EDX、EBX、ESP、EBP、ESI、EDI Push ,
; After execution ESP = Before execution ESP - 32
pushad
mov dx,0x3d4
mov al,0x0e
; towards 0x3d4 write in 0x0e
out dx,al
inc dx
; from 0x3d5 Read in 1 Bytes to al
in al,dx
; This is the cursor position high 8 position
mov ah,al
; dx Turn into 0x3d4
dec dx
mov al,0x0f
; towards 0x3d4 write in 0x0f
out dx,al
inc dx
; from 0x3d5 Read in 1 Bytes to al
in al,dx
; here bx The cursor position is stored ,16 position
mov bx,ax
; If the character to be processed is 0x0d
cmp cl,0x0d
; No 0x0d
jnz .put_0a
; Here to 0x0d Perform display processing
; Save the cursor position to ax
mov ax,bx
mov bl,80
; ax / 80, merchant ah remainder ,al merchant ,
div bl
; al * bl = ax
mul bl
; bx Press the cursor position 80 Rounded value , This means "enter"
mov bx,ax
; Set cursor position , Let carriage return reflect its function
jmp .set_cursor
; The pending character is not 0x0d, It's not a return
.put_0a:
; If cl yes 0x0a
cmp cl,0x0a
; cl No 0x0a
jnz .put_other
; take bx Move to the corresponding position of the next line
add bx,80
; Scroll the whole screen up one line , One more line at the bottom is uniformly displayed as blank . Cursor position with bx Whichever comes first .
jmp .roll_screen
; At this time cl It can only be an ordinary character to be displayed
.put_other:
; take es Put it on the stack
push es
mov eax,video_ram_seg_sel
; The corresponding segment selector is 4, This is text mode video memory
mov es,eax
; Multiply the cursor position by 2 Get the position of the corresponding position character in the video memory
shl bx,1
; Setting up video memory
mov [es:bx],cl
; recovery es
pop es
; recovery bx
shr bx,1
; to update bx Make it point to the next character position to be displayed
inc bx
; When the next display position crosses the screen , Just scroll
.roll_screen:
cmp bx,2000
jl .set_cursor
push ds
push es
mov eax,video_ram_seg_sel
mov ds,eax
mov es,eax
cld
mov esi,0xa0
mov edi,0x00
mov ecx,1920
rep movsd
mov bx,3840
mov ecx,80
.cls:
mov word[es:bx],0x0720
add bx,2
loop .cls
pop es
pop ds
; If scrolling happens , The cursor notification is displayed at the first position of the last line
mov bx,1920
.set_cursor:
mov dx,0x3d4
mov al,0x0e
out dx,al
inc dx
mov al,bh
out dx,al
dec dx
mov al,0x0f
out dx,al
inc dx
mov al,bl
out dx,al
popad
ret
; Set the logical sector eax The starting address of copying from disk to physical memory is ebx Region
read_hard_disk_0:
; Register stack save
push eax
push ecx
push edx
push eax
mov dx,0x1f2
mov al,1
; towards 0x1f2 write in 1, Indicates the number of disk sectors to read
out dx,al
inc dx
; eax Put it on the stack
pop eax
; towards 0x1f3 Write logical sector number is low 8 position
out dx,al
inc dx
mov cl,8
shr eax,cl
; towards 0x1f4 The write logical sector number is lower 8 position
out dx,al
inc dx
shr eax,cl
; towards 0x1f5 Write the logical sector lower 8 position
out dx,al
inc dx
shr eax,cl
or al,0xe0
; towards 0x1f6 write in 1 byte , high 4 Bit means LBA On the main disk , low 4 Is it 28 The height of the bit start logical sector 4 position
out dx,al
inc dx
mov al,0x20
; towards 0x1f7 write in 0x20, Notify the disk to start working
out dx,al
.waits:
; from 0x1f7 Read 1 byte
in al,dx
and al,0x88
cmp al,0x08
; Keep waiting , Know that the disk is not busy and is ready for data transmission
jnz .waits
mov ecx,256
mov dx,0x1f0
.readw:
; from 0x1f0 Read 2 Bytes to ax
in ax,dx
; ebx At the beginning, the offset of the starting position of the physical area corresponding to the disk block is stored
mov [ebx],ax
; Update next offset
add ebx,2
loop .readw
; Register recovery
pop edx
pop ecx
pop eax
retf
; take edx Medium 32 The digit value is parsed in hexadecimal and displayed on the screen
put_hex_dword:
; take eax,ecx,edx,ebx,esp,ebp,esi,edi Stack in turn
pushad
; ds Also save on the stack
push ds
; The selector is 6, Core data segment , The segment base address has been set
mov ax,core_data_seg_sel
mov ds,ax
; This is the kernel data segment description 0~F Start offset of string
mov ebx,bin_hex
; ecx Set to 8, loop 8 Time
mov ecx,8
.xlt:
; edx yes 32 Bit to be pressed 16 The value displayed in hexadecimal
rol edx,4
mov eax,edx
; eax It's low 4 Bit reserved edx low 8 High in the middle 4 position
and eax,0x0000000f
; This is to achieve 4 Bits correspond to 16 Characters under base
; DS:[BX+AL] Take out a byte and send it to al
xlat
; ecx Put it on the stack
push ecx
; al As characters to be displayed
mov cl,al
; Show
call put_char
; recovery ecx
pop ecx
; loop
loop .xlt
; recovery ds
pop ds
; Restore each register
popad
; The function returns
retf
; Memory allocation
; Before distribution
; [ram_alloc] The last position after the last allocation is stored .
; ecx The size of this application is stored
; After the distribution
; [ram_alloc] The last position after this allocation is stored .
; ecx The last trailing position before allocation is stored
allocate_memory:
; ds Put it on the stack
push ds
; eax Put it on the stack
push eax
; ebx Put it on the stack
push ebx
; The segment selector is 6, Is the core data segment . The segment base address has been set .
mov eax,core_data_seg_sel
; Set as core data segment
mov ds,eax
; Will specify the location 4 Put the bytes in eax
mov eax,[ram_alloc]
; take 4 Bytes plus ecx
add eax,ecx
; ecx Store the original 4 byte
mov ecx,[ram_alloc]
; take eax The value is stored in ebx
mov ebx,eax
; take ebx low 2 Location 0
and ebx,0xfffffffc
; take ebx Add... To the original basis 4
add ebx,4
; test eax low 2 Are all bits 0
test eax,0x00000003
; Not for 0 Next ,eax It is set to the original value and adjusted to 4 The value after the multiple of 【 Magnified 】.
; yes 0 Next , It is 4 Byte Alignment
;cmovnz eax,ebx
mov eax, ebx
; take eax write in ram_alloc. This is the position with the assigned size .
mov [ram_alloc],eax
;
pop ebx
pop eax
pop ds
retf
; take edx:eax Representative 8 Bit descriptor write gdt The tail . Notify the processor again .
; cx The new write item distance is stored gdt Start position offset
set_up_gdt_descriptor:
; Register stack save
push eax
push ebx
push edx
push ds
push es
; The segment selector is 6, Is the core data segment . The segment base address has been set .
mov ebx,core_data_seg_sel
; Set as core data segment
mov ds,ebx
; hold gdtr Register 6 Bytes are stored in a specific location
; gdt Size and starting physical location of
sgdt [pgdt]
mov ebx,mem_0_4_gb_seg_sel
; The segment selector is 1, This is a 8 Global data segment of bytes
mov es,ebx
; from [pgdt] Indicates that the physical memory location is fetched 2 byte ,0 Expand to 4 Byte data is moved into ebx
movzx ebx,word [pgdt]
; ebx low 16 Digit value plus 1
inc bx
; The physical memory location will be specified 4 Bytes are stored ebx
; gdt Starting physical location [ low 16 All of them 0]
; ebx Point to gdt The last position of all current elements
add ebx,[pgdt+2]
; The physical memory location will be specified 4 The byte is set to eax
mov [es:ebx],eax
; The physical memory location will be specified 4 The byte is set to edx
mov [es:ebx+4],edx
; take [pgdt] Physical memory location value plus 8
add word [pgdt],8
; Tell the processor gdt The size of the , Starting physical location
lgdt [pgdt]
; New size
mov ax,[pgdt]
; dx Set to 0
xor dx,dx
; bx Set to 8
mov bx,8
; dx:ax / 8, merchant ax, remainder dx
div bx
; merchant
mov cx,ax
; Zoom in to 8 times , This starts with the last write 8 Byte distance gdt Offset of starting position
shl cx,3
; Register recovery
pop es
pop ds
pop edx
pop ebx
pop eax
retf
; eax The physical starting position of the segment is stored
; ebx Store 20 Segment boundaries of bits
; ecx Stored in the peer location G D/B L AVL P DPL S TYPE This information
; 8 Byte data expansion
; 0x00 0x40 0x92 0x0b 0x80 0x00 0x7f 0xff
; High position <----- Low position
; Segment base address 31~24 G D/B L AVL Segment boundary 19~16 P DPL S TYPE Segment base address 23~16 Segment base address 15~0 Segment boundary 15~0
; Segment base address :0x00 0x0b 0x80 0x00, It means that the segment base address is 0x000b 8000
; G by 0, It means that the segment boundary is in bytes
; D/B by 1, It means that the data in the segment is 32 Bit
; L by 0, Retain
; AVL by 0, Reserved for software
; Segment boundary 0x0 0x7f 0xff,0x07fff,
; P by 1, Indicates that the contents of the segment are already in physical memory
; DPL by 0, The privilege level of the segment
; S by 1, Non system segment
; TYPE by 0x2, Indicates that the segment is readable , Writable data segments
make_seg_descriptor:
; take eax Store in edx
mov edx,eax
; high 16 The bit is now the original low 16 position , low 16 Bit is set to 0
shl eax,16
; low 16 Bit adoption bx The median , This is the low limit of the segment 16 position
or ax,bx
; edx Keep high only 16 position , It's primitive eax Middle high 16 position
and edx,0xffff0000
; high 8 Bit is primitive eax high 16 Low bit 8 position , low 8 Bit is primitive eax The height of 8 position
rol edx,8
; Byte swapping
; high 8 Bit is primitive eax The height of 8 position , low 8 Bit is primitive eax high 16 Low bit 8 position
bswap edx
; bx Set to 0
xor bx,bx
; take edx Secondary high 8 A low 4 Bit is set to 20 The height of the bit segment boundary 4 position
or edx,ebx
; take edx Secondary high 8 Bitheight 4 position , Secondary height 8 Bit is set to ecx The value of the corresponding position in
or edx,ecx
retf
; Kernel data segment
SECTION core_data vstart=0
; Temporary storage gdt For dynamic modification
pgdt dw 0
dd 0
; At present, the rear position of the available area
ram_alloc dd 0x00100000
; label
salt:
; 256 Byte string
salt_1 db '@PrintString'
times 256-($-salt_1) db 0
; 4 Intra segment offset of bytes
dd put_string
; 2 Segment selector of bytes
dw sys_routine_seg_sel
salt_2 db '@ReadDiskData'
times 256-($-salt_2) db 0
dd read_hard_disk_0
dw sys_routine_seg_sel
salt_3 db '@PrintDwordAsHexString'
times 256-($-salt_3) db 0
dd put_hex_dword
dw sys_routine_seg_sel
salt_4 db '@TerminateProgram'
times 256-($-salt_4) db 0
dd return_point
dw core_code_seg_sel
; The size of the above item
salt_item_len equ $-salt_4
; Number of items
salt_items equ ($-salt)/salt_item_len
; String ending with terminator
message_1 db ' If you seen this message,that means we '
db 'are now in protect mode,and the system '
db 'core is loaded,and the video display '
db 'routine works perfectly.',0x0d,0x0a,0
; String ending with terminator
message_5 db ' Loading user program...',0
; String ending with terminator
do_status db 'Done.',0x0d,0x0a,0
; String ending with terminator
message_6 db 0x0d,0x0a,0x0d,0x0a,0x0d,0x0a
db ' User program terminated,control returned.',0
; A string of characters with a specific meaning
bin_hex db '0123456789ABCDEF'
; A buffer that occupies a certain size of physical memory
core_buf times 2048 db 0
; occupy 4 Bytes of physical memory
esp_pointer dd 0
; String ending with terminator
cpu_brnd0 db 0x0d,0x0a,' ',0
; A buffer that occupies a certain size of physical memory
cpu_brand times 52 db 0
; String ending with terminator
cpu_brnd1 db 0x0d,0x0a,0x0d,0x0a,0
; Kernel code snippet
SECTION core_code vstart=0
; The function loads the application from the specified location on the disk to the specified physical memory location
; Complete the construction of segment descriptor for application & Apply the relocation of the inner segment of the head segment
; Relocate each symbol reference in the symbol table that applies the header segment
load_relocate_program:
; All registers that will be polluted in the process are saved first
push ebx
push ecx
push edx
push esi
push edi
push ds
push es
; Set up ds For kernel data segment
mov eax,core_data_seg_sel
mov ds,eax
; Set up eax Is the logical sector of the disk
mov eax,esi
; ebx Is the intra segment offset of a buffer in the kernel data segment
mov ebx,core_buf
; take esi The first disk sector , Read in ds:ebx Specified physical memory
call sys_routine_seg_sel:read_hard_disk_0
; This is the application header block
; Take the head 4 byte , This applies dimensions
mov eax,[core_buf]
; Put in ebx
mov ebx,eax
; Take out the tail 9 position
and ebx,0xfffffe00
; take ebx add 512
add ebx,512
; test eax low 9 Are all bits 0
test eax,0x000001ff
; Not all 0 Next , take ebx Put in eax
; This guarantee eax The size in is 512 An integral multiple , At the same time, this size can accommodate the application size
;cmovnz eax,ebx
mov eax, ebx
; take eax Set to ecx
mov ecx,eax
; Perform memory allocation
; Before distribution
; [ram_alloc] The last position after the last allocation is stored .
; ecx The size of this application is stored
; After the distribution
; [ram_alloc] The last position after this allocation is stored .
; ecx The last trailing position before allocation is stored
call sys_routine_seg_sel:allocate_memory
; ebx The last trailing position before allocation is stored , This is also the starting physical address of the new free space
mov ebx,ecx
; ebx Put it on the stack
push ebx
; Empty edx
xor edx,edx
; take ecx Set to 512
mov ecx,512
; edx:eax / 512, merchant eax, In this way, the quotient is just able to provide the required size 512 Number of unit sizes
div ecx
; take eax Set to ecx,ecx The number of times to read is stored
mov ecx,eax
; This is the global data segment
mov eax,mem_0_4_gb_seg_sel
; Set up ds Point to global data segment , To access all 4GB Memory space
mov ds,eax
; esi Is the first logical number applied to the disk
mov eax,esi
.b1:
; Set the disk sector eax Read into the physical memory segment with an offset of ebx Starting position
; ebx It will be automatically increased after each reading 512 byte
call sys_routine_seg_sel:read_hard_disk_0
; eax increase , Point to the next disk sector
inc eax
loop .b1
; The above completes the allocation of physical memory space , The operation of copying all blocks of disk application to the allocated physical memory space in turn
; Pass in the starting address of available physical memory edi
pop edi
; use edi Set up eax
mov eax,edi
; What we need to do here is to build segment descriptors for each segment in the application & to update gdt
; Segment relocation of the application header segment
; Relocate the symbol table in the application header segment
; Set up ax To point to the selector of the application header segment
; -----next
; Construct for the head segment 8 Bit descriptor
; Read the size of the head segment in the application header
mov ebx,[edi+0x04]
; subtract 1, Get the segment boundary
dec ebx
; Set it up eax, It means that this is 32 position , Segment boundaries are bytes , Can be read , Writable data segments
mov ecx,0x00409200
; eax Represents the segment base address
; ebx Represents the segment boundary
; ecx Represents information such as signs
; obtain 8 The bit segment descriptor is stored in edx:eax
call sys_routine_seg_sel:make_seg_descriptor
; use edx:eax in 8 Bit descriptor added to gdt, Notification processor
; cx The new write item distance is stored gdt Start position offset , This actually happens to be the requirement of symbol segment selection
call sys_routine_seg_sel:set_up_gdt_descriptor
; Set segment selector
mov [edi+0x04],cx
; This is the starting physical memory address of the entire application
mov eax,edi
; edi Is the starting physical memory location of the application
; [edi+0x14] yes 4 Byte code segment offset
; such eax Is the physical starting position of the code segment
add eax,[edi+0x14]
; [edi+0x18] yes 4 Byte code segment size
mov ebx,[edi+0x18]
; Code segment boundaries
dec ebx
; In bytes ,32 position , Code segment
mov ecx,0x00409800
call sys_routine_seg_sel:make_seg_descriptor
call sys_routine_seg_sel:set_up_gdt_descriptor
; [edi+0x14] Instead, store the corresponding segment selector
mov [edi+0x14],cx
mov eax,edi
; [edi+0x1c] in 4 Bytes store the segment offset
; Get the starting physical memory location of the application data segment
add eax,[edi+0x1c]
; [edi+0x20] in 4 Bytes store the data segment size
mov ebx,[edi+0x20]
; Segment boundaries
dec ebx
; In bytes ,32 position , Readable and writable data segments
mov ecx,0x00409200
call sys_routine_seg_sel:make_seg_descriptor
call sys_routine_seg_sel:set_up_gdt_descriptor
; [edi+0x1c] Change to storage 2 Segment selector of bytes
mov [edi+0x1c],cx
; The above completes the header segment for the application , Code segment , Data segment 8 Bit descriptor construction
; And repositioning in the head segment
; Next, allocate an independent application stack segment for the application
; Take out 4 byte , Values are 1
mov ecx,[edi+0x0c]
; ebx Set to 0x000fffff
mov ebx,0x000fffff
; 0x000fffff - 1 = 0x000ffffe
; This starts with 4KB The segment boundary calculation method of segment
sub ebx,ecx
; Set up eax by 4096
mov eax,4096
; eax * 4 Number of bytes = edx:eax
; 4096 * 1 = 4096
mul dword [edi+0x0c]
; Size in bytes
mov ecx,eax
; Allocate additional physical memory space
; Perform memory allocation
; Before distribution
; [ram_alloc] The last position after the last allocation is stored .
; ecx The size of this application is stored
; After the distribution
; [ram_alloc] The last position after this allocation is stored .
; ecx The last trailing position before allocation is stored
call sys_routine_seg_sel:allocate_memory
; eax = Size in bytes + Last last last position before allocation
; eax This is the new rear position
; Particularity of stack segment base address : The base address is the maximum address that a segment can reach
add eax,ecx
; Set up ecx
; With 4KB Segment boundaries in units ,32 position , Can be read , Writable stack segment
mov ecx,0x00c09600
; eax The physical starting position of the segment is stored --- Stack segment , The highest position of the stack is stored
; ebx Store 20 Segment boundaries of bits
; ecx Stored in the peer location G D/B L AVL P DPL S TYPE This information
call sys_routine_seg_sel:make_seg_descriptor
call sys_routine_seg_sel:set_up_gdt_descriptor
; Relocate the selector that allows it to store stack segments
mov [edi+0x08],cx
; Next, we will complete the relocation of each symbol in the symbol table in the application header segment
; es Set to Corresponding segment selector
mov eax,[edi+0x04]
; es Is the selector of the application header segment
mov es,eax
; Set up ds Point to the corresponding segment selector
mov eax,core_data_seg_sel
; ds It is the selector of the core data segment
mov ds,eax
; The relocation of the symbol table is a double cycle
; Data copy , positive
cld
; This is the initialization of the outermost layer of the double-layer loop
; Specify physical memory location 4 byte , Number of terms
; Control the execution times of the outermost loop
mov ecx,[es:0x24]
; Set up edi by 0x28, This is the starting offset of the first term
; Control the first execution of the outermost loop edi The direction of
mov edi,0x28
.b2:
; The number of items is saved in the stack
; ecx Put it on the stack
push ecx
; The initial offset of the first item is saved on the stack
; edi Put it on the stack
push edi
; This is a es:edi And ds:esi Match by match
; At the beginning of each time esi Point to the offset of the current item to be matched in the kernel segment
; When the match is successful , Would be right es:edi Point to the content for relocation
; This is a core Number of items in the middle
; obtain core The number of items inside
mov ecx,salt_items
; This is a core The intra segment offset of the first item in
; Set up esi by core The starting position of the first item inside is offset
mov esi,salt
; Maximum cycle core The number of times in the middle
.b3:
; The starting offset of the application item
; edi Put it on the stack -- Pointing application
push edi
; core The starting offset of the middle term
; esi Put it on the stack --- Point to core
push esi
; core Number of items in the middle
; ecx Put it on the stack
push ecx
; Set up ecx by 64
; Set up ecx by 64
mov ecx,64
; repeat 64 Time , Compare double words every time
; 64*4 = 256
; es:edi ds:esi
repe cmpsd
; The results are not equal , To b4
; The results are not equal , To express with core The current item does not match
jnz .b4
; This is a es:edi And ds:esi perfect match
; here [esi] Take out the symbol corresponding to the kernel example segment 4 Offset in byte segment
mov eax,[esi]
; This is before the corresponding symbol will be applied 4 The byte is set to the intra segment offset of the routine corresponding to the kernel symbol
mov [es:edi-256],eax
; here [esi+4] Take out 2 Byte is the segment selector of the symbol corresponding to the kernel routine segment
mov ax,[esi+4]
; This is the corresponding symbol that will be applied 5,6 The byte is set as the segment selector of the routine corresponding to the kernel symbol
mov [es:edi-252],ax
.b4:
; because es:edi Mismatch
; At this time , Need to put es:edi String match with the next symbol item in the kernel
; recovery ecx-- kernel core Number of items
pop ecx
; recovery esi-- The starting offset of the kernel entry
pop esi
; take esi Update to kernel core The starting offset of the next item of the current item
add esi,salt_item_len
; recovery edi-- The starting offset of the application item
pop edi
; Cycle back .b3
loop .b3
; recovery edi, This is the intra segment offset of the first item applied
pop edi
; edi Point to the in segment offset to apply the next item
add edi,256
; recovery ecx, This is the number of items to be matched in the application
pop ecx
; Cycle back .b2
loop .b2
; Set up ax Select sub for application header segment
mov ax,[es:0x04]
; End of the process , Register recovery
pop es
pop ds
; End of the process , Register recovery
pop edi
pop esi
pop edx
pop ecx
pop ebx
; Full application loading and relocation
; 1. Load disk applications into physical memory
; 2. Complete the settings for each segment of the application 8 Bit descriptor & to update gdt
; 3. Complete segment relocation for each segment of the application
; 4. Complete relocation for each symbol in the applied symbol table
; 5. Set up ax Select sub for application header segment
ret
start:
mov ecx,core_data_seg_sel
; Set up ds In order to select the core data segment
mov ds,ecx
; Set up ebx Point to the start offset of the string
mov ebx,message_1
; Display the string on the screen
call sys_routine_seg_sel:put_string
; First set up eax
mov eax,0x80000002
; Point to cpuid In this way, processor information can be obtained
cpuid
; Store the information in the specified physical memory location -- In the kernel data segment
mov [cpu_brand + 0x00],eax
mov [cpu_brand + 0x04],ebx
mov [cpu_brand + 0x08],ecx
mov [cpu_brand + 0x0c],edx
; First set up eax
mov eax,0x80000003
; Point to cpuid In order to obtain processor information
cpuid
; Store the processor information in the specified physical memory location
mov [cpu_brand + 0x10],eax
mov [cpu_brand + 0x14],ebx
mov [cpu_brand + 0x18],ecx
mov [cpu_brand + 0x1c],edx
; First set up eax
mov eax,0x80000004
; Re pass cpuid Get processor information
cpuid
; Store the processor information in the specified physical memory location
mov [cpu_brand + 0x20],eax
mov [cpu_brand + 0x24],ebx
mov [cpu_brand + 0x28],ecx
mov [cpu_brand + 0x2c],edx
; 16*3 = 48 byte
mov ebx,cpu_brnd0
; Display the information , Is format control
call sys_routine_seg_sel:put_string
mov ebx,cpu_brand
; Display processor information
call sys_routine_seg_sel:put_string
mov ebx,cpu_brnd1
; display information , Format control information
call sys_routine_seg_sel:put_string
; display string
mov ebx,message_5
; display information
call sys_routine_seg_sel:put_string
; Set up esi by 50
mov esi,50
; ds At this time, it points to the kernel data segment
; Point to load & Reposition the application process
call load_relocate_program
; Video memory status
mov ebx,do_status
call sys_routine_seg_sel:put_string
; Storage at this time esp To the specified physical memory location
mov [esp_pointer],esp
; Set up ds by ax,ax The meaning is in load_relocate_program Set in the
; It should be the application header segment selector
mov ds,ax
; Process far jump
jmp far [0x10]
; It is explained here that after the application is executed , Return to the kernel
return_point:
; Set up ds Execute kernel data segment
mov eax,core_data_seg_sel
mov ds,eax
; Set up ss Execute kernel stack segment
mov eax,core_stack_seg_sel
mov ss,eax
; Set up esp Is the value of the kernel stack segment before jump
mov esp,[esp_pointer]
; display string
mov ebx,message_6
call sys_routine_seg_sel:put_string
; downtime
hlt
SECTION core_trail
core_end:1.3. Applications
Load data from the specified location on the disk , And output and display the loaded data information screen .
; Head segment
SECTION header vstart=0
; 4 Byte application size
program_length dd program_end
; 4 Byte size of this segment 【 Before relocation 】& Segment selector 【 After repositioning 】
head_len dd header_end
; 4 Byte segment start offset 【 Before relocation 】& Storage stack segment selector 【 After repositioning 】
stack_seg dd 0
; 4 byte , Stack size
stack_len dd 1
; 4 byte , Offset within the entry point segment
prgentry dd start
; 4 Byte code segment start offset 【 Before relocation 】& Segment selector 【 After repositioning 】
code_seg dd section.code.start
; 4 Byte code segment size
code_len dd code_end
; 4 Byte data segment start offset 【 Before relocation 】& Segment selector 【 After repositioning 】
data_seg dd section.data.start
; 4 Byte segment size
data_len dd data_end
; Number of items in the symbol table , Number of items in the symbol table
salt_items dd (header_end-salt)/256
salt:
; 256 Characters , Symbol strings 【 Before relocation 】&6 Entry address of byte symbol 【 After repositioning 】
PrintString db '@PrintString'
times 256-($-PrintString) db 0
; 256 Characters , Refer to the foregoing
TerminateProgram db '@TerminateProgram'
times 256-($-TerminateProgram) db 0
; 256 Characters , Refer to the foregoing
ReadDiskData db '@ReadDiskData'
times 256-($-ReadDiskData) db 0
header_end:
SECTION data vstart=0
buffer times 1024 db 0
message_1 db 0x0d,0x0a,0x0d,0x0a
db '**********User program is runing**********'
db 0x0d,0x0a,0
message_2 db ' Disk data:',0x0d,0x0a,0
data_end:
[bits 32]
; Before entering the user program ,
; ds It has been set up , It should be the selector of the application header segment
SECTION code vstart=0
start:
mov eax,ds
; Set up fs
mov fs,eax
;
mov eax,[stack_seg]
; Set the application stack segment , The base address is the highest address of the segment
mov ss,eax
; Stack segments are consistent at the beginning esp Point to 0
mov esp,0
mov esp,0xffffffff
mov eax,[data_seg]
; Set the application data segment
mov ds,eax
; Set the intra segment offset of the display string
mov ebx,message_1
; Perform a remote jump , Display the string in the application header segment with the help of kernel routines
call far [fs:PrintString]
; Set up eax by 100
mov eax,100
; Set up ebx Execute intra segment offset 【 The offset of the segment where the physical memory of the disk block starts 】
mov ebx,buffer
; The disk logical sector 100 The disk data of is read to the specified location of the application data segment
call far [fs:ReadDiskData]
; With the help of kernel routines , Display user segment string
mov ebx,message_2
call far [fs:PrintString]
; With the help of kernel routines , Display user segment string
mov ebx,buffer
call far [fs:PrintString]
; Execute kernel routines ---TerminateProgram
; This routine is expected to transfer control to the kernel code segment
jmp far [fs:TerminateProgram]
code_end:
SECTION trail
program_end:The so-called memory space allocation , But the kernel program delimits a piece of memory by itself , Let this memory load the specified data . And the kernel itself knows it .
The kernel is responsible for the management of all hardware resources of the system , Distribute , maintain .
边栏推荐
- ans1编码解析
- Clean the disk with CMD command (mainly the system disk)
- 带领全网朋友,完成粉笔登录加密分析,再次换种玩法
- Openpose: real time multiplayer 2D pose estimation using partial affinity fields
- What do LETV employees rely on to live a "fairy life" without a boss?
- 原子类及CAS
- Vs publish websites using webdeploy
- WordPress Theme sharing: flatsome theme v3.15.7 download the latest version in 2022 for free
- 开发到底要不要转行软件测试?一篇足以 最全方位分析
- Kubesphere deployment
猜你喜欢

WordPress主题分享:Avada主题v7.8.0免费下载 2022年最新版
Master-slave separation of database

Word2Vec Skip-gram 模型實現

WordPress主题分享:Flatsome主题v3.15.7免费下载 2022年最新版

【论文阅读】YOLOv7: Trainable bag-of-freebies sets new state-of-the-art for real-time object detectors

2022 latest Chinese Camtasia studio computer recording screen tool

微信小程序开发学习3(WXSS模板和全局配置)

Shell's third day small exercise: access the self built nextcloud network disk service through the self built DNS server

如何设计接口测试用例?(文末送接口测试用例模板)
![[untitled]](/img/e1/01e7a5bf3976a4434cdc91647b684d.png)
[untitled]
随机推荐
Business is too busy. Is there really no reason to have time for automation?
C语言的内存管理-堆、栈等
Why is nodejs so fast?
Master-slave separation of database
[paper reading] yolov7: trainable bag of freebies sets new state of the art for real-time object detectors
Collection of various materials about websocket
Redis has three modes -- master-slave replication, sentinel mode, and cluster
笔记
【CANN训练营】基于昇腾CANN平台的AI CPU算子开发
Rocky foundation shell script create Yum source
The difference between cookies and session and JWT
Daily question 1: merge two sorted linked lists (Sword finger offer25)
外部PLC触发VisionMaster多流程运行PLC部分特殊说明
[Vulnhub] Raven-2 (mysql-UDF提权)
2022-07-15 网工进阶(十九)BGP-状态机、对等体之间的交互原则、影响对等体关系建立的因素、对等体表、路由表、详细路由表、路由属性
2022最新汉化camtasia studio电脑录制屏幕工具
Mysql的redolog和binlog
2022 latest Chinese Camtasia studio computer recording screen tool
Wechat applet Development Learning 3 (wxss Template and Global configuration)
【无标题】