【发布时间】:2016-08-18 18:02:36
【问题描述】:
我想问如何在引导加载程序中获取 Total RAM Size 和 Usable RAM Size 。截至目前,我知道如何获得较低的内存。但由于某种原因,我无法将其打印到屏幕上,因为它保存在斧头寄存器中。这是我到目前为止所拥有的:
[BITS 16] ; BootLoader always starts 16 BIT Moded
jmp main_bootloader ; Jump to Main Bootloader
;************** INITALIZED VARIABLES *********************;
string db 'BoneOS Loading . . .', 0x0
string2 db 'Starting of 16Bit Bootloader' , 0x0
press_to_cont db 'Press any key to continue . . .' , 0x0
carry_flag_err db ' CARRY FLAG HAS BEEN SET! ERROR ' , 0x0
magic_number equ 0x534D4150
limit dw 0
base dw 0
low_memory dd 0
answer resb 64
;*********************************************************;
;******************** GDTs *****************************;
null_descriptor :
dd 0 ; null descriptor--just fill 8 bytes with zero
dd 0
; Notice that each descriptor is exactally 8 bytes in size. THIS IS IMPORTANT.
; Because of this, the code descriptor has offset 0x8.
code_descriptor: ; code descriptor. Right after null descriptor
dw 0FFFFh ; limit low
dw 0 ; base low
db 0 ; base middle
db 10011010b ; access
db 11001111b ; granularity
db 0 ; base high
; Because each descriptor is 8 bytes in size, the Data descritpor is at offset 0x10 from
; the beginning of the GDT, or 16 (decimal) bytes from start.
data_descriptor: ; data descriptor
dw 0FFFFh ; limit low (Same as code)
dw 0 ; base low
db 0 ; base middle
db 10010010b ; access
db 11001111b ; granularity
db 0 ; base high
end_of_gdt:
toc:
dw end_of_gdt - null_descriptor - 1 ; limit (Size of GDT)
dd null_descriptor ; base of GDT
load_gdt:
lgdt [toc]
.done:
ret
;*********************************************************;
;*************** LABELS FOR MAIN **************************;
print_char_boot:
mov ah, 0Eh ; Code For BIOS To Print Char 0Eh
.repeat:
lodsb ; Load Byte From SI Register
cmp al, 0 ; Compare AL With 0 If so Done
je .done
int 10h ; Call Interupt. Checks AH Register for code 0EH = Print char
jmp .repeat ; Loop Back
.done:
ret ; Return to previous code
print_new_line:
mov al, 0 ; null terminator '\0'
;Adds a newline break '\n'
mov ah, 0x0E
mov al, 0x0D
int 0x10
mov al, 0x0A
int 0x10
ret
get_pressed_key:
mov ah, 0
int 0x16 ;BIOS Call. Key goes to al register
ret
GET_RAM_SIZE:
reboot:
mov si, press_to_cont
call print_char_boot
call get_pressed_key ; Gets Pressed Key
int 19h ;Reboot
ret
enable_A20: ; Enabling A20 Line For Full Memory
cli ; Stop Interupts before doing so
call a20wait ; a20wait call
mov al,0xAD ; Send 0xAD Command to al register
out 0x64,al ; Send command 0xad (disable keyboard).
call a20wait ; When controller ready for command
mov al,0xD0 ; Send 0xD0 Command to al register
out 0x64,al ; Send command 0xd0 (read from input)
call a20wait2 ; When controller ready for command
in al,0x60 ; Read input from keyboard
push eax ; Save Input by pushing to stack
call a20wait ; When controller ready for command
mov al,0xD1 ; mov 0xD1 Command to al register
out 0x64,al ; Set command 0xd1 (write to output)
call a20wait ; When controller ready for command
pop eax ; Pop Input from Keyboard
or al,2 ; Mov 0xD3 to al register
out 0x60,al ; Set Command 0xD3
call a20wait ; When controller ready for command
mov al,0xAE ; Mov Command 0xAE To al register
out 0x64,al ; Write command 0xae (enable keyboard)
call a20wait ; When controller ready for command
sti ; Enable Interrupts after enabling A20 Line
ret
a20wait:
in al,0x64 ; input from 0x64 port, goes to al register
test al,2 ; compares al register with 2
jnz a20wait ; If it is zero loop again
ret
a20wait2:
in al,0x64 ; input from 0x64 port, goes to al register
test al,1 ; compares al register with 2
jz a20wait2 ; If it is zero loop again
ret
get_lower_memory:
clc ; Clears Carry Flag
int 0x12 ; BIOS Call Request Lower Memory Size in KB
jc .err ; If Carry Flag Has Been Set , the system its running on dosent support this
jmp .done ; If Sucessfull ax register contains contiguous low memory in KB
.err:
times 5 call print_new_line ; Prints New Line
mov si, carry_flag_err
call print_char_boot
jmp .repeat
.done:
ret
.repeat:
jmp .repeat
;**************************************************************;
;*******************'MAIN' BOOTLOADER FUNCTION ****************;
main_bootloader:
xor ax, ax
mov ss, ax
mov sp, 4096
mov ax, 07C0h ; Set data segment to where we're loaded
mov ds, ax
mov si, string ; si register usefull for lodsb command
call print_char_boot ; Call print_char_boot label below
call print_new_line ; Prints New Line
mov si, string2
call print_char_boot
times 2 call print_new_line
; Enable A20 Line
call enable_A20
call get_lower_memory ; Get Low Memory
mov si,ax
call print_char_boot
times 5 call print_new_line
call reboot ; Reboot
;call null_descriptor
jmp $ ; Infinite Loop
;Bootloader gets infinite loop
;Incase No Infinite Loop in Kernel
;****************************************************************;
;************************* BOOTLOADER REQUIREMENTS **************;
times 510 - ($ - $$) db 0 ; Has to be 512 bytes .. Repeats 510 byes to make it so
dw 0xAA55 ; BootLoader Sig. To Validate this is a bootloader
;
****************************************************************;
正如您在我的主服务器上看到的那样,我是 call get_lower_memory ; Get Low Memory,以获得低内存。但我已经测试了打印斧头寄存器,但屏幕上没有显示任何内容。而且我也不知道如何在系统中获得总和可用的 ram。非常感谢您的帮助!
【问题讨论】:
-
使用 INT 15h, EAX = E820h 获取系统的内存映射,以便找到您可以使用的内存区域。
-
如果
ax包含以千字节为单位的低内存量,那么当mov si, ax和call print_char_boot这两条语句被执行时会发生什么?
标签: assembly x86 ram bootloader osdev