我一直想展示我的 i386 实验室在过去一年的研究中是如何进行的。这个主题是我在 NASM 论坛上的帖子的延续,可以在下面的链接中找到 https://forum.nasm.us/index .php?topic=3828.0
在这里,我正在寻找一个简洁的 kernel.asm 文件来完成基本任务,其中包括一个通用的保护模式来执行 BIOS 模式调用(在本例中为模式 13 设置视频)。我主要担心的是,当我尝试在模式段之间添加小部分时,我的 gdb 对象调试会发生巨大变化。这个模型理论上看起来像这样(Use32 => Real mode => protected16 => rm BIOS calls => protected32)
现在我的问题是与这些段之间的跳转相关的 BIOS/pmode 设置容器。这里我有测试代码,当我尝试为键盘输入添加标准代码时,您可以在其中观察目标文件的路径效果。 所以有没有其他人经历过这个。我真的希望我没有把自己逼到墙角,所以我很乐意通过你的回应继续这个对话。如果有人想要完整测试的配置文件副本,也请告诉我。 干杯!
这里是kernel.asm的运行代码
``
;[ORG 0x7E00]
%define BUILD_GDT_DESC(bounds,base,access,flags) \
((( base & 0x00FFFFFF) << 16) | \
(( base & 0xFF000000) << 32) | \
( bounds & 0x0000FFFF) | \
(( bounds & 0x000F0000) << 32) | \
(( access & 0xFF) << 40) | \
(( flags & 0x0F) << 52))
TSS_IO_MAP_SIZE EQU 0x400/8
%define REBASE_ADDRESS(A) (0x7E00 + ((A) - BIOS32_PREP))
[BITS 16]
section .data
ROWS EQU 25
COLS1 EQU 80
section .text
_prep_module2:
; jmp _prep_module2_
[bits 32]
BIOS32_PREP:use32
pusha
; save current esp to edx
mov edx, esp
; jumping to 16 bit protected mode
; disable interrupts
cli
; clear cr3 by saving cr3 data in ebx register
xor ecx, ecx
mov ebx, cr3
mov cr3, ecx
; load new empty GDT
lgdt [REBASE_ADDRESS(bios32_gdt_ptr)]
; lgdt [REBASE_ADDRESS(gdt32Ptr)]
; load new empty IDT
lidt [REBASE_ADDRESS(bios32_idt_ptr)]
; jump to 16 bit protected mode
jmp 0x30:REBASE_ADDRESS(__protected_mode_16)
; jmp code16_post:REBASE_ADDRESS(__protected_mode_16)
; 16 bit protected mode
__protected_mode_16:use16
; jumping to 16 bit real mode
mov ax, 0x38
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
; turn off protected mode
; set bit 0 to 0
mov eax, cr0
and al, ~0x01
mov cr0, eax
jmp 0x0:REBASE_ADDRESS(__real_mode_16)
; 16 bit real mode
__real_mode_16:use16
xor ax, ax
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov sp, 0x8c00
; enable bios interrupts to call
sti
; save current context, all general, segment registers, flags
pusha
mov cx, ss
push cx
mov cx, gs
push cx
mov cx, fs
push cx
mov cx, es
push cx
mov cx, ds
push cx
pushf
; get current stack pointer & save it to current_esp
mov ax, sp
mov edi, current_esp
stosw
; load our custom registers context
mov esp, REBASE_ADDRESS(bios32_in_reg16_ptr)
; only use some general register from the given context
popa
; set a new stack for bios interrupt
mov sp, 0x9c00
; call immediate interrupt opcode to execute context
pusha
jmp bios32_GraphicCtrlA
;TestCode
;keyboardCtrlA:
;.loopstep1:
; mov ah,01h
; int 16h
; jz .loopstep1
;
; call GraphicPrint
;
; mov ah,00h
; int 16h
;
; cmp ah,48h
; jnz .SetOn
; cmp dl,0
; jz .SetOn
; dec dl
;
;SetOn:
;
; cmp ah,50h
; jnz .SetOff
; cmp dl,24
; jz .SetOff
; inc dl
;
;SetOff:
;
; cmp ah,48h
; jnz .SetNotLeft
; cmp dh,0
; jz .SetNotLeft
; dec dh
;
;.SetNotLeft:
;
; cmp ah,4Dh
; jnz .SetNotRight
; cmp dh,39
; jz .SetNotRight
; inc dh
;
;.SetNotRight:
;
; call GraphicPrint
; jmp graphic_function2
bios32_GraphicCtrlA:
; will be bios interrupt number passed
; put the actual interrupt number here
; db 0xCD
; db 0x10
; db 0x01
mov ax,0x13
int 0x10
;graphic_function2:
; call bios32_int_number_ptr
mov dh,1
mov dl,1
call GraphicPrint
; jmp loopstep1
popa
mov ax,0x13
int 0x10
jmp poll_function
GraphicPrint:
mov cx,0A000h
mov es,cx
; mov ax
push dx
mov ax,8
mul dh
mov bp,ax
mov ax,8*320
mov bx,0
add bl,dl
mul bx
add bp,ax
pop dx
mov si,GraphicA
mov cl,8
PrintGraphicY:
push bp
mov ch,8
PrintGraphicX:
mov al,[ds:si]
xor al,[es:bp]
mov [es:bp],al
inc si
inc bp
dec ch
jnz PrintGraphicX
pop bp
add bp,320
dec cl
jnz PrintGraphicY
; mov sp,dx
;GraphicCtrlRet:
hlt
; popa
ret
; jmp poll_function
; jmp GraphicCtrlRet
; ret
GraphicA:
db 00h,00h,0Eh,0Eh,0Eh,0Eh,00h,00h
db 00h,0Eh,0Eh,0Eh,0Eh,0Eh,0Eh,00h
db 0Eh,0Eh,03h,0Eh,0Eh,03h,0Eh,0Eh
db 0Eh,0Eh,0Eh,0Eh,0Eh,0Eh,0Eh,0Eh
db 0Eh,0Eh,0Eh,0Eh,0Eh,0Eh,0Eh,0Eh
db 0Eh,0Eh,02h,0Eh,0Eh,02h,0Eh,0Eh
db 00h,0Eh,0Eh,02h,02h,0Eh,0Eh,00h
db 00h,00h,0Eh,0Eh,0Eh,0Eh,00h,00h
poll_function:
; get our output context here
mov esp, REBASE_ADDRESS(bios32_out_reg16_ptr)
add sp, 28 ; restore stack used for calling our context
; save current context, all general, segment registers, flags
pushf
mov cx, ss
push cx
mov cx, gs
push cx
mov cx, fs
push cx
mov cx, es
push cx
mov cx, ds
push cx
pusha
; restore the current_esp to continue
mov esi, current_esp
lodsw
mov sp, ax
; restore all current context, all general, segment registers, flags
popf
pop cx
mov ds, cx
pop cx
mov es, cx
pop cx
mov fs, cx
pop cx
mov gs, cx
pop cx
mov ss, cx
popa
; jmp _prep_module2_
; jumping to 32 bit protected mode
; set bit 0 in cr0 to 1
;testGate:
lgdt[gdt32Ptr]
mov eax, cr0
; inc eax
or eax,1
mov cr0, eax
; smsw eax
; jmp 0x08:REBASE_ADDRESS(__protected_mode_32)
; jmp 0x10:REBASE_ADDRESS(__protected_mode_32)
_prep_module2_:
cld
cli
in al,0x92
or al,2
out 0x92,al
; mov [saved_segment],ds
; lidt[Idtpipe32]
; jmp code32_post:REBASE_ADDRESS(__protected_mode_32)
jmp code32_post:__protected_mode_32
; jmp 0x08:REBASE_ADDRESS(__protected_mode_32)
; jmp 0x10:REBASE_ADDRESS(__protected_mode_32)
; 32 bit protected mode
__protected_mode_32:use32
; mov ax, 0x10
mov ax,data32_post
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
; mov ss, ax
; restore cr3
mov cr3, ebx
; restore esp
mov esp, edx
; sti
popa
hlt
jmp $
.loopcheck:
hlt
jmp .loopcheck
; ret
__padding:
db 0x0
db 0x0
db 0x0
bios32_gdt_entries:
; 8 gdt entries
resb 64
bios32_gdt_ptr:
dd 0x00000000
dd 0x00000000
bios32_idt_ptr:
dd 0x00000000
dd 0x00000000
bios32_in_reg16_ptr:
resw 14
bios32_out_reg16_ptr:
dd 0xaaaaaaaa
dd 0xaaaaaaaa
dd 0xaaaaaaaa
dd 0xaaaaaaaa
dd 0xaaaaaaaa
dd 0xaaaaaaaa
dd 0xaaaaaaaa
current_esp:
dw 0x0000
section .data
gdt32:
dq BUILD_GDT_DESC(0,0,0,0)
gdt32code:
dq BUILD_GDT_DESC(0x0000ffff,0,10011010b,1100b)
gdt32data:
dq BUILD_GDT_DESC(0x0000ffff,0,10010010b,1100b)
gdt16code:
dq BUILD_GDT_DESC(0x0000ffff,0,10011010b,1000b)
gdt16data:
dq BUILD_GDT_DESC(0x0000ffff,0,10010010b,1000b)
;gdt16tss:dq BUILD_GDT_DESC(0x8230,TSS_SIZE-1,10001001b,0000b) & 0 << 22
gdt32tss:
dq BUILD_GDT_DESC(TSS_SIZE-1,0x8280,10001001b,0000b)
; dq BUILD_GDT_DESC(TSS_SIZE-1,0x9260,10001001b,0000b)
.stub1:
code32_post: equ gdt32code -gdt32
data32_post: equ gdt32data -gdt32
;.stub:
code16_post: equ gdt16code -gdt32
data16_post: equ gdt16data -gdt32
tss32_post: equ gdt32tss -gdt32
gdt32Len: equ $-gdt32
gdt32Ptr: dw gdt32Len-1
dd gdt32
align 4
;vidmem_ptr: dd VIDEO_TEXT_ADDR
pm_str: db 'protected mode string ',0
pm_str_length: equ $-pm_str
vm_str: db 'virtual',0
;vidmem_address: dw 0
;resb 512
times 512 db 0
align 16
tss:
.back_link: dd 0
.esp0: dd 0
.ss0: dd 0
.esp1: dd 0
.ss1: dd 0
.esp2: dd 0
.ss2: dd 0
.cr3: dd 0
.eip: dd 0
.eflags: dd 0
.eax: dd 0
.ecx: dd 0
.edx: dd 0
.ebx: dd 0
.esp: dd 0
.ebp: dd 0
.esi: dd 0
.type2: dd 0
.es: dd 0
.cs: dd 0
.ss: dd 0
.ds: dd 0
.fs: dd 0
.gs: dd 0
.ldt: dd 0
.trap: dw 0
.iomap_base: dw 0
.iomap: TIMES TSS_IO_MAP_SIZE db 0x00
%if TSS_IO_MAP_SIZE > 0
.iomap_pad:db 0xff
%endif
.end:
TSS_SIZE: EQU tss.end -tss
align 4
ColorTable: db 00h,01h,02h,03h,04h,05h,06h,07h
;db 10h,11h,12h,13h,14h,15h,16h,17h
db 38h,39h,3Ah,3Bh,3Ch,3Dh,3Eh,3Fh
ColorTableSize: equ $-ColorTable
save_cr0 dd 0
save_cr3 dd 0
saved_segment resd 0
gate_voucher dw 1
;X dd 0
;Y dd 0
;color_pkg dw 5
section .bss
align 16
;ring0_proc_stack: resb RING0_PROC_STACK_SIZE
ring0_proc_stack_placer:
align 4
save_esp: resd 1`
save_ss: resd 1`
``