我目前正在编写一个32位操作系统,在尝试获取内存Map以便编写内存管理器时,我使用了brokenthorn教程中的以下函数
memmap.asm
struc MemoryMapEntry
.baseAddress resq 1 ; base address of address range
.length resq 1 ; length of address range in bytes
.type resd 1 ; type of address range
.acpi_null resd 1 ; reserved
endstruc
BiosGetMemoryMap:
pushad
xor ebx, ebx
xor bp, bp ; number of entries stored here
mov edx, 'PAMS'
mov eax, 0xe820
mov ecx, 24 ; memory map entry struct is 24 bytes
int 0x15 ; get first entry
jc .error
cmp eax, 'PAMS' ; bios returns SMAP in eax
jne .error
test ebx, ebx ; if ebx=0 then list is one entry long; bail out
je .error
jmp .start
.next_entry:
mov edx, 'PAMS' ; some bios's trash this register
mov ecx, 24 ; entry is 24 bytes
mov eax, 0xe820
int 0x15 ; get next entry
.start:
jcxz .skip_entry ; if actual returned bytes is 0, skip entry
.notext:
mov ecx, [es:di + MemoryMapEntry.length] ; get length (low dword)
test ecx, ecx ; if length is 0 skip it
jne short .good_entry
mov ecx, [es:di + MemoryMapEntry.length + 4]; get length (upper dword)
jecxz .skip_entry ; if length is 0 skip it
.good_entry:
inc bp ; increment entry count
add di, 24 ; point di to next entry in buffer
.skip_entry:
cmp ebx, 0 ; if ebx return is 0, list is done
jne .next_entry ; get next entry
jmp .done
.error:
stc
.done:
popad
ret
loader.asm
; Fortress Bootloader
; The quasar bootloader is a bare metal bootloader
; It can load 128 sectors, and is meant to load a
; tiny but powerful kernel
[bits 16]
[extern kernel]
[global isr_stub_table]
[global IDT_load]
[extern FortressLoader_IdtInit]
[extern FortressLoader_ChecmMemMap]
[extern X86TTY_Init]
[extern X86TTY_Clear]
[extern printf]
[global startKernel]
section .boot
global boot
KERNEL_SIZE_SECTORS equ 128
jmp $boot
bpbBytesPerSector: DW 512
bpbSectorsPerCluster: DB 1
bpbReservedSectors: DW 1
bpbNumberOfFATs: DB 2
bpbRootEntries: DW 224
bpbTotalSectors: DW 2880
bpbMedia: DB 0xF0
bpbSectorsPerFAT: DW 9
bpbSectorsPerTrack: DW 18
bpbHeadsPerCylinder: DW 2
bpbHiddenSectors: DD 0
bpbTotalSectorsBig: DD 0
bsDriveNumber: DB 0
bsUnused: DB 0
bsExtBootSignature: DB 0x29
bsSerialNumber: DD 0xa0a1a2a3
bsVolumeLabel: DB "6STAR OS "
bsFileSystem: DB "FAT12 "
%include "./fortressloader/memory.asm"
%include "./fortressloader/memmap.asm"
%include "./fortressloader/multiboot.asm"
test_message db "test", 0
boot:
cld
xor ax, ax
mov ds, ax
mov ss, ax
mov sp, 0x7c00
mov di, 0x7c00
cli
mov [disk], dl
mov ax, 0x2401
int 0x15
mov ax, 0x3 ;Set the VGA mode, unknown at boot
int 0x10
mov ah, 42h ;Do modern disk reading (no fuckery)
mov dl, [disk] ;Account for cosmic bit flips
mov si, dap ;Load disk address packet
int 0x13
jc disk_err ;Jump if disk read error
jmp disk_target ;
print:
pusha
start:
mov al, [bx]
cmp al, 0
je done
mov ah, 0x0e
int 0x10
add bx, 1
jmp start
done:
popa
ret
print_nl:
pusha
mov ah, 0x0e
mov al, 0x0a
int 0x10
mov al, 0x0d
int 0x10
popa
ret
print_hex:
pusha
mov cx, 0
hex_loop:
cmp cx, 4
je end
mov ax, dx
and ax, 0x000f
add al, 0x30
cmp al, 0x39
jle step2
add al, 7
step2:
mov bx, HEX_OUT + 5
sub bx, cx
mov [bx], al
ror dx, 4
add cx, 1
jmp hex_loop
end:
mov bx, HEX_OUT
call print
popa
ret
disk_err: ;Label for any disk errors
mov bx, disk_read_error ;Print the disk error
call print
call print_nl
mov dh, ah ;Load error code in ah register
call print_hex
jmp $
GDT_START:
dq 0x0
GDT_CODE: ;base = 0x00000000, length = 0xfffff
dw 0xffff ;segment length, bits 0-15
dw 0x0 ;segment base, bits 0-15
db 0x0 ;segment base, bits 16-23
db 10011010b ;flags (8 bits)
db 11001111b ;flags (4 bits) + segment length
db 0x0 ;segment base, bits 24-31
GDT_DATA:
dw 0xFFFF
dw 0x0
db 0x0
db 10010010b
db 11001111b
db 0x0
GDT_END:
GDT_POINTER:
dw GDT_END - GDT_START
dd GDT_START
CODE_SEG equ GDT_CODE - GDT_START
DATA_SEG equ GDT_DATA - GDT_START
disk:
db 0x0
dap:
db 0x10
db 0
dw KERNEL_SIZE_SECTORS
dw 0 ;
dw 0x07e0 ;value recommended by a friend
dq 1 ;start second sector read
HEX_OUT:
db '0x0000',0
disk_read_error: db "Disk read error!", 0
times 510 - ($-$$) db 0
dw 0xAA55
disk_target:
call BiosGetMemorySize64MB ;Load the memory size
mov [mbInfo+mbInfo.memoryHi], bx
mov [mbInfo+mbInfo.memoryLo], ax
mov word [mbInfo+mbInfo.bootDevice], 0x0
call BiosGetMemoryMap
mov word [mbInfo+mbInfo.mmap_length], ax
mov word [mbInfo+mbInfo.mmap_addr], 0x2000
cli ;Clear the interrupts
lgdt [GDT_POINTER] ;Load the GDT using a gdt pointer
mov eax, cr0
or eax, 0x1
mov cr0, eax
jmp CODE_SEG:boot2
[bits 32]
startKernel:
boot2:
mov ax, DATA_SEG
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov esi, loaded_msg
mov ebx, 0xb8000
.loop: ;Print a message using a loop
lodsb
or al, al
jz load_kernel ;Load kern when msg finished
or eax,0x0F00
mov word [ebx], ax
add ebx,2
jmp .loop
load_kernel:
mov esp, kernel_stack_top ;Load the stack to call C functions
call X86TTY_Init ;Initalize the TTY
call X86TTY_Clear ;Clear everything on the screen
call FortressLoader_IdtInit ;Initalize the IDT
mov eax, 0x2BADB002 ;Multiboot magic number
mov ebx, mbInfo
mov ebx, 0
call kernel ;Call the actual kernel
halt:
cli
hlt
loaded_msg: db "Operating system loaded",0 ;Message here to verify disk read
section .bss
align 4
kernel_stack_bottom: equ $ ;equ the current address for the stack
resb 16384 ;Use 16kb for stack size
kernel_stack_top: ;Top of the stack
section .text ;Fuck bss and asm sections
然而,我的问题是,这会导致Qemu永远不会调用内核,或者这之后的任何事情
我尝试过注解掉引导装载程序中的某些行,并意识到这是第12行上的特定指令mov edx, 'PAMS'
。注解掉该特定行时,没有任何问题。我可以做些什么来解决这个问题?
1条答案
按热度按时间ncecgwcz1#
修复!我在
mov word [mbInfo+mbInfo.bootDevice], 0x0
之后缺少一个mov edi, 0x2000