📄 start386.asm
字号:
;/++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; we first fetch the information we need from stack passed
; by startstuix subroutine in bootmanager, then setup the
; minium protected mode environment to execute our kernel.
; at beginning of kernel initialize procedure, the kernel
; shares the same stack segment with start386, the stack
; originally belongs to bootmanager which is big enough,
; but most of all, it contains all the parameters, makes
; the kernel easy to fetch them.
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++/
.386p
include pmstruc.inc
include comstruc.inc
cseg1 segment para public 'init_386_code' use16
assume cs:cseg1,ds:dseg
start:
jmp getstart
; our 16 bit code seg use to switch
; back to real mode, how ever the
; processor still works in protected
; mode, we need to switch back
mov eax,cr0
and eax,0fffffffeh
mov cr0,eax ; disable protected mode
; far jump machine code
; this instruction willl bring
; processor to real mode again
db 0eah
dw offset realagain
dw 961ch
; physical seg address, it was calculated
; by 90200h + 5fb0h + 10h, 5fb0h is the
; relative code segment from stuixldr.exe
; 10h is the offset where start386.exe
; residents to its code seg. if stack size
; has been changed in stuixldr, 5fb0h is
; not valid any more, we shall check the
; file 'stuixldr.map' generated by tasm
; again to determine this value
getstart:
; get our parameters
; stack arranges like this
; 28[bp] : data seg for configbuf
; 26[bp] : configbuf offset
; 24[bp] : hdrlen
; 20[bp] : a_text
; 16[bp] : a_data
; 12[bp] : a_bss
; 8[bp] : a_entry
; 4[bp] : a_total
; 2[bp] : cursor position
; [bp] : bp image
; [bp-2] : ds image
cli
push cs
pop ax
add ax,dseg ; patch data segment manually
mov ds,ax
mov es,ax
push bp
mov bp,sp
; get config buf
push ds
mov ax,28[bp]
mov ds,ax
mov si,26[bp]
mov di,offset configbuf
mov cx,1024
cld
repnz movsb
pop ds
; get the last cursor position in real mode
mov ax,2[bp]
mov cursorpos,ax
; format the char string and directly
; write to the text display ram
mov ax,bligreen
push ax
mov ax,offset pmok
push ax
mov ax,offset pmok_raw
push ax
call fmtmes
pop cx
pop cx
pop cx
; initialize the global descriptor table register
push ds
pop ax
movzx ebx,ax
shl ebx,4
add ebx,offset gdt_null_desc
mov dword ptr gdt_desc.table_linear,ebx
lgdt gdt_desc
; start initialize first 386 code segment
mov ax,cseg2
push cs
pop cx
add ax,cx
movzx ebx,ax
shl ebx,4
mov word ptr startup_code_desc.bas_0_15,bx
shr ebx,16
mov byte ptr startup_code_desc.bas_16_23,bl
mov byte ptr startup_code_desc.bas_24_31,bh
; initialize the data segment
push ds
pop ax
movzx ebx,ax
shl ebx,4
mov word ptr startup_data_desc.bas_0_15,bx
shr ebx,16
mov byte ptr startup_data_desc.bas_16_23,bl
mov byte ptr startup_data_desc.bas_24_31,bh
; initialize the stack segment
push ss
pop ax
movzx ebx,ax
shl ebx,4
mov word ptr startup_stack_desc.bas_0_15,bx
shr ebx,16
mov byte ptr startup_stack_desc.bas_16_23,bl
mov byte ptr startup_stack_desc.bas_24_31,bh
; init code segment for kernel
mov eax,es_sym
movzx ebx,ax
shl ebx,4
add ebx,di_sym
mov ax,24[bp] ; hdrlen
movzx eax,ax
add ebx,eax
mov edx,ebx ; backup for latter use
mov word ptr kernel_code_desc.bas_0_15,bx
shr ebx,16
mov byte ptr kernel_code_desc.bas_16_23,bl
mov byte ptr kernel_code_desc.bas_24_31,bh
; init data segment for kernel
mov ebx,edx ; start after kernel code seg
xor eax,eax
mov ax,22[bp]
shl eax,16
mov ax,20[bp]
add ebx,eax ; get data seg start address
mov edx,ebx
mov word ptr kernel_data_desc.bas_0_15,bx
shr ebx,16
mov byte ptr kernel_data_desc.bas_16_23,bl
mov byte ptr kernel_data_desc.bas_24_31,bh
; initialize temp code segment for kernel
xor ax,ax
mov ebx,ident_code_bas
mov al,24[bp]
movzx eax,ax
add ebx,eax
mov word ptr temp_code_desc.bas_0_15,bx
shr ebx,16
mov byte ptr temp_code_desc.bas_16_23,bl
mov byte ptr temp_code_desc.bas_24_31,bh
; initialize temp data segment for kernel
xor ax,ax
mov al,24[bp]
movzx eax,ax
xor ecx,ecx
mov cx,22[bp]
shl ecx,16
mov cx,20[bp]
add eax,ecx ; get data seg position
and eax,0fffh ; align on the nearest page frame
mov ebx,ident_data_bas
add ebx,eax
mov word ptr temp_data_desc.bas_0_15,bx
shr ebx,16
mov byte ptr temp_data_desc.bas_16_23,bl
mov byte ptr temp_data_desc.bas_24_31,bh
mov ax,ss
mov cs:[ssimage],ax
mov ax,ds
push ds ; can be recover in real mode
; switch to protected mode
mov eax,cr0
or eax,1
mov cr0,eax
db 0eah
dw 0
dw startup_code
; we will be back
realagain:
; we put stack seg to the instruction space
; it is easy to recover
jmp realinit
ssimage dw 0
realinit:
mov ax,cs:[ssimage]
mov ss,ax
mov ax,[bp-2]
mov ds,ax
; show some message indicate we
; are in real mode now
; first clean the screen
mov ch,0
mov cl,0
mov dh,24
mov dl,79
mov bh,7
mov al,0
mov ah,6
int 10h
mov bh,0
mov dh,0
mov dl,0
mov ah,2
int 10h
mov si,offset realok ; points to our message
disp:
lodsb
cmp al,36 ; '$'
jz dispover
push si
mov bx,7
mov ah,0eh
int 10h
pop si
jmp disp
dispover:
jmp dispover
;/============================================================================
;
; fmtmes
;
;============================================================================/
fmtmes proc near
push ds
push es
push bp
mov bp,sp
sub sp,6
; stack arranges like this
; [bp-2] : source string
; [bp-4] : destination string
; [bp-6] : display attrib
mov ax,8[bp]
mov [bp-2],ax
mov ax,10[bp]
mov [bp-4],ax
mov ax,12[bp]
mov [bp-6],ax
; write to destination string
mov si,[bp-2]
mov di,[bp-4]
fmtw1loop:
xor ax,ax
cld
lodsb
cmp al,36 ; '$'
je endloop
mov ah,[bp-6]
stosw
jmp fmtw1loop
endloop:
mov sp,bp
pop bp
pop es
pop ds
ret
fmtmes endp
cseg1 ends
; now this the 32 bit code to start stuix kernel
cseg2 segment para public 'start_386_code' use32
; initialize stack for kernel
mov ax,startup_stack
mov ss,ax
movzx esp,sp ; bootmanager stack is 16 bit
; make a stack frame
push ebp
mov ebp,esp
; display some message indicate that
; our protected code works
mov ax,startup_data
mov ds,ax
; get text ram descriptor
mov ax,text_data
mov es,ax
lea esi,pmok
mov bx,cursorpos
mov bl,bh ; we only concern about row of cursor
inc bl ; ajust base # count
xor bh,bh
mov ax,160 ; each line has 160 shadow bytes
mul bx
movzx edi,ax
; resume display after real mode
mov ecx,40 ; number of character need to display
cld
rep movsw
; get floppy motor killed
mov al,0
mov dx,03f2h
out dx,al
mov ax,kernel_data ; setup kernel execution environment
mov ds,ax
mov gs,ax
mov ax,text_data
mov es,ax
mov ax,startup_data ; kernel use fs to access boot parameter
mov fs,ax
; far call machine code
db 9ah
dw 0
dw 0
dw kernel_code
; make a far call to kernel
; assume entry point is 0
; when stuix is halt, control will transfer
; to this with page mechanism off. load ds,
; fs, gs with startup_data seg selector, ss
; with startup_stack seg selector and es with
; text_data seg selector which are appropriate
; for real-address mode
mov ax,startup_data
mov ds,ax
mov fs,ax
mov gs,ax
mov ax,startup_stack
mov ss,ax
mov ax,text_data
mov es,ax
mov esp,ebp
pop ebp ; ebp now point to real address stack
; jump to our 16 bit code segment, it is overlaped
; with the 'init_386_code' in real mode, but start
; after the 'jmp getstart' instruction
db 0eah
dw 3
dw 0
dw temp_code16
cseg2 ends
dseg segment para public 'init_386_data' use16
a_text dd 0
a_data dd 0
a_bss dd 0
gdt_null_desc desc <> ; null descriptor
startup_code_desc desc <0ffffh,,,98h,40h,>
startup_data_desc desc <0ffffh,,,92h,40h,>
startup_stack_desc desc <0ffffh,,,92h,40h,>
kernel_code_desc desc <0ffffh,,,98h,0c0h,>
kernel_data_desc desc <0ffffh,,,92h,0c0h,>
temp_code_desc desc <0ffffh,,,98h,40h,>
temp_data_desc desc <0ffffh,,,92h,40h,>
text_ram_desc desc <0ffffh,8000h,0bh,92h,0c0h,>
temp_code16_desc desc <0ffffh,61c0h,9,9ah,0,>
gdt_desc table_reg <0ffh,>
cursorpos dw 0 ; last cursor position in real mode
pmok_raw db 'try to execute stuix kernel ...','$'
pmok dw 40 dup (20h)
configbuf db 1024 dup (0)
realok db 'we are in real mode now!','$'
dseg ends
end start
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -