首页 > 其他 > 详细

操作系统与网络实现 之四

时间:2015-11-06 22:24:59      阅读:368      评论:0      收藏:0      [点我收藏+]

 

实模式与保护模式互相跳转

从这里开始我们就要告别实模式,实现保护模式了。

首先了解一些相关知识。

段描述符的具体格式

技术分享

段描述符长8个字节64位。

 

技术分享

 

重点说明:
  
空描述符:           ; 这是保护模式要求保留的,第一个段必须是空段,空描述符的64位全是0
        dd  0
        dd  0           
   
对于代码段字节5:
        db  10011010b   ; 0x9A
属性描述位,P=1DPL=0DT1=1TYPE=A,指明此是代码段、可读可执行
   
对于数据段字节5:              
        db  10010010b   ;  0x92
属性描述位,P=1DPL=0DT1=1TYPE=2,指明此是数据段,可读可写

虚拟地址转换物理地址

简单的说:虚拟地址的偏移量+base=线性地址

在没有使用分布机制情况下,线性地址就是物理地址。

这里,我们没有使用分布机制。

 

改变kernelloader.asm,让它从实模式到保护模式显示一个字母,再返回实模式并显示hello

kernelloader.asm

[BITS 16]  

jmp                 main

 

gdt_entries   equ    5                  ;共有五个段描述符:null,os code32,os data32,os code16,os data16

showbase       equ    8900h

pe              equ    1                  ;bit PE in CR0

null              equ    0h

os_code32_sel   equ    8h                ;1,gdt,rpl=00

os_data32_sel   equ    10h               ;2,gdt,rpl=00

os_code16_sel   equ    18h               ;3,gdt,rpl=00

os_data16_sel   equ    20h               ;4,gdt,rpl=00

 

[SECTION .data]

ns db 0x48,0x65,0x6C,0x6C,0x6F,0x20,0x77,0x6F,0x72,0x6C,0x64,0x21, ‘from ya‘  ;;hello world!from ya

pdescr       times 6 db 0

gdt_table    times (gdt_entries*8) db 0

end_32       dd 0

         dw 0

hello:                 ;hello子程序

  push es

  mov cx,19           ;循环19

  mov bx,0            ;从数组[0]开始

  mov ah,0eh

next:

  mov al,[ns+bx]

  int 10h

  inc bx

  dec cx

  jnz next            ;cx不为0则继续

  pop es

  ret

 

main:

mov ax,1000h

mov ds,ax

;打开 A 20 地址线

mov               ax , 0x2401

int               0x15 

mov word[end_32+0],end32

mov word[end_32+4],os_code16_sel        ;point to 0018:end32

;[1]built up GDT table

cli

mov  eax,gdt_table

;item 0:null descriptor,

mov  dword[eax],0

mov  dword[eax+4],0

add  eax,8

;item 1,OS code32 descriptor,

;Base=00010000h,limit=0fh,G=1,D=1,type=a,dpl=0

mov  word[eax],0000fh

mov  word[eax+2],0

mov  byte[eax+4],01h

mov  byte[eax+5],09ah

mov  byte[eax+6],0c0h

mov  byte[eax+7],00h

add  eax,8

;item 2,OS data32 descriptor

;Base=00010000h,Limit=0fffh,G=1,D=1,Type=2,DPL=0

mov  word[eax],0fffh

mov  word[eax+2],0000h

mov  byte[eax+4],01h

mov  byte[eax+5],092h

mov  byte[eax+6],0c0h

mov  byte[eax+7],00h

add  eax,8

;item 3,OS code16 descriptor,

;Base=00010000h,limit=0ffffh,G=0,D=0,type=a,dpl=0

mov  word[eax],0ffffh

mov  word[eax+2],0

mov  byte[eax+4],01h

mov  byte[eax+5],09ah

mov  byte[eax+6],00h

mov  byte[eax+7],00h

add  eax,8

;item 4,OS data16 descriptor

;Base=00010000h,Limit=0ffffh,G=0,D=1,Type=2,DPL=0

mov  word[eax],0ffffh

mov  word[eax+2],0000h

mov  byte[eax+4],01h

mov  byte[eax+5],092h

mov  byte[eax+6],40h

mov  byte[eax+7],00h

;[2]built false GDT descriptor

mov  word[pdescr+0],(gdt_entries*8-1)

mov  dword[pdescr+2],gdt_table+00010000h

lgdt [pdescr]

;[3]enter into protected mode

;刷新CR0

mov eax,cr0

or  eax,pe

mov cr0,eax

jmp flush

flush:

mov ax,os_data32_sel

mov ds,ax

mov es,ax

mov ss,ax

mov fs,ax

mov gs,ax

jmp dword os_code32_sel:start32

;[4]run in protected mode

start32:

cli                 

mov bx,showbase

dw  0ah                     ;相当于mov ebx,0a8900h

mov di,bx                  ;相当于es:edi=0010:000a8900=0b8900h

mov al,‘A‘

mov ah,34h

stosw

 

mov si,end_32

dw  00h                     ;相当于mov esi,offset end_32

 

db  0ffh,2eh               ;相当于jmp Fword Ptr [esi] ,jmp to 0018:end32

end32:

;[5]exit to dos

mov ax,os_data16_sel      

mov ds,ax

mov es,ax

mov ss,ax

mov fs,ax

mov gs,ax

cli

mov eax,cr0

and al,0feh

mov cr0,eax                ;clear pe bit,exit of protected mode

mov cr3,eax

jmp   realflush

realflush:

mov ax,01000h

mov ds,ax

mov es,ax

mov ss,ax

xor ax,ax

mov fs,ax

mov gs,ax

jmp 0x1000:real16

real16:

mov word[pdescr+0],0ffffh    ;limit

mov dword[pdescr+2],0         ;basement

lidt [pdescr]

sti

mov ah,4ch

int 21h

call hello                      ;返回实模式后显示hello

jmp $

 

 

程序中

;打开 A 20 地址线

mov               ax , 0x2401

int               0x15

 

......

;刷新CR0

mov eax,cr0

or  eax,pe

mov cr0,eax

jmp flush

flush:

这些语句都是按要求必须这么做的,没什么可说的,大家按套路来就行。

目前kernelloader.bin大小为444字节,占据1个扇区,相应的boot程序中读取扇区的参数值应为1

boot.asm

[BITS 16]                                                  ;编译成16位的指令

[ORG 0x7C00]

jmp                 main

 

read_kernelloader:                                        ;读入 kernelloader 程序

  push              es

 

  .rk:

  mov               ax , 0x1000                            ;kernelloader.bin 所在的段基址           

  mov               es , ax

  mov               bx , 0

  mov               ah , 2

  mov               dl , 0

  mov               ch , 0

  mov               cl , 2

  mov               al , 1                                 ;读入扇区数,每个扇区为 512B

  int               0x13 

  jc                .rk

 

  pop               es

  ret

 

main:                                                       ;主程序         

  mov               ax , 0x0                               ;boot.bin 程序的段基址

  mov               ds , ax

 

  call              read_kernelloader                    ;读入 kernelloader 程序 

 

  jmp dword         0x1000:0                              ;跳转到 kernelloader 处执行

times 510-($-$$) db 0

db 0x55

db 0xAA

 

 

bochs中运行效果如下:

技术分享

 

16位模式下与32位模式下的编译结果(机器码)是有区别的:

(16位下)mov bx,8900h       机器码为  BB0089

(32位下)mov ebx,68900h     机器码为  BB00890600

两个相差0600

 

(16位下)mov di,bx           机器码为  89DF

(32位下)mov edi,ebx         机器码为  89DF

两个相同

 

(16位下)mov si,end_32       机器码为  BE4500

(32位下)mov esi,end_32      机器码为  BE45000000

两个相差0000

 

(16位下)jmp fword ptr [esi]    机器码为   FF2e

为什么要研究机器码?因为我们程序是在16位模式下编译,但是我们中间这段程序又将要跳转到保护模式,但是在保护模式下运行16位程序显然会出错,怎么解决这个问题?

我们可以将16位模式下与32位模式指令中相差的部分补充上,那么以下的语句就可以理解了:

mov bx,showbase

dw  06h                   ;相当于mov ebx,68900h

mov di,bx                ;es:edi=0010:00068900=0b8900h

mov al,‘A‘               ;16位与32位相同

mov ah,34h               ;16位与32位相同

stosw                     ;16位与32位相同

 

mov si,end_32

dw  00h                    ;mov esi,offset end_32

 

db  0ffh,2eh              ;相当于jmp Fword Ptr [esi] ,jmp to 0018:end32

操作系统与网络实现 之四

原文:http://www.cnblogs.com/ya20151015/p/4943675.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!