⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 start386.asm

📁 一个朋友写的操作系统源码
💻 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 9424h

     ; physical seg address, it was calculated
     ; by 90200h + 4030h + 10h, 4030h 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, 4030h is
     ; not valid any more, we shall check the
     ; file 'stuixldr.map' generated by tasm
     ; again to determine this value, also
     ; remember to modify temp_code16_desc

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 a_text, a_data, a_bss

     mov ax,22[bp]
     shl eax,16
     mov ax,20[bp]
     mov a_text,eax

     mov ax,18[bp]
     shl eax,16
     mov ax,16[bp]
     mov a_data,eax

     mov ax,14[bp]
     shl eax,16
     mov ax,12[bp]
     mov a_bss,eax

     ; 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
     mov ax,offset gdt_null_desc
     movzx eax,ax
     add ebx,eax

     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

     mov ax,ss          
     mov cs:[ssimage],ax

     ; real mode stack seg must put
     ; in the code seg

     mov ax,ds
     push ds            ; save real mode data seg

     ; 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

     configbuf db 1024 dup (0)

     gdt_null_desc       desc <>
     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,>
     text_ram_desc       desc <0ffffh,8000h,0bh,92h,0c0h,>
     temp_code16_desc    desc <0ffffh,4240h,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)

     realok  db 'we are in real mode now!','$'

dseg ends

end start

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -