尝试从保护模式返回到Real

时间:2016-11-17 19:44:06

标签: assembly nasm dos real-mode protected-mode

我试图在保护之后回到实模式,并且在更改cr0寄存器后处理器刚刚卡住了。 我正在使用nasm,并将我的程序编译为二进制.img,以便在virtualbox下作为bootloader运行。可能我错过了跳远回到realMain proc的东西。

[org 0x7C00] ; BIOS boot origin
[bits 16] ; 16-bit Real Mode

jmp start ;Jump to start() entry-point
%include "routines16.asm"
[bits 16]

start:
  mov si, welcomeMsg
  call print
  call getKey
  call clear

realMain:
  cli
  mov ax, cs
  mov ds, ax
  mov es, ax
  ; mov ax, STACK16
  ; mov ss, ax
  sti

  mov si, inrealmsg
  call print

  mov si, anykeyMsg
  call print
  call getKey

  call toProtected

toProtected:
  mov si, toprotectedmsg
  call print
  call clear;
  ;move
  cli
  lgdt [gdt32_descriptor] ; Load GDT
  mov eax, cr0
  or eax, 0x1
  mov cr0, eax
  jmp dword CODE_SEG_32:protectedMain

;;;;;;;;;;;;;;
welcomeMsg db "IPR1-degtyarev. Press any key to start", 0x0
inrealmsg db "in real", 0x0
toprotectedmsg db "switching to protected", 0x0
anykeyMsg db "Press any key to switch cpu mode...", 0x0
;;;;;;;;;;;;;;

%include "gdt32.asm"
%include "routines32.asm"

[bits 32]

protectedMain:
  mov eax, DATA_SEG_32
  mov ds, eax
  mov es, eax

  mov eax, 0x0000; zero line
  mov ebx, inprotectedmsg
  call print32
  add eax, 0x00A0; moving next line
  call toReal

toReal:
  mov edx, eax
  mov ebx, torealmsg
  call print32
  ;move
  cli

  mov eax, cr0
  dec al
  mov cr0, eax

  jmp 0x7C00:realMain

end:
  jmp end

;;;;;;;;;;;;;;
inprotectedmsg db "in protected", 0x0
torealmsg db "switching to real", 0x0
;;;;;;;;;;;;;;

times 510 - ($-$$) db 0 ;Fill the rest of the bootloader with zeros
dw 0xAA55 ;Boot signature

附加GDT32

; Descriptor CONFIG
gdt32_start:

gdt32_null:         ; Initialization null
    dq 0x0

gdt32_cs:
    dw 0xFFFF    ; Limit
    dw 0x0000    ; Base
    db 0x0000    ; Base 23:16
    db 10011011b ; [p][dpl][][s][type][][][a]
    db 11011111b ; [g][x][0][avl][lim][][][]
    db 0x0000

gdt32_ds:
    dw 0xFFFF    ; Limit
    dw 0x0000    ; Base
    db 0x0000    ; Base 23:16
    db 10010011b
    db 11011111b
    db 0x0000

gdt32_end:         ; Pour avoir la taille du GDT

gdt32_descriptor:
    dw gdt32_end - gdt32_start - 1 ; GDT size
    dd gdt32_start

; Constants to get address of gdt32
CODE_SEG_32 equ gdt32_cs - gdt32_start
DATA_SEG_32 equ gdt32_ds - gdt32_start

0 个答案:

没有答案