操作系統(tǒng)-從保護(hù)模式返回實(shí)模式

Q.從上節(jié)課可以引出一個(gè)小問題,下面的語(yǔ)句是否有Bug的存在操作系統(tǒng)-從保護(hù)模式返回實(shí)模式
在進(jìn)入保護(hù)模式后,在第一處使用了棧段選擇址對(duì)ss賦值,然后使用打印,覺得會(huì)出現(xiàn)Bug的存在的是因?yàn)槭褂昧苏{(diào)用函數(shù),而使用調(diào)用函數(shù)需要??臻g,還需要棧頂指針-esp寄存器,而在這里的代碼中沒有對(duì)esp寄存器進(jìn)行賦值。在這里需要對(duì)esp寄存器進(jìn)行查找。
A.對(duì)上節(jié)課的代碼進(jìn)行實(shí)驗(yàn)
操作系統(tǒng)-從保護(hù)模式返回實(shí)模式操作系統(tǒng)-從保護(hù)模式返回實(shí)模式操作系統(tǒng)-從保護(hù)模式返回實(shí)模式操作系統(tǒng)-從保護(hù)模式返回實(shí)模式操作系統(tǒng)-從保護(hù)模式返回實(shí)模式
操作系統(tǒng)-從保護(hù)模式返回實(shí)模式操作系統(tǒng)-從保護(hù)模式返回實(shí)模式
在這里進(jìn)行的步驟是首先反編譯找到跳轉(zhuǎn)處的地址值,然后在bochs上設(shè)置斷點(diǎn)通過一步一步的單步調(diào)試使其運(yùn)行到圖5中即將進(jìn)行call命令處,然后實(shí)驗(yàn)reg命令對(duì)寄存器地址進(jìn)行查看,發(fā)現(xiàn)esp寄存器的地址是0x00007c00,與上章的棧頂寄存器地址一致,程序的運(yùn)行結(jié)果符合預(yù)期。這里會(huì)出現(xiàn)一個(gè)疑問,沒有對(duì)esp寄存器地址進(jìn)行賦值,為什么會(huì)在32保護(hù)模式下,esp寄存器的值卻指向棧頂,可以再一次的進(jìn)行實(shí)驗(yàn)
實(shí)驗(yàn)-對(duì)esp進(jìn)行驗(yàn)證
操作系統(tǒng)-從保護(hù)模式返回實(shí)模式
操作系統(tǒng)-從保護(hù)模式返回實(shí)模式操作系統(tǒng)-從保護(hù)模式返回實(shí)模式![]
操作系統(tǒng)-從保護(hù)模式返回實(shí)模式
操作系統(tǒng)-從保護(hù)模式返回實(shí)模式
這里運(yùn)行的情況是,同樣首先通過反編譯對(duì)圖1處的地址進(jìn)行查找,然后設(shè)置斷點(diǎn)并查該斷點(diǎn)處的esp寄存器值,然后單步調(diào)試值跳轉(zhuǎn)處在對(duì),esp寄存器值進(jìn)行查看,最后進(jìn)入到32位保護(hù)模式下對(duì)esp寄存器地址進(jìn)行查看,發(fā)現(xiàn)所有的esp寄存器的值都是相同的,所以在32位保護(hù)模式下剋有不對(duì)esp寄存器進(jìn)行賦值.
a.保護(hù)模式下的棧段
1.指定一段空間,并為其定義段描述符
2.根據(jù)段描述符表中的位置定義選擇子
3.初始化段寄存器
4.初始化棧頂指針
B.棧段的一般性定義(保護(hù)模式下)
主要對(duì)上章的段描述符與基址進(jìn)行了修改,同時(shí)重新定義了一個(gè)新的代碼節(jié),還有定義保護(hù)模式下專用的棧段

創(chuàng)新互聯(lián)專注為客戶提供全方位的互聯(lián)網(wǎng)綜合服務(wù),包含不限于成都網(wǎng)站制作、網(wǎng)站設(shè)計(jì)、古雷港網(wǎng)絡(luò)推廣、微信小程序定制開發(fā)、古雷港網(wǎng)絡(luò)營(yíng)銷、古雷港企業(yè)策劃、古雷港品牌公關(guān)、搜索引擎seo、人物專訪、企業(yè)宣傳片、企業(yè)代運(yùn)營(yíng)等,從售前售中售后,我們都將竭誠(chéng)為您服務(wù),您的肯定,是我們最大的嘉獎(jiǎng);創(chuàng)新互聯(lián)為所有大學(xué)生創(chuàng)業(yè)者提供古雷港建站搭建服務(wù),24小時(shí)服務(wù)熱線:028-86922220,官方網(wǎng)址:muchs.cn

%include "inc.asm"

org 0x9000

jmp CODE16_SEGMENT

[section .gdt]
; GDT definition
;                                
GDT_ENTRY       :     Descriptor    0,            0,           0
CODE32_DESC     :     Descriptor    0,    Code32SegLen - 1,    DA_C + DA_32
VIDEO_DESC      :     Descriptor 0xB8000,     0x07FFF,         DA_DRWA + DA_32
DATA32_DESC     :     Descriptor    0,    Data32SegLen - 1,    DA_DR + DA_32
STACK32_DESC    :     Descriptor    0,     TopOfStack32,     DA_DRW + DA_32
; GDT end

GdtLen    equ   $ - GDT_ENTRY

GdtPtr:
          dw   GdtLen - 1
          dd   0

; GDT Selector

Code32Selector    equ (0x0001 << 3) + SA_TIG + SA_RPL0
VideoSelector     equ (0x0002 << 3) + SA_TIG + SA_RPL0
Data32Selector    equ (0x0003 << 3) + SA_TIG + SA_RPL0
Stack32Selector   equ (0x0004 << 3) + SA_TIG + SA_RPL0

; end of [section .gdt]

TopOfStack16    equ 0x7c00

[section .dat]
[bits 32]
DATA32_SEGMENT:
    DTOS               db  "D.T.OS!", 0
    DTOS_OFFSET        equ DTOS - $$
    HELLO_WORLD        db  "Hello World!", 0
    HELLO_WORLD_OFFSET equ HELLO_WORLD - $$

Data32SegLen equ $ - DATA32_SEGMENT

[section .s16]
[bits 16]
CODE16_SEGMENT:
    mov ax, cs
    mov ds, ax
    mov es, ax
    mov ss, ax
    mov sp, TopOfStack16

    ; initialize GDT for 32 bits code segment
    mov esi, CODE32_SEGMENT
    mov edi, CODE32_DESC

    call InitDescItem

    mov esi, DATA32_SEGMENT
    mov edi, DATA32_DESC

    call InitDescItem

    mov esi, STACK32_SEGMENT
    mov edi, STACK32_DESC

    call InitDescItem

    ; initialize GDT pointer struct
    mov eax, 0
    mov ax, ds
    shl eax, 4
    add eax, GDT_ENTRY
    mov dword [GdtPtr + 2], eax

    ; 1. load GDT
    lgdt [GdtPtr]

    ; 2. close interrupt
    cli 

    ; 3. open A20
    in al, 0x92
    or al, 00000010b
    out 0x92, al

    ; 4. enter protect mode
    mov eax, cr0
    or eax, 0x01
    mov cr0, eax

    ; 5. jump to 32 bits code
    jmp dword Code32Selector : 0

; esi    --> code segment label
; edi    --> descriptor label
InitDescItem:
    push eax

    mov eax, 0
    mov ax, cs
    shl eax, 4
    add eax, esi
    mov word [edi + 2], ax
    shr eax, 16
    mov byte [edi + 4], al
    mov byte [edi + 7], ah

    pop eax

    ret

[section .s32]
[bits 32]
CODE32_SEGMENT:
    mov ax, VideoSelector
    mov gs, ax

    mov ax, Stack32Selector
    mov ss, ax

    mov eax, TopOfStack32
    mov esp, eax

    mov ax, Data32Selector
    mov ds, ax

    mov ebp, DTOS_OFFSET
    mov bx, 0x0C
    mov dh, 12
    mov dl, 33

    call PrintString

    mov ebp, HELLO_WORLD_OFFSET
    mov bx, 0x0C
    mov dh, 13
    mov dl, 31

    call PrintString

    jmp $

; ds:ebp    --> string address
; bx        --> attribute
; dx        --> dh : row, dl : col
PrintString:
    push ebp
    push eax
    push edi
    push cx
    push dx

print:
    mov cl, [ds:ebp]
    cmp cl, 0
    je end
    mov eax, 80
    mul dh
    add al, dl
    shl eax, 1
    mov edi, eax
    mov ah, bl
    mov al, cl
    mov [gs:edi], ax
    inc ebp
    inc dl
    jmp print

end:
    pop dx
    pop cx
    pop edi
    pop eax
    pop ebp

    ret

Code32SegLen    equ    $ - CODE32_SEGMENT

[section .gs]
[bits 32]
STACK32_SEGMENT:
    times 1024 * 4 db 0

Stack32SegLen equ $ - STACK32_SEGMENT
TopOfStack32  equ Stack32SegLen - 1

make之后在bochs下的運(yùn)行結(jié)果
操作系統(tǒng)-從保護(hù)模式返回實(shí)模式
現(xiàn)在通過實(shí)驗(yàn)對(duì)esp再次進(jìn)行查看,首先再次通過反編譯對(duì)跳轉(zhuǎn)指令查看,然后設(shè)置斷點(diǎn)并單步查看,并單步查看的寄存器地址的變化-ss段寄存器指向了定義的棧段,最后esp指向棧空間的限制處,最后打印處字符串,說明自定義的棧段空間被使用了操作系統(tǒng)-從保護(hù)模式返回實(shí)模式操作系統(tǒng)-從保護(hù)模式返回實(shí)模式
C.是否能從保護(hù)模式返回實(shí)模式?
a.80x86中的一個(gè)神秘限制
1.無法直接從32位代碼段回到實(shí)模式
2.只能從16位代碼段間接返回實(shí)模式
3.在返回前必須用合適的選擇子對(duì)寄存器賦值
b.處理器中的設(shè)計(jì)簡(jiǎn)介
1.80286之后的處理器都提供兼容8086的實(shí)模式
2.然而,絕大多數(shù)處理器都運(yùn)行于保護(hù)模式
3.因此,保護(hù)模式的運(yùn)行效率至關(guān)重要
4.那么,處理器如何高效的訪問內(nèi)存中的段描述符?

解決方案-高速緩存存儲(chǔ)器
a.當(dāng)使用選擇子設(shè)置段寄存器時(shí)
1.根據(jù)選擇子訪問內(nèi)存中的段描述符
2.將段描述符加載到段寄存器的高速緩沖存儲(chǔ)器
3.需要段描述符信息時(shí),直接從高速緩沖存儲(chǔ)器中獲得
但是會(huì)出現(xiàn)一個(gè)問題,當(dāng)處理器運(yùn)行于實(shí)模式時(shí),段寄存器的高速緩沖存儲(chǔ)器是否會(huì)用到?
在這里需要注意的是-在實(shí)模式下,高速緩沖存儲(chǔ)器仍然發(fā)揮著作用,段基址是32位,其值是相應(yīng)段寄存器的值乘以16,實(shí)模式下段基址有效位為20位,段界限固定為0xFFFF(64K),段屬性的值不可設(shè)置,只能繼續(xù)沿用保護(hù)方式下所設(shè)置的值
操作系統(tǒng)-從保護(hù)模式返回實(shí)模式
因此,當(dāng)從保護(hù)模式返回實(shí)模式時(shí)-提供加載一個(gè)合適的描述符選擇子到有關(guān)段寄存器,以使得對(duì)應(yīng)段描述符高速緩沖寄存器中含有合適的段界限和屬性
返回實(shí)模式的流程
操作系統(tǒng)-從保護(hù)模式返回實(shí)模式操作系統(tǒng)-從保護(hù)模式返回實(shí)模式
代碼

%include "inc.asm"

org 0x9000

jmp ENTRY_SEGMENT

[section .gdt]
; GDT definition
;                                 段基址,       段界限,       段屬性
GDT_ENTRY       :     Descriptor    0,            0,           0
CODE32_DESC     :     Descriptor    0,    Code32SegLen - 1,    DA_C + DA_32
VIDEO_DESC      :     Descriptor 0xB8000,     0x07FFF,         DA_DRWA + DA_32
DATA32_DESC     :     Descriptor    0,    Data32SegLen - 1,    DA_DR + DA_32
STACK32_DESC    :     Descriptor    0,     TopOfStack32,       DA_DRW + DA_32
CODE16_DESC     :     Descriptor    0,        0xFFFF,          DA_C 
UPDATE_DESC     :     Descriptor    0,        0xFFFF,          DA_DRW
; GDT end

GdtLen    equ   $ - GDT_ENTRY

GdtPtr:
          dw   GdtLen - 1
          dd   0

; GDT Selector

Code32Selector    equ (0x0001 << 3) + SA_TIG + SA_RPL0
VideoSelector     equ (0x0002 << 3) + SA_TIG + SA_RPL0
Data32Selector    equ (0x0003 << 3) + SA_TIG + SA_RPL0
Stack32Selector   equ (0x0004 << 3) + SA_TIG + SA_RPL0
Code16Selector    equ (0x0005 << 3) + SA_TIG + SA_RPL0
UpdateSelector    equ (0x0006 << 3) + SA_TIG + SA_RPL0
; end of [section .gdt]

TopOfStack16    equ 0x7c00

[section .dat]
[bits 32]
DATA32_SEGMENT:
    DTOS               db  "D.T.OS!", 0
    DTOS_OFFSET        equ DTOS - $$
    HELLO_WORLD        db  "Hello World!", 0
    HELLO_WORLD_OFFSET equ HELLO_WORLD - $$

Data32SegLen equ $ - DATA32_SEGMENT

[section .s16]
[bits 16]
ENTRY_SEGMENT:
    mov ax, cs
    mov ds, ax
    mov es, ax
    mov ss, ax
    mov sp, TopOfStack16

    mov [BACK_TO_REAL_MODE + 3], ax

    ; initialize GDT for 32 bits code segment
    mov esi, CODE32_SEGMENT
    mov edi, CODE32_DESC

    call InitDescItem

    mov esi, DATA32_SEGMENT
    mov edi, DATA32_DESC

    call InitDescItem

    mov esi, STACK32_SEGMENT
    mov edi, STACK32_DESC

    call InitDescItem

    mov esi, CODE16_SEGMENT
    mov edi, CODE16_DESC

    call InitDescItem

    ; initialize GDT pointer struct
    mov eax, 0
    mov ax, ds
    shl eax, 4
    add eax, GDT_ENTRY
    mov dword [GdtPtr + 2], eax

    ; 1. load GDT
    lgdt [GdtPtr]

    ; 2. close interrupt
    cli 

    ; 3. open A20
    in al, 0x92
    or al, 00000010b
    out 0x92, al

    ; 4. enter protect mode
    mov eax, cr0
    or eax, 0x01
    mov cr0, eax

    ; 5. jump to 32 bits code
    jmp dword Code32Selector : 0

BACK_ENTRY_SEGMENT:
    mov ax, cs
    mov ds, ax
    mov es, ax
    mov ss, ax
    mov sp, TopOfStack16

    in al, 0x92
    and al, 11111101b
    out 0x92, al

    sti

    mov bp, HELLO_WORLD
    mov cx, 12
    mov dx, 0
    mov ax, 0x1301
    mov bx, 0x0007
    int 0x10

    jmp $

; esi    --> code segment label
; edi    --> descriptor label
InitDescItem:
    push eax

    mov eax, 0
    mov ax, cs
    shl eax, 4
    add eax, esi
    mov word [edi + 2], ax
    shr eax, 16
    mov byte [edi + 4], al
    mov byte [edi + 7], ah

    pop eax

    ret

[section .s16]
[bits 16]
CODE16_SEGMENT:
    mov ax, UpdateSelector
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    mov ss, ax

    mov eax, cr0
    and al, 11111110b
    mov cr0, eax

BACK_TO_REAL_MODE:    
    jmp 0 : BACK_ENTRY_SEGMENT

Code16SegLen    equ    $ - CODE16_SEGMENT

[section .s32]
[bits 32]
CODE32_SEGMENT:
    mov ax, VideoSelector
    mov gs, ax

    mov ax, Stack32Selector
    mov ss, ax

    mov eax, TopOfStack32
    mov esp, eax

    mov ax, Data32Selector
    mov ds, ax

    mov ebp, DTOS_OFFSET
    mov bx, 0x0C
    mov dh, 12
    mov dl, 33

    call PrintString

    mov ebp, HELLO_WORLD_OFFSET
    mov bx, 0x0C
    mov dh, 13
    mov dl, 31

    call PrintString

    jmp Code16Selector : 0

; ds:ebp    --> string address
; bx        --> attribute
; dx        --> dh : row, dl : col
PrintString:
    push ebp
    push eax
    push edi
    push cx
    push dx

print:
    mov cl, [ds:ebp]
    cmp cl, 0
    je end
    mov eax, 80
    mul dh
    add al, dl
    shl eax, 1
    mov edi, eax
    mov ah, bl
    mov al, cl
    mov [gs:edi], ax
    inc ebp
    inc dl
    jmp print

end:
    pop dx
    pop cx
    pop edi
    pop eax
    pop ebp

    ret

Code32SegLen    equ    $ - CODE32_SEGMENT

[section .gs]
[bits 32]
STACK32_SEGMENT:
    times 1024 * 4 db 0

Stack32SegLen equ $ - STACK32_SEGMENT
TopOfStack32  equ Stack32SegLen - 1

運(yùn)行結(jié)果
操作系統(tǒng)-從保護(hù)模式返回實(shí)模式
小結(jié)
1.定義保護(hù)模式的棧段時(shí),必須設(shè)置段選擇子和棧頂指針
2.從保護(hù)模式能夠間接跳轉(zhuǎn)返回實(shí)模式
3.在實(shí)模式下,依然使用高速緩沖存儲(chǔ)器中數(shù)據(jù)做有效性判斷
4.通過運(yùn)行時(shí)修改指令中的數(shù)據(jù)能夠動(dòng)態(tài)決定代碼的行為

文章名稱:操作系統(tǒng)-從保護(hù)模式返回實(shí)模式
路徑分享:http://muchs.cn/article20/igheco.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站策劃、網(wǎng)站排名、響應(yīng)式網(wǎng)站、搜索引擎優(yōu)化微信小程序、網(wǎng)站改版

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

商城網(wǎng)站建設(shè)