"Self-written operating system" source code Analysis-Chapter III PMTEST5.ASM

Source: Internet
Author: User
In Pmtest4, we have seen how to transfer from a low privilege level to a highly privileged level for non-conformance code. But how do we move from a high-privileged level to a low-privileged level? At first we were in real mode, the ring 0, how we went from ring 0 to Ring3, which is not possible through call and jmp, and how we should do it. This article is mainly for you to answer these questions, showing the way to achieve this level of privilege transfer. In this section, you will learn how to switch freely between privileged levels.

First, the preparatory theory 1. About Stacks

We all know that you can use call and jmp for long jumps or short jumps (intra-segment or inter-segment transfer). However, after all, jmp and call are different, in which calls commands affect the stack: for a short invocation, when the calling instruction executes, the EIP of the next instruction is in the stack, and when the RET instruction executes =, the eip pops up from the stack. The changes to the stack before and after the call command execution are as follows (note the RET instruction with parameters):

A schematic diagram of the return time of a short call:


Long invocation is similar to this, the difference is that when the call command executes, the stack is also compressed CS.


2. Privilege Level Transformations

Note: If we take a long jump with the call instruction and the privilege level changes, a stack switch occurs at this point, such as switching from A to B. But our data is stored on a, how to return from B. Originally, Intel provided a mechanism to copy some of the contents of a onto the B stack. At the same time, the a stack is going to switch to the B stack, but how does it know where the B stack is? The answer: Originally this content is stored in the TSS structure of the task, and TSS is the task state segment. Each task has a maximum of four stack segments, but only one ESP and SS,TSS solves the problem of data preservation in the context of stack switching. For more information about TSS, refer to: Protection mode and its programming-task switching http://blog.csdn.net/trochiluses/article/details/19768579.

The schematic is as follows:



For example, we are currently ring 3 and need to be transferred to Ring 1, when the stack will automatically switch to SS1 and ESP1. (Because the stack information is obtained from the TSS only by switching from the outer to the inner layer, there is no stack information related to ring 3 in TSS.) So how to get the information of the destination from the inner layer to the outer layers. Press into the stack ahead of time to get the return information).

The processing of the stack during the switchover can be referred to: protection mode and its programming--the detailed meaning of protection: transferring privileged level http://blog.csdn.net/trochiluses/article/details/19573651 by calling the gate


second, code analysis

This part of the code is similar to the code in PMTEST4, we only use the bold part to mark the change and add the code, unchanged and not specifically affect the logic of the code we directly omitted, to analyze:

; ==========================================
%include "Pm.inc"; constants, macros, and some instructions

Org 0100h
JMP Label_begin

[section. GDT]
; GDT
; Segment base, segment bounds, properties
Label_gdt:descriptor 0, 0, 0; NULL descriptor
Label_desc_code_ring3:descriptor 0, Segcodering3len-1, Da_c + da_32 + da_dpl3; Non-Uniform code snippet, 32
Label_desc_stack:descriptor 0, Topofstack, Da_drwa + da_32; stack, 32 bits; a stack without a tag, actually a ring 0.
Label_desc_stack3:descriptor 0, TopOfStack3, Da_drwa + da_32 + da_dpl3; Stack, 32 bit; Ring 3
Label_desc_ldt:descriptor 0, LDTLen-1, Da_ldt; LDT
Label_desc_tss:descriptor 0, TSSLen-1, DA_386TSS; Tss
label_desc_video:descriptor0b8000h, 0FFFFH, DA_DRW + da_dpl3; Memory first address, in order to read and write memory in Ring 3, we changed the privilege level of the memory segment


; Gate target selector, offset, DCount, attribute
label_call_gate_test:gate selectorcodedest, 0, 0, da_386cgate + da_dpl3; the privilege level of the gate descriptor is also ring 3, otherwise it cannot be accessed
; GDT End

Gdtlen equ $-LABEL_GDT; GDT length
Gdtptr DW GdtLen-1; GDT boundaries
DD 0; GDT Base Address

; GDT Select Child
Selectornormal EQULABEL_DESC_NORMAL-LABEL_GDT
Selectorcodering3equ LABEL_DESC_CODE_RING3-LABEL_GDT + sa_rpl3
Selectorstack3equ LABEL_DESC_STACK3-LABEL_GDT + sa_rpl3
Selectortssequ LABEL_DESC_TSS-LABEL_GDT
Selectorcallgatetestequ LABEL_CALL_GATE_TEST-LABEL_GDT + sa_rpl3
; END of [section. GDT]
; ========================================================================================================

[section. Data1]; Data segment
Spvalueinrealmode DW 0
; String
Pmmessage:db "in Protect Mode now. ^-^ ", 0; Show this string after entering protected mode
;*******************************
Datalen equ $-Label_data
; END of [section. Data1]

===============================================================================================
; Global Stack Segment
[section. GS]
Label_stack:
Times 0 db
Topofstack equ$-Label_stack-1
; END of [section. GS]
================================================================================================

; stack segment Ring3
[section. S3]
ALIGN 32
[BITS 32]
LABEL_STACK3:
Times 0 db
TopOfStack3 equ$-Label_stack3-1
; END of [section. S3]

=================================================================================================
; TSS---------------------------------------------------------------------------------------------
[section. TSS]
ALIGN 32
[BITS 32]
LABEL_TSS:
DD 0; Back
DD Topofstack; Level 0 Stack
DD Selectorstack;
DD 0; Level 1 Stack
DD 0;
; TSS ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^, ^^ ^^ ^^ ^^ ^^ ^^ ^^, ^^ ^^ ^^ ^^ ^^ ^^ the ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ the ^^ of ^^ ^^ ^^ ^^.
========================================================================================================

[section. S16]
[BITS 16]
Label_begin:
MOV ax, CS
MOV ds, ax
MOV es, ax
mov ss, ax
mov sp, 0100h
mov [label_go_back_to_real+3], ax
mov [Spvalueinrealmode], SP

; Initializing a 16-bit code snippet descriptor
MOV ax, CS
;********************
mov byte [Label_desc_code16 + 7], ah

; Initializing a 32-bit code snippet descriptor
; Initialize the code snippet descriptor of the Test call gate
; Initialize Data segment Descriptor
; Initialize the stack segment descriptor
; Initialize the stack segment descriptor (RING3)
xor eax, EAX
mov ax, DS
SHL EAX, 4
add eax, Label_stack3
mov Word [Label_desc_stack3 + 2], ax
shr eax, 16
mov byte [Label_desc_stack3 + 4], AL
mov byte [Label_desc_stack3 + 7], ah

; Initializes the descriptor of the LDT in the GDT
; Initializing descriptors in the LDT
; initialize RING3 descriptor
xor eax, EAX
mov ax, DS
SHL EAX, 4
add eax, Label_code_ring3
mov Word [label_desc_code_ring3 + 2], ax
shr eax, 16
mov byte [Label_desc_code_ring3 + 4], AL
mov byte [label_desc_code_ring3 + 7], ah


; Initialize the TSS descriptor
Xoreax, eax
mov ax, DS
SHL EAX, 4
add eax, LABEL_TSS
mov Word [label_desc_tss + 2], ax
shr eax, 16
mov byte [Label_desc_tss + 4], AL
mov byte [label_desc_tss + 7], ah


; Preparing to load GDTR
; Load GDTR
; Off interrupt
; Open Address line A20
; Ready to switch to protected mode
; Real access to Protected mode
JMP DWORD selectorcode32:0;  Executing this sentence will load the SelectorCode32 into CS and jump to code32selector:0 Secretariat
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Label_real_entry:; Jump back from Protected mode to real mode.
MOV ax, CS
Close A20 Address Line
; Open Interrupt
; ┛ Back to DOS
; END of [section. S16]
==============================================================================================

[section. S32]; 32-bit code snippet. Jumped in by real mode.
[BITS 32]
LABEL_SEG_CODE32:
Movax, Selectordata
MOVDS, Ax; Data Segment Selection Sub
; Video Segment Selector
; Stack Segment Selection Sub
MOVESP, Topofstack

; A string is shown below
; Display complete
Call Dispreturn
; Load TSS
Movax, SELECTORTSS

Ltrax, when a privilege-level transformation occurs within a task, the stack is switched, and the pointer to the inner stack is stored in the TSS of the current task, so the task state segment register TR is set.


PushSelectorStack3; SS3
Push TopOfStack3; SP3
Push SelectorCodeRing3; cs3
Push 0; Eip
RETF; RING0, Ring3, historic transfer. The number ' 3 ' will be printed.

Note: This key retf instruction, which pops up two values, one to the EIP, another to the ECS; in this way, to ring 3; Special attention is paid to the RETF directive, which is used for long returns and can be used for long returns with privileged-level transformations. The above reason is to push 4 parameters, because RETF to use these four parameters. The reason is to LOADTSS, because later will return from Ring3 to ring 0.


In addition, there is a need to pay special attention to the TSS here; if there is no TSS, we can only move from a high privileged level to a low privileged level; we cannot move from a low privilege level to a high privilege level. In other words, if a stack switch is involved, TSS must be used. We can comment out this sentence of the Ltr Ax and see the results (see the last picture).
; ------------------------------------------------------------------------

Segcode32len equ$-Label_seg_code32
; END of [section. S32]

;=======================================================================================================

[section. Sdest]; Call Gate Destination Segment
[BITS 32]

Label_seg_code_dest:
mov ax, selectorvideo
mov gs, AX; Video Segment Selector (purpose)
Movedi, (80 * 12 + 0) * 2; Screen 12th, column No. 0.
mov ah, 0Ch; 0000: Black Bottom 1100: Scarlet Letter
mov al, ' C '
mov [Gs:edi], ax
; Load LDT
mov ax, Selectorldt
Lldt Ax
jmpselectorldtcodea:0; Jumps into the local task and will print the letter ' L '.
; retf
Segcodedestlenequ $-Label_seg_code_dest
; END of [section. Sdest]
======================================================================================

; 16-bit code snippet. Jump from a 32-bit code snippet and jump back to real mode
[section. S16code]
ALIGN 32
[BITS 16]
LABEL_SEG_CODE16:
; To jump back to Real mode:
mov ax, selectornormal
;******************************************
Label_go_back_to_real:
JMP 0:label_real_entry; The segment address is set to the correct value at the beginning of the program

Code16len equ $-Label_seg_code16

; END of [section. S16code]
=============================================================================
; LDT
[section. Ldt]
ALIGN 32
Label_ldt:
; Segment base segment bounds, properties
Label_ldt_desc_codea:descriptor 0, CodeALen-1, Da_c + da_32; Code, 32-bit

Ldtlen equ $-Label_ldt

; LDT Selection Sub
Selectorldtcodea Equlabel_ldt_desc_codea-label_ldt + sa_til
; END of [section. Ldt]

==================================================================================
; Codea (LDT, 32-bit code snippet)
[Section. La]
ALIGN 32
[BITS 32]
Label_code_a:
mov ax, selectorvideo
mov gs, AX; Video Segment Selector (purpose)
Movedi, (80 * 13 + 0) * 2; Screen 13th, column No. 0.
mov ah, 0Ch; 0000: Black Bottom 1100: Scarlet Letter
mov al, ' L '
mov [Gs:edi], ax
; Ready to jump back to real mode via 16-bit code segment
JMP selectorcode16:0
Codealen equ $-label_code_a
; END of [section. La]

=======================================================================================

; CodeRing3
[section. Ring3]
ALIGN 32
[BITS 32]
Label_code_ring3:
mov ax, selectorvideo
mov gs, AX; Video Segment Selector (purpose)
Movedi, (80 * 14 + 0) * 2; Screen 14th, column No. 0.
mov ah, 0Ch; 0000: Black Bottom 1100: Scarlet Letter
mov al, ' 3 '
mov [Gs:edi], ax

callselectorcallgatetest:0; Test call Gate (with privileged level transform), the letter ' C ' will be printed.

jmp$; Note: The program will stop here


segcodering3lenequ $-Label_code_ring3
; END of [section. Ring3]


The procedure is roughly executed as follows:

Protected mode enters the code snippet of 16b , ring=0, initializes the relevant segment descriptor, Gate descriptor, LDT descriptor, data segment descriptor, stack segment descriptor, descriptor in the LDT, the code snippet descriptor of the Ring 3 TSS descriptor, load GDT, Through long jmp, enter protection mode, enter 32b code snippet, ring = 0: initialize data segment, stack segment, select Sub Register of video segment, display a string, load TSS, use RETF instruction, transfer from ring 0 to ring 3 code snippet: display ' 3 ' in the code snippet and then enter the ring 0 code snippet by calling the door: print the letter C, then go through jmp to jump to the local code snippet: Print the letter ' L '; The program goes back to ring 3 and becomes a loop.


View running results: We first entered a different privilege level.


Below: Note the results of the TSS, which can be seen from ring 0 into ring 3, but not from ring 3 into ring 0.


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.