[英]Far jump after switching from real to protected mode
According to this tutorial it is sufficient to create a simple operating system with switching to protected mode as simple as the following code without the need for other well known actions such as enabling A20... 根据本教程 ,创建一个简单的操作系统就足够了,切换到保护模式就像下面的代码一样简单,无需其他众所周知的操作,如启用A20 ...
Anyway, I am newbie to this domain, I wrote the following code as they mentioned exactly with the modification inspired from this SO . 无论如何,我是这个领域的新手,我写了下面的代码,因为他们提到了这个SO的修改。
Code Structure: This simple operating system should load briefly as follows: 代码结构:这个简单的操作系统应简要加载如下:
However the emulator is still rebooting. 但是,模拟器仍在重新启动。 Please find enclosed the entire code.
请查看随附的整个代码。
bootloader.asm bootloader.asm
[bits 16]
[org 0x7C00]
KERNEL_OFFSET equ 0x1000
xor ax, ax
mov ds, ax
mov es, ax
mov [BOOT_DRIVE], dl
mov ax, 0x07E0 ; End of stack
cli
mov ss, ax
mov sp, 0x1200 ; Size of Stack. By this, we assume that stack starts at 9000h
; of size 1200h and ends at 7E00h to avoid being overwritten.
sti
call load_kernel
call switch_to_pm
jmp $
%include "src/functions/disk_load.asm"
load_kernel:
mov bx, KERNEL_OFFSET
mov dh, 15
mov dl, [BOOT_DRIVE]
call disk_load
ret
; Global variables
BOOT_DRIVE db 0
SECTORS db 0
MSG_PROT_MODE db "Successfully landed in 32-bit Protected Mode" , 0
%include "src/functions/gdt.asm"
%include "src/functions/switch_to_pm.asm"
[ bits 32]
; This is where we arrive after switching to and initialising protected mode.
BEGIN_PM:
mov ebx , MSG_PROT_MODE
call print_string_pm ; Use our 32 - bit print routine.
;call KERNEL_OFFSET ; Now jump to the address of our loaded
; kernel code , assume the brace position ,
; and cross your fingers. Here we go !
jmp $ ; Hang.
%include "src/functions/writing_video_mode.asm"
; Bootsector padding
times 510-($-$$) db 0
dw 0xAA55
; 15 sector padding
times 15*256 dw 0xDADA
disk_load.asm disk_load.asm
disk_load:
mov [SECTORS], dh
mov ch, 0x00 ;C=0
mov dh, 0x00 ;H=0
mov cl, 0x02 ;S=2
next_group:
mov di, 5 ;Max 5 tries
again:
mov ah, 0x02 ;Read sectors
mov al, [SECTORS]
int 0x13
jc maybe_retry
sub [SECTORS], al ;Remaining sectors
jz ready
mov cl, 0x01 ;Always sector 1
xor dh, 1 ;Next head on diskette!
jnz next_group
inc ch ;Next cylinder
jmp next_group
maybe_retry:
mov ah, 0x00 ;Reset diskdrive
int 0x13
dec di
jnz again
jmp disk_error
ready:
ret
disk_error:
mov ah, 0x0e
mov al, 'Y'
int 0x10
jmp $
DISK_ERROR_MSG db "Disk read error!", 0
gdt.asm gdt.asm
gdt_start:
gdt_null:
dd 0x0 ; ’ dd ’ means define double word ( i.e. 4 bytes )
dd 0x0
gdt_code:
dw 0xffff
dw 0x0
db 0x0
db 10011010b ; 1 st flags , type flags
db 11001111b ; 2 nd flags , Limit ( bits 16 -19)
db 0x0
gdt_data:
dw 0xffff
dw 0x0
db 0x0
db 10010010b ; 1 st flags , type flags
db 11001111b ; 2 nd flags , Limit ( bits 16 -19)
db 0x0
gdt_end:
gdt_descriptor:
dw gdt_end - gdt_start - 1
dd gdt_start
CODE_SEG equ gdt_code - gdt_start
DATA_SEG equ gdt_data - gdt_start
switch_to_pm.asm switch_to_pm.asm
[ bits 16 ]
switch_to_pm:
cli
lgdt [ gdt_descriptor ]
mov eax , cr0
or eax , 0x1
mov cr0 , eax
jmp CODE_SEG:init_pm
[ bits 32 ]
init_pm:
mov ax, DATA_SEG
mov ds, ax
mov ss, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ebp , 0x90000
mov esp , ebp
call BEGIN_PM
And in order to make sure that we landed in the protected mode: 并且为了确保我们落入保护模式:
writing_video_mode.asm writing_video_mode.asm
[ bits 32]
VIDEO_MEMORY equ 0xb8000
WHITE_ON_BLACK equ 0x0f
print_string_pm:
push eax
push ebx
push edx
mov edx , VIDEO_MEMORY ; Set edx to the start of vid mem.
print_string_pm_loop:
mov al, [ebx]
mov ah, WHITE_ON_BLACK
cmp al, 0
je print_string_pm_done
mov [edx], ax
add ebx, 1
add edx, 2
jmp print_string_pm_loop
print_string_pm_done:
pop edx
pop ebx
pop eax
ret
kernel.c kernel.c
void main () {
char * video_memory = (char *) 0xb8000;
*video_memory = 'X';
}
By the way, I am using this Makefile : 顺便说一下,我正在使用这个Makefile :
all: bootloader.bin kernel.bin
bootloader.bin: src/bootloader.asm
nasm src/bootloader.asm -f bin -o output/bootloader.bin
kernel.o: src/kernel/kernel.c
gcc -ffreestanding -c src/kernel/kernel.c -o output/kernel.o -m32
kernel.bin: kernel.o
ld -o output/kernel.bin -Ttext 0x1000 --oformat binary output/kernel.o -melf_i386
clean:
rm -f output/*.* output/*
and in order to move it into the flash memory, I use these commands: 并且为了将其移动到闪存中,我使用以下命令:
cat output/bootloader.bin output/kernel.bin > os-image
sudo dd if=os-image of=/dev/sdb bs=512 conv=notrunc && sync
In order to run it, I am using qemu with this command: 为了运行它,我使用qemu与此命令:
qemu-system-i386 -hda /dev/sdb
Noting that /dev/sdb is my flash memory drive. 注意到/ dev / sdb是我的闪存驱动器。
Problem: Indeed, the code is landing into the protected mode (Ie Printing "Successfully landed in 32-bit Protected Mode") just when disabling/commenting the call KERNEL_OFFSET
in the bootloader.asm
. 问题:实际上,当禁用/注释
bootloader.asm
的call KERNEL_OFFSET
时,代码将进入保护模式(即打印“成功登陆32位保护模式”)。 However when enabling this line it starts booting and rebooting. 但是,启用此行时,它将开始启动并重新启动。
I hope I have provided every needed information. 我希望我已经提供了所有必要的信息。 It seems for me that the far jump should not be done this way.
对我来说,远程跳跃不应该这样做。 Any comment is appreciated.
任何评论表示赞赏。
Just remove 只需删除
times 15*256 dw 0xDADA
时间15 * 256 dw 0xDADA
(btw, why DADA?) (顺便问一下,DADA为什么?)
then compile your kernel, after that 然后编译你的内核
cat output/bootloader.bin output/kernel.bin > os-image
cat output / bootloader.bin output / kernel.bin> os-image
and somehow make your os image 8192 byte long (16 sectors, bootloader + 15). 并以某种方式使你的os图像长8192字节(16扇区,bootloader + 15)。 I'm not Linux/Unix fan (even can't use them), but I think dd command (something like dd if=dev\\zero of=temp_file count=(8192 - file actual size ) , and then cat os-image temp-file > os-image ) should do the job.
我不是Linux / Unix风扇(甚至不能使用它们),但我认为dd命令(类似于dd if = dev \\ zero of = temp_file count =(8192 - 文件实际大小 ) ,然后是cat os-image临时文件> os-image )应该完成这项工作。 I'm also not sure is this compilation command correct (only not sure).
我也不确定这个编译命令是否正确(只是不确定)。 I would remove "-melf_i386" from linker command, but idk, I have only used MinGW on Windows (it's only similar to GCC).
我会从链接器命令中删除“-melf_i386”,但是idk,我只在Windows上使用过MinGW(它只与GCC类似)。
Sorry for my bad English, I hope I helped. 对不起我的英语不好,我希望我帮忙。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.