热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

从真实模式切换到保护模式后跳远

如何解决《从真实模式切换到保护模式后跳远》经验,如何解决这个问题?

根据本教程,创建一个简单的操作系统就足够了,切换到保护模式就像下面的代码一样简单,无需其他众所周知的操作,如启用A20 ...

无论如何,我是这个领域的新手,我写了下面的代码,因为他们提到了这个SO的修改.

代码结构: 这个简单的操作系统应简要加载如下:

    加载/读取15个扇区

    启用GDT

    切换到保护模式(并打印"成功登陆32位保护模式").

    加载内核并打印"X"

但是,模拟器仍在重新启动.请查看随附的整个代码.

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:
    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_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

[ 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

并且为了确保我们落入保护模式:

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

void main () {
    char * video_memory = (char *) 0xb8000;
    *video_memory = 'X';
}

顺便说一下,我正在使用这个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/*

并且为了将其移动到闪存中,我使用以下命令:

cat output/bootloader.bin output/kernel.bin > os-image
sudo dd if=os-image of=/dev/sdb bs=512 cOnv=notrunc && sync

为了运行它,我使用qemu与此命令:

qemu-system-i386 -hda /dev/sdb

注意到/ dev/sdb是我的闪存驱动器.

问题: 实际上,代码被降落到受保护模式(即打印"成功登陆在保护模式下的32位")禁用正当/评论的call KERNEL_OFFSETbootloader.asm.但是,启用此行时,它将开始启动并重新启动.

我希望我已经提供了所有必要的信息.对我来说,远程跳跃不应该这样做.任何评论表示赞赏.


推荐阅读
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • http:my.oschina.netleejun2005blog136820刚看到群里又有同学在说HTTP协议下的Get请求参数长度是有大小限制的,最大不能超过XX ... [详细]
  • Python正则表达式学习记录及常用方法
    本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • C++字符字符串处理及字符集编码方案
    本文介绍了C++中字符字符串处理的问题,并详细解释了字符集编码方案,包括UNICODE、Windows apps采用的UTF-16编码、ASCII、SBCS和DBCS编码方案。同时说明了ANSI C标准和Windows中的字符/字符串数据类型实现。文章还提到了在编译时需要定义UNICODE宏以支持unicode编码,否则将使用windows code page编译。最后,给出了相关的头文件和数据类型定义。 ... [详细]
  • This article discusses the efficiency of using char str[] and char *str and whether there is any reason to prefer one over the other. It explains the difference between the two and provides an example to illustrate their usage. ... [详细]
  • Java SE从入门到放弃(三)的逻辑运算符详解
    本文详细介绍了Java SE中的逻辑运算符,包括逻辑运算符的操作和运算结果,以及与运算符的不同之处。通过代码演示,展示了逻辑运算符的使用方法和注意事项。文章以Java SE从入门到放弃(三)为背景,对逻辑运算符进行了深入的解析。 ... [详细]
  • 本文介绍了解决Netty拆包粘包问题的一种方法——使用特殊结束符。在通讯过程中,客户端和服务器协商定义一个特殊的分隔符号,只要没有发送分隔符号,就代表一条数据没有结束。文章还提供了服务端的示例代码。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • IhaveconfiguredanactionforaremotenotificationwhenitarrivestomyiOsapp.Iwanttwodiff ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文介绍了游标的使用方法,并以一个水果供应商数据库为例进行了说明。首先创建了一个名为fruits的表,包含了水果的id、供应商id、名称和价格等字段。然后使用游标查询了水果的名称和价格,并将结果输出。最后对游标进行了关闭操作。通过本文可以了解到游标在数据库操作中的应用。 ... [详细]
  • 本文讨论了一个数列求和问题,该数列按照一定规律生成。通过观察数列的规律,我们可以得出求解该问题的算法。具体算法为计算前n项i*f[i]的和,其中f[i]表示数列中有i个数字。根据参考的思路,我们可以将算法的时间复杂度控制在O(n),即计算到5e5即可满足1e9的要求。 ... [详细]
  • 在Oracle11g以前版本中的的DataGuard物理备用数据库,可以以只读的方式打开数据库,但此时MediaRecovery利用日志进行数据同步的过 ... [详细]
author-avatar
iuang
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有