- 浏览: 548857 次
- 性别:
- 来自: 上海
-
文章分类
- 全部博客 (231)
- 一个操作系统的实现 (20)
- 汇编(NASM) (12)
- Linux编程 (11)
- 项目管理 (4)
- 计算机网络 (8)
- 设计模式(抽象&封装) (17)
- 数据结构和算法 (32)
- java基础 (6)
- UML细节 (2)
- C/C++ (31)
- Windows (2)
- 乱七八糟 (13)
- MyLaB (6)
- 系统程序员-成长计划 (8)
- POJ部分题目 (10)
- 数学 (6)
- 分布式 & 云计算 (2)
- python (13)
- 面试 (1)
- 链接、装载与库 (11)
- java并行编程 (3)
- 数据库 (0)
- 体系结构 (3)
- C++ template / STL (4)
- Linux环境和脚本 (6)
最新评论
-
chuanwang66:
默默水塘 写道typedef void(*Fun)(void) ...
C++虚函数表(转) -
默默水塘:
typedef void(*Fun)(void);
C++虚函数表(转) -
lishaoqingmn:
写的很好,例子简单明了,将观察者模式都表达了出来。
这里是ja ...
观察者模式——Observer
在此之前,先要熟悉汇编指令“长/短jmp”、“长/短call”、ret、retf.
一、调用门“纯粹”作为入口地址
调用门本质上就是个入口地址,只是增加若干属性而已。例子pmtest5a.asm完全将其作为一个地址使用。
二、使用调用门,在不同特权级间转移
使用调用门分为以下两个阶段,难点无非就是“TSS”和“堆栈的变化”。本质上,TSS就是记录了不同特权级堆栈的SS和ESP;堆栈的变化无非就是无非就是短跳转压入SS&ESP,长跳转再多加CS&EIP,有时候也要压入和弹出参数,并且需要相关的检验。详见书上P55~60,或者这里http://www.cnblogs.com/Aoysme/archive/2011/01/17/1937796.html
1. 从高特权级别到低特权级别,通过ret指令实现;
关键代码:
[SECTION .s32] ... ; Load TSS(Task-State Stack) to register TR mov ax, SelectorTSS ltr ax ; Ring0 -> Ring3,历史性转移!将打印数字'3' push SelectorStack3 push TopOfStack3 push SelectorCodeRing3 push 0 retf ...
2. 从低特权级别到高特权级别,通过调用门和call指令来实现。
关键代码:
[SECTION .ring3] ... ; 打印数字'3' call SelectorCallGateTest:0 ;Ring3 -> Ring0 jmp $
以上调用门指向下面的段[SECTION .sdest](称为“调用门目标段”),而该目标段是ring0级别的——
LABEL_DESC_CODE_DEST: Descriptor 0, SegCodeDestLen-1, DA_C+DA_32 ;默认DA_DPL0
LABEL_DESC_CODE_RING3: Descriptor 0, SegCodeRing3Len-1, DA_C+DA_32+DA_DPL3
下面这个实验(pmtest5c.asm)将展示 “1. 高特权级别-->低特权级别” & “2. 低特权级别-->高特权级别”。主要流程如下。在第三部分将详细赏析每个代码段代码。
跳入保护模式
[SECTION .s32]-->
[SECTION .ring3]-->
调用门-->[SECTION .sdest]-->
[SECTION .la]
跳回实模式
和TSS相关用红色标记;
调用门本身用深绿色标记;
调用门指向的段用浅绿色标记;
; ==========================================
; pmtest5.asm
; 编译方法:nasm pmtest5.asm -o pmtest5.com
; ==========================================
%include "pm.inc" ; 常量, 宏, 以及一些说明
org 0100h
jmp LABEL_BEGIN
[SECTION .gdt]
; GDT
; 段基址, 段界限 , 属性
LABEL_GDT: Descriptor 0, 0, 0 ;空描述符
LABEL_DESC_NORMAL: Descriptor 0, 0ffffh, DA_DRW ;Normal描述符
LABEL_DESC_CODE32: Descriptor 0, SegCode32Len-1, DA_C+DA_32 ;非一致,32
LABEL_DESC_CODE16: Descriptor 0, 0ffffh, DA_C ;非一致,16
LABEL_DESC_CODE_DEST: Descriptor 0, SegCodeDestLen-1, DA_C+DA_32 ;非一致,32
LABEL_DESC_CODE_RING3: Descriptor 0, SegCodeRing3Len-1, DA_C+DA_32+DA_DPL3
LABEL_DESC_DATA: Descriptor 0, DataLen-1, DA_DRW ;Data
LABEL_DESC_STACK: Descriptor 0, TopOfStack, DA_DRWA+DA_32 ;Stack,32
LABEL_DESC_STACK3: Descriptor 0, TopOfStack3, DA_DRWA+DA_32+DA_DPL3
LABEL_DESC_LDT: Descriptor 0, LDTLen-1, DA_LDT ;LDT
LABEL_DESC_TSS: Descriptor 0, TSSLen-1, DA_386TSS ;TSS
LABEL_DESC_VIDEO: Descriptor 0B8000h, 0ffffh, DA_DRW+DA_DPL3
; 门 目标选择子, 偏移, DCount, 属性
LABEL_CALL_GATE_TEST: Gate SelectorCodeDest, 0, 0, DA_386CGate + DA_DPL3
; GDT 结束
GdtLen equ $ - LABEL_GDT ; GDT长度
GdtPtr dw GdtLen - 1 ; GDT界限
dd 0 ; GDT基地址
; GDT 选择子
SelectorNormal equ LABEL_DESC_NORMAL - LABEL_GDT
SelectorCode32 equ LABEL_DESC_CODE32 - LABEL_GDT
SelectorCode16 equ LABEL_DESC_CODE16 - LABEL_GDT
SelectorCodeDest equ LABEL_DESC_CODE_DEST - LABEL_GDT
SelectorCodeRing3 equ LABEL_DESC_CODE_RING3 - LABEL_GDT + SA_RPL3
SelectorData equ LABEL_DESC_DATA - LABEL_GDT
SelectorStack equ LABEL_DESC_STACK - LABEL_GDT
SelectorStack3 equ LABEL_DESC_STACK3 - LABEL_GDT + SA_RPL3
SelectorLDT equ LABEL_DESC_LDT - LABEL_GDT
SelectorTSS equ LABEL_DESC_TSS - LABEL_GDT
SelectorVideo equ LABEL_DESC_VIDEO - LABEL_GDT
SelectorCallGateTest equ LABEL_CALL_GATE_TEST - LABEL_GDT + SA_RPL3
; END of [SECTION .gdt]
[SECTION .data1] ; 数据段
ALIGN 32
[BITS 32]
LABEL_DATA:
SPValueInRealMode dw 0
; 字符串
PMMessage: db "In Protect Mode now. ^-^", 0 ; 进入保护模式后显示此字符串
OffsetPMMessage equ PMMessage - $$
StrTest: db "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 0
OffsetStrTest equ StrTest - $$
DataLen equ $ - LABEL_DATA
; END of [SECTION .data1]
; 全局堆栈段
[SECTION .gs]
ALIGN 32
[BITS 32]
LABEL_STACK:
times 512 db 0
TopOfStack equ $ - LABEL_STACK - 1
; END of [SECTION .gs]
; 堆栈段ring3
[SECTION .s3]
ALIGN 32
[BITS 32]
LABEL_STACK3:
times 512 db 0
TopOfStack3 equ $ - LABEL_STACK3 - 1
; END of [SECTION .s3]
; TSS ---------------------------------------------------------------------------------------------
[SECTION .tss]
ALIGN 32
[BITS 32]
LABEL_TSS:
DD 0 ; Back
DD TopOfStack ; 0 级堆栈 -->除了0级堆栈外,其他字段没做任何初始化。因为本例中只用到这部分
DD SelectorStack ; -->除了0级堆栈外,其他字段没做任何初始化。因为本例中只用到这部分
DD 0 ; 1 级堆栈
DD 0 ;
DD 0 ; 2 级堆栈
DD 0 ;
DD 0 ; CR3
DD 0 ; EIP
DD 0 ; EFLAGS
DD 0 ; EAX
DD 0 ; ECX
DD 0 ; EDX
DD 0 ; EBX
DD 0 ; ESP
DD 0 ; EBP
DD 0 ; ESI
DD 0 ; EDI
DD 0 ; ES
DD 0 ; CS
DD 0 ; SS
DD 0 ; DS
DD 0 ; FS
DD 0 ; GS
DD 0 ; LDT
DW 0 ; 调试陷阱标志
DW $ - LABEL_TSS + 2 ; I/O位图基址
DB 0ffh ; I/O位图结束标志
TSSLen equ $ - LABEL_TSS
; TSS ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[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
; 初始化 16 位代码段描述符
mov ax, cs
movzx eax, ax
shl eax, 4
add eax, LABEL_SEG_CODE16
mov word [LABEL_DESC_CODE16 + 2], ax
shr eax, 16
mov byte [LABEL_DESC_CODE16 + 4], al
mov byte [LABEL_DESC_CODE16 + 7], ah
; 初始化 32 位代码段描述符
xor eax, eax
mov ax, cs
shl eax, 4
add eax, LABEL_SEG_CODE32
mov word [LABEL_DESC_CODE32 + 2], ax
shr eax, 16
mov byte [LABEL_DESC_CODE32 + 4], al
mov byte [LABEL_DESC_CODE32 + 7], ah
; 初始化测试调用门的代码段描述符
xor eax, eax
mov ax, cs
shl eax, 4
add eax, LABEL_SEG_CODE_DEST
mov word [LABEL_DESC_CODE_DEST + 2], ax
shr eax, 16
mov byte [LABEL_DESC_CODE_DEST + 4], al
mov byte [LABEL_DESC_CODE_DEST + 7], ah
; 初始化数据段描述符
xor eax, eax
mov ax, ds
shl eax, 4
add eax, LABEL_DATA
mov word [LABEL_DESC_DATA + 2], ax
shr eax, 16
mov byte [LABEL_DESC_DATA + 4], al
mov byte [LABEL_DESC_DATA + 7], ah
; 初始化堆栈段描述符
xor eax, eax
mov ax, ds
shl eax, 4
add eax, LABEL_STACK
mov word [LABEL_DESC_STACK + 2], ax
shr eax, 16
mov byte [LABEL_DESC_STACK + 4], al
mov byte [LABEL_DESC_STACK + 7], ah
; 初始化堆栈段描述符(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
; 初始化 LDT 在 GDT 中的描述符
xor eax, eax
mov ax, ds
shl eax, 4
add eax, LABEL_LDT
mov word [LABEL_DESC_LDT + 2], ax
shr eax, 16
mov byte [LABEL_DESC_LDT + 4], al
mov byte [LABEL_DESC_LDT + 7], ah
; 初始化 LDT 中的描述符
xor eax, eax
mov ax, ds
shl eax, 4
add eax, LABEL_CODE_A
mov word [LABEL_LDT_DESC_CODEA + 2], ax
shr eax, 16
mov byte [LABEL_LDT_DESC_CODEA + 4], al
mov byte [LABEL_LDT_DESC_CODEA + 7], ah
; 初始化Ring3描述符
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
; 初始化 TSS 描述符
xor eax, 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
; 为加载 GDTR 作准备
xor eax, eax
mov ax, ds
shl eax, 4
add eax, LABEL_GDT ; eax <- gdt 基地址
mov dword [GdtPtr + 2], eax ; [GdtPtr + 2] <- gdt 基地址
; 加载 GDTR
lgdt [GdtPtr]
; 关中断
cli
; 打开地址线A20
in al, 92h
or al, 00000010b
out 92h, al
; 准备切换到保护模式
mov eax, cr0
or eax, 1
mov cr0, eax
; 真正进入保护模式
jmp dword SelectorCode32:0 ; 执行这一句会把 SelectorCode32 装入 cs, 并跳转到 Code32Selector:0 处
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LABEL_REAL_ENTRY: ; 从保护模式跳回到实模式就到了这里
mov ax, cs
mov ds, ax
mov es, ax
mov ss, ax
mov sp, [SPValueInRealMode]
in al, 92h ; ┓
and al, 11111101b ; ┣ 关闭 A20 地址线
out 92h, al ; ┛
sti ; 开中断
mov ax, 4c00h ; ┓
int 21h ; ┛回到 DOS
; END of [SECTION .s16]
[SECTION .s32]; 32 位代码段. 由实模式跳入.
[BITS 32]
LABEL_SEG_CODE32:
mov ax, SelectorData
mov ds, ax ; 数据段选择子
mov ax, SelectorVideo
mov gs, ax ; 视频段选择子
mov ax, SelectorStack
mov ss, ax ; 堆栈段选择子
mov esp, TopOfStack
; 下面显示一个字符串
mov ah, 0Ch ; 0000: 黑底 1100: 红字
xor esi, esi
xor edi, edi
mov esi, OffsetPMMessage ; 源数据偏移
mov edi, (80 * 10 + 0) * 2 ; 目的数据偏移。屏幕第 10 行, 第 0 列。
cld
.1:
lodsb
test al, al
jz .2
mov [gs:edi], ax
add edi, 2
jmp .1
.2: ; 显示完毕
call DispReturn
; Load TSS
mov ax, SelectorTSS
ltr ax ; 在任务内发生特权级变换时要切换堆栈,而内层(高特权级)堆栈的指针存放在当前任务的TSS中,所以要设置任务状态段寄存器TR。
push SelectorStack3
push TopOfStack3
push SelectorCodeRing3
push 0
retf ; Ring0 -> Ring3,历史性转移!将打印数字 '3'。
; ------------------------------------------------------------------------
DispReturn:
push eax
push ebx
mov eax, edi
mov bl, 160
div bl
and eax, 0FFh
inc eax
mov bl, 160
mul bl
mov edi, eax
pop ebx
pop eax
ret
; DispReturn 结束---------------------------------------------------------
SegCode32Len equ $ - LABEL_SEG_CODE32
; END of [SECTION .s32]
[SECTION .sdest]; 调用门目标段
[BITS 32]
LABEL_SEG_CODE_DEST:
mov ax, SelectorVideo
mov gs, ax ; 视频段选择子(目的)
mov edi, (80 * 12 + 0) * 2 ; 屏幕第 12 行, 第 0 列。
mov ah, 0Ch ; 0000: 黑底 1100: 红字
mov al, 'C'
mov [gs:edi], ax
; Load LDT
mov ax, SelectorLDT
lldt ax
jmp SelectorLDTCodeA:0 ; 跳入局部任务,将打印字母 'L'。
;retf
SegCodeDestLen equ $ - LABEL_SEG_CODE_DEST
; END of [SECTION .sdest]
; 16 位代码段. 由 32 位代码段跳入, 跳出后到实模式
[SECTION .s16code]
ALIGN 32
[BITS 16]
LABEL_SEG_CODE16:
; 跳回实模式:
mov ax, SelectorNormal
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov eax, cr0
and al, 11111110b
mov cr0, eax
LABEL_GO_BACK_TO_REAL:
jmp 0:LABEL_REAL_ENTRY ; 段地址会在程序开始处被设置成正确的值
Code16Len equ $ - LABEL_SEG_CODE16
; END of [SECTION .s16code]
; LDT
[SECTION .ldt]
ALIGN 32
LABEL_LDT:
; 段基址 段界限 , 属性
LABEL_LDT_DESC_CODEA: Descriptor 0, CodeALen - 1, DA_C + DA_32 ; Code, 32 位
LDTLen equ $ - LABEL_LDT
; LDT 选择子
SelectorLDTCodeA equ LABEL_LDT_DESC_CODEA - LABEL_LDT + SA_TIL
; END of [SECTION .ldt]
; CodeA (LDT, 32 位代码段)
[SECTION .la]
ALIGN 32
[BITS 32]
LABEL_CODE_A:
mov ax, SelectorVideo
mov gs, ax ; 视频段选择子(目的)
mov edi, (80 * 13 + 0) * 2 ; 屏幕第 13 行, 第 0 列。
mov ah, 0Ch ; 0000: 黑底 1100: 红字
mov al, 'L'
mov [gs:edi], ax
; 准备经由16位代码段跳回实模式
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 ; 视频段选择子(目的)
mov edi, (80 * 14 + 0) * 2 ; 屏幕第 14 行, 第 0 列。
mov ah, 0Ch ; 0000: 黑底 1100: 红字
mov al, '3'
mov [gs:edi], ax
call SelectorCallGateTest:0 ; 测试调用门(有特权级变换),将打印字母 'C'。
jmp $
SegCodeRing3Len equ $ - LABEL_CODE_RING3
; END of [SECTION .ring3]
三、逐段赏析pmtest5.asm
1、本段([SECTION .s32])属性:
[SECTION .gdt]
LABEL_DESC_CODE32: Descriptor 0, SegCode32Len-1, DA_C+DA_32 ;非一致,32
SelectorCode32 equ LABEL_DESC_CODE32 - LABEL_GDT
[SECTION .s32];32位代码段,由实模式跳入 ... (10行0列显示PMMessage,即"In Protect Mode now. ^-^") ... mov ax, SelectorTSS ltr ax ; 在任务内发生特权级变换时要切换堆栈,而内层堆栈的指针存放在当前任务的TSS中,所以要设置任务状态段寄存器TR push SelectorStack3 ;ss push TopOfStack3 ;esp push SelectorCodeRing3 ;cs push 0 ;eip retf ;ring0~~>ring3跳转
从[SECTION .s32]跳到[SECTION .ring3]是从高到低特权级的跳转!
本来ret(retf)是和call配合使用的指令,用来返回断点。这里单独使用,可以理解为“从[SECTION .32]返回[SECTION .ring3]”,用来从高特权级跳转到低特权级,具体过程如书P59叙述,P60图3.21所示:
1)检查被调用者堆栈中保存的CS中的RPL(对应代码push SelectorCodeRing3),以判断返回时是否要变换特权级。
此时发现当前特权级为0,转到特权级为3的代码段,发生了特权级变化(高-->低)。
2)加载被调用者堆栈上的cs和eip(SelectorCodeRing3和0)。
(此时怎么进行特权级检验???)
此时,就返回断点了——在本程序中cs和eip已经指向[SECTION .ring3]段了。
3)此retf不含参数,不用增加esp跳过参数。当前堆栈是被调用者([SECTION .s32])堆栈。
4)加载被调用者([SECTION .s32)堆栈中的ss和esp,切换到调用者([SECTION .ring3])堆栈。此时,被调用者([SECTION .s32)堆栈中的ss和esp被丢弃,但由于等会儿还要从低特权级转换回高特权级,故需要将“0级堆栈的SelectorStack和TopOfStack”提前放入TSS。
此时,当前堆栈从被调用者([SECTION .s32])堆栈变成了调用者([SECTION .ring3)堆栈了。
5)此retf不含参数,不用增加esp跳过参数。当前堆栈是调用者([SECTION .ring3)堆栈。
6)检查ds、es、fs、gs的值,如果其中哪一个寄存器指向的段的DPL小于CPL(此规则不适用于一致代码段),那么一个空描述符被加载到该寄存器。我想:此时这几个寄存器都被置空描述符了吧~(???)
2、本段([SECTION .ring3])属性:
[SECTION .gdt]
LABEL_DESC_CODE_RING3: Descriptor 0, SegCodeRing3Len-1, DA_C+DA_32+DA_DPL3
LABEL_DESC_STACK3: Descriptor 0, TopOfStack3, DA_DRWA+DA_32+DA_DPL3
SelectorCodeRing3 equ LABEL_DESC_CODE_RING3 - LABEL_GDT + SA_RPL3
SelectorStack3 equ LABEL_DESC_STACK3 - LABEL_GDT + SA_RPL3
[SECTION .ring3] ... (14行0列显示'3') ... call SelectorCallGateTest:0 ;调用调用门中的目标代码段,如果在目标段最后有retf可以返回这个断点,但我们不这么做。我们在目标段中继续进入局部段[SECTION .la],然后返回实模式 ...
这个跳转是“通过调用门 从低到高特权级”!
1)step1: 指示调用门的选择子的RPL<=门描述符DPL & 当前代码段的CPL<=门描述符的DPL。
此时,在[SECTION .ring3]中。因为[SECTION .ring3]是非一致代码段,故在从[SECTION .s32]跳转到该段时,已经设置CPL=3 (参见http://chuanwang66.iteye.com/admin/blogs/1075472)。即是说,此时CPL=3。
call SelectorCallGateTest:0调用调用门,由SelectorCallGateTest equ LABEL_CALL_GATE_TEST - LABEL_GDT + SA_RPL3)可知,调用门的RPL为3。即是说,此时RPL=3。
又调用门的DPL=3。
由上面三段的描述有: CPL<=调用门DPL & RPL<=调用门DPL。故可以访问到调用门中的目标段选择子了^_^
2)step2: CPL>=DPL,RPL不作检查(因为RPL总被清0)
现在,CPL=3; 目标段[SECTION .sdest]的DPL=0,且为非一致代码段。故CPL>=DPL(RPL不作检查),满足特权级检查,跳转到[SECTION .sdest],哈哈
3)跳转后,CPL被修改为0(原来为3)
因为CPL=目标段[SECTION .sdest]的DPL(=0),因此,跳转到[SECTION .sdest]后CPL=0
3、本段([SECTION .sdest])属性:
[SECTION .gdt]
; 门 目标选择子, 偏移, DCount, 属性
LABEL_CALL_GATE_TEST: Gate SelectorCodeDest, 0, 0, DA_386CGate + DA_DPL3
LABEL_DESC_CODE_DEST: Descriptor 0, SegCodeDestLen-1, DA_C+DA_32 ;非一致,32
SelectorCallGateTest equ LABEL_CALL_GATE_TEST - LABEL_GDT + SA_RPL3
SelectorCodeDest equ LABEL_DESC_CODE_DEST - LABEL_GDT
[SECTION .sdest] ;调用门目标段 ... (12行0列显示'C') ... mov ax, SelectorLDT lldt ax jmp SelectorLDTCodeA:0 ;跳到LDT中定义的局部段
[SECTION .sdest]段是非一致32位段,而且DPL=0,并且当前CPL=0。而此后用到的“DPL”和“选择子中的RPL”都为0,均在最高特权级上跳转,不需要设计权限检查了!啊,是不是突然感觉轻松许多了呢^_^
4、本段([SECTION .la])属性:
[SECTION .gdt]
LABEL_DESC_LDT: Descriptor 0, LDTLen-1, DA_LDT ;LDT
SelectorLDT equ LABEL_DESC_LDT - LABEL_GDT
[SECTION .ldt]
LABEL_LDT_DESC_CODEA: Descriptor 0, CodeALen - 1, DA_C + DA_32 ; Code, 32 位
SelectorLDTCodeA equ LABEL_LDT_DESC_CODEA - LABEL_LDT + SA_TIL
[SECTION .la] ... (13行0列显示'L') ... jmp SelectorCode16:0 ;准备经由16位代码段跳回实模式
参考:
http://blog.csdn.net/axman/archive/2009/12/09/4969131.aspx retf指令实现从高特权级到低特权级的跳转
发表评论
-
(第三章 8 )特权级——保护模式的特权级检查(DPL,RPL,CPL, 一致代码段,非一致代码段)
2013-03-20 11:14 2380特权级是保护模式下一个重要的概念,CPL,RPL和 ... -
(第6章 1)最简单的进程
2012-10-11 10:56 1049第一步——ring0 --> ring1 ... -
(第4章 2)突破512字节的限制
2012-09-15 11:40 2832一、代码 ... -
(第4章 1)软盘结构及其数据读取
2012-09-14 21:59 1961参考资料: http://blog.cs ... -
(第三章 12)中断
2012-09-11 20:20 1068一、中断和8259A中断控制器 1. ... -
(第三章 8 )特权级——CPL、DPL、RPL
2012-07-11 10:02 2472很久以后,等我大量翻阅关于“保护模式的特权级检 ... -
(第三章 0)保护模式如何“保护”
2012-03-14 07:59 1116IA32中“保护模式”的“保护”二字理解:(P48) ... -
(第一、二章)nasm的汇编和反汇编
2012-02-27 13:36 4994nasm的汇编和反汇编 步骤: 1. 汇编(bo ... -
(第三章 14)克勤克俭用内存——初始化页目录表、页表,开启分页机制
2011-07-22 11:30 249在启动分页机制SetupPaging之前,先调用了Di ... -
(第三章 13)克勤克俭用内存——查看内存块
2011-07-22 09:25 143[SECTION .data1] ALIGN 32 ... -
(第三章 12)克勤克俭用内存——显示字符串
2011-07-21 16:25 116DispStr调用方法: [SECTION . ... -
(第三章 11)根据自己内存情况 使用分页机制
2011-06-11 15:51 1508一、查看内存分布情况 设置“页目录表”和“页 ... -
参考博客-还有哪些人也在看这本书
2011-06-10 22:46 1408这位很详细: http://www.cnblogs.com/ ... -
(第三章 10)“代码段间跳转” 和 “访问数据段”
2011-06-10 15:40 1395下面说明代码段和数据段的访问: 一、代码段间跳转 ... -
(第三章 9)通过调用门进行有特权级变换的转移(二)
2011-06-08 11:29 191本文展示《(第三章 9)通过调用门进行有特权级变换的转移(一) ... -
(第三章 7)LDT
2011-06-06 09:49 1533先展示一下效果图: 直接看代码: ... -
(第三章 6)保护模式下,读写大地址内存 & 从32位保护模式跳回16位实模式(二)
2011-06-06 09:15 1502三、关于保护模式和实 ... -
(第三章 5)保护模式下,读写大地址内存 & 从32位保护模式跳回16位实模式(一)
2011-06-05 13:53 2095一、主要功能 ... -
(第三章 3)数据段/代码段描述符
2011-06-05 11:53 2292一、宏定义和属性常量 (代码段/数据段描述符见P32;门描述 ... -
(第三章 4)A20地址线
2011-06-03 20:43 2103A20地址线困惑我了很久,这篇文章终于揭开了这个谜 ...
相关推荐
#### 第三章 8086和Pentium的指令系统 1. **寻址方式的概念**:确定操作数的有效地址的方法。 2. **8086CPU的寻址方式**: - **立即寻址**:操作数直接包含在指令中。 - **寄存器寻址**:操作数在寄存器中。 - ...
内容概要:本文档详细介绍了VMware虚拟机的安装步骤,涵盖从环境准备到优化与迁移建议的全过程。首先,确保物理机满足VMware的硬件需求,如支持虚拟化的CPU、足够的内存和存储空间。接着,下载并运行VMware Workstation或ESXi的安装程序,完成基本配置和许可证激活,必要时重启系统以启用虚拟化功能。然后,创建新的虚拟机,选择操作系统镜像,合理分配资源并配置网络,以确保虚拟机与外部网络的连通性。之后,启动虚拟机并安装操作系统,完成硬盘分区、格式化等操作,并安装VMware Tools以增强性能。最后,针对平滑迁移和云环境部署提出了建议,强调了兼容性验证和备份与安全的重要性。 适合人群:具有计算机基础,对虚拟化技术有一定了解的技术人员或IT爱好者。 使用场景及目标:①个人用户希望通过VMware创建虚拟机进行操作系统测试或开发环境搭建;②企业级用户进行虚拟化平台的部署和迁移,提高业务连续性和安全性。 阅读建议:此文档提供了详细的VMware虚拟机安装步骤,建议读者在实际操作前仔细阅读每一步骤,并结合自身需求进行合理配置,特别是在资源分配和网络配置方面。对于企业级用户,还需关注云宏等国产虚拟化方案的无感迁移路径以及华为云等云服务商提供的部署指南。
# 基于C++的AWS IoT设备开发工具包 ## 项目简介 本项目是基于C++的AWS IoT设备SDK,用于与AWS IoT的各类服务交互,涵盖影子服务、作业服务和安全隧道服务等。借助该SDK,开发者能够实现设备与AWS IoT服务的连接、通信,完成诸如状态管理、作业执行等操作。 ## 项目的主要特性和功能 1. MQTT协议支持通过MQTT协议实现设备与AWS IoT服务间的通信。 2. 设备影子状态管理可对设备的影子状态进行获取、更新和删除操作。 3. 作业管理支持设备接收作业任务,并更新作业执行状态。 4. 安全隧道服务能在AWS资源间建立安全的通信通道。 5. 错误处理与日志记录具备完善的错误处理和日志记录机制,便于诊断和调试。 6. 多平台支持兼容Windows、Linux和macOS等多种操作系统。 ## 安装使用步骤 ### 环境要求 C++ 11或更高版本(Clang 3.9+、GCC 4.8+或MSVC 2015+)
第16章-超声波跟随功能 基于STM32的三路超声波自动跟随小车 毕业设计 课程设计
Microgrid systems have been recognized as a promising means for renewable energy integration, grid resilience, and power supply to remote areas. The optimal performance of these systems entails numerous challenges in terms of power sharing, stability, and energy harvesting from photovoltaic (PV) systems. The current study aims to improve microgrid performance using advanced control strategies, such as droop control and fuzzy logic-based maximum power point tracking (MPPT), for hybrid PV and battery energy systems. The study commenced with an introduction that portrays the significance of microgrid systems and the reasons for enhancing the operational efficiency of microgrids. The principal challenges associated with microgrid performance, including power quality, frequency regulation, and
内容概要:本文深入探讨了内嵌式永磁同步电机(IPMSM)复矢量电流调节器的设计及其动态解耦问题。首先介绍了IPMSM的基本特性和d、q轴电流存在的动态耦合问题,然后详细推导了复矢量数学模型,展示了如何将d、q轴电流转化为复矢量形式,从而简化了数学表达并消除了交叉耦合项。接着,文章设计了一种基于复矢量的电流调节器,采用比例积分(PI)控制算法,能够分别对d、q轴电流进行精准调节,实现动态解耦。最后,通过Matlab/Simulink进行了仿真验证,证明了该设计方案的有效性和优越性能。 适合人群:从事电机控制系统设计的研究人员和技术工程师,尤其是关注IPMSM电流解耦问题的专业人士。 使用场景及目标:适用于需要提高IPMSM电流控制精度和响应速度的应用场合,如伺服系统和电动汽车驱动。主要目标是解决d、q轴电流之间的动态耦合问题,提升系统的稳定性和可靠性。 其他说明:文中提供了详细的数学推导过程和代码示例,有助于读者理解和实现复矢量电流调节器。同时强调了有效磁链的概念和复矢量运算的优势,指出了实际应用中需要注意的问题,如电感参数的准确性。
# 基于嵌入式系统和Qt的俄罗斯方块游戏 ## 项目简介 本项目是一个基于嵌入式系统Gumstix的俄罗斯方块游戏,由两名开发者合作完成。项目使用C++和Qt库开发游戏逻辑,并通过Linux内核的用户级控制程序和Android应用通过蓝牙进行游戏控制。 ## 项目的主要特性和功能 游戏逻辑使用C++和Qt库实现经典的俄罗斯方块游戏。 用户控制通过Linux内核的用户级控制程序实现游戏控制。 蓝牙控制开发Android应用,通过蓝牙连接Gumstix进行游戏操作。 ## 安装使用步骤 1. 安装Android应用在Android手机上安装UserLevel.apk。 2. 硬件连接将蓝牙模块和其他必要的硬件连接到Gumstix开发板上,并启动Gumstix。 3. 编译代码使用Makefile编译Tetris和ul两个项目,并将生成的可执行文件复制到Gumstix中。
内容概要:本文档为《毕业设计写作全攻略:从选题到答辩的完整指南》,涵盖毕业设计从选题、开题报告撰写、论文写作核心框架与技巧、典型问题解决方案、答辩准备技巧以及资源工具包六个方面。选题部分强调了可行性、创新性和实用性,提供了具体的选题反例和正例。论文写作部分给出了详细的章节结构建议,包括研究背景、关键技术分析、系统设计与实现、实验与结果分析及总结与展望,并提供了写作技巧和避坑指南。对于答辩准备,提出了PPT制作原则、答辩话术模板和模拟方法。 适合人群:即将进行毕业设计的大学生,尤其是计算机相关专业的学生。 使用场景及目标:①帮助学生理解并掌握从选题到答辩的全过程;②提供实用的写作技巧和避坑指南,确保毕业设计顺利完成;③为答辩环节做好充分准备,提高答辩成功率。 其他说明:文档不仅提供了理论指导,还附有写作思路、避坑技巧与万能模板,旨在帮助学生更好地完成毕业设计,顺利过渡到职业生涯。此外,文档还推荐了一些辅助工具,如Overleaf、Grammarly等,以提升写作质量和效率。
华为OD机考辅导材料50题
蓝桥杯
notepad++ 插件 android logger 支持lexer fot App & Radio Log, 和自定义 支持从设备捕获日志! 支持在设备上启动命令行控制台或运行选定的Shell命令。 支持捕获设备截图,目前仅保存为 d:\device.bmp 支持文件浏览器功能! 提供Unix时间戳转换工具,轻松实现时间转换!
# 基于STM32L011F4微控制器的智能手表固件项目(简称“SMART WATCH FIRMWARE”) ## 项目简介 SMART WATCH FIRMWARE是一个基于STM32L011F4微控制器的智能手表固件项目。该项目旨在开发一个具有实时时钟、日期显示、电量监控、用户交互等功能的手表固件。通过使用特定的硬件和软件组件,该项目提供了一个完整的手表固件解决方案,旨在实现低功耗、高性能的用户体验。 ## 项目的主要特性和功能 1. 硬件初始化包括微控制器、显示设备、输入设备等硬件的初始化和配置。 2. 状态机管理控制用户界面状态,包括时间显示、日期显示、电量监控等。 3. 显示驱动控制显示设备的显示内容,如时间、日期和电量等。 4. 输入处理处理用户的输入操作,如按键或触摸等。 5. 时间管理提供实时时钟功能,包括时间的设置和显示。 6. 代码质量检查使用clangtidy和Cppcheck等工具进行代码静态分析,确保代码质量。
内容概要:本文详细探讨了齿轮系统在不同阻尼比条件下表现出的非线性动力学特性。通过构建微分方程并在MATLAB中实现,研究了齿侧间隙、时变刚度和综合啮合误差等因素对系统振动响应的影响。文中展示了如何利用ode45求解器解决非线性微分方程,并通过相图、频谱瀑布图等多种可视化手段分析了不同阻尼比下的系统行为。实验结果显示,适当的阻尼比能够有效抑制非线性振动,提高系统的稳定性。 适合人群:机械工程专业学生、从事齿轮设计与制造的技术人员以及对非线性动力学感兴趣的科研工作者。 使用场景及目标:适用于需要深入理解齿轮系统非线性振动机制的研究项目,旨在帮助工程师优化齿轮设计参数,提升机械设备的可靠性和使用寿命。 其他说明:文中提供了详细的MATLAB代码示例,便于读者复现实验结果。同时强调了数值仿真中的注意事项,如步长选择和参数设置,确保仿真结果的准确性。
1、该资源内项目代码经过严格调试,下载即用确保可以运行! 2、该资源适合计算机相关专业(如计科、人工智能、大数据、数学、电子信息等)正在做课程设计、期末大作业和毕设项目的学生、或者相关技术学习者作为学习资料参考使用。 3、该资源包括全部源码,需要具备一定基础才能看懂并调试代码。 菜谱APP微信小程序实现源码.zip菜谱APP微信小程序实现源码.zip 菜谱APP微信小程序实现源码.zip菜谱APP微信小程序实现源码.zip 菜谱APP微信小程序实现源码.zip菜谱APP微信小程序实现源码.zip 菜谱APP微信小程序实现源码.zip菜谱APP微信小程序实现源码.zip 菜谱APP微信小程序实现源码.zip菜谱APP微信小程序实现源码.zip 菜谱APP微信小程序实现源码.zip菜谱APP微信小程序实现源码.zip 菜谱APP微信小程序实现源码.zip菜谱APP微信小程序实现源码.zip
# 基于Arduino和Python的温室蘑菇生长环境监控与控制系统 ## 项目简介 本项目致力于自动化温室环境控制,为蘑菇生长营造最优条件。借助Arduino收集温度、湿度、CO2浓度等环境数据,由Python脚本处理并存储至数据库,方便后续展示与分析。 ## 项目的主要特性和功能 1. 传感器数据采集运用BME280测湿度,DS18B20测堆肥和空气温度,MN Z19B测CO2浓度。 2. 继电器控制三个继电器分别调控空气温度、湿度和CO2浓度。 3. 数据处理与存储Arduino收集的数据经串口传至Python脚本处理,存入数据库。 4. 数据展示与分析通过Grafana可视化工具,展示时间序列数据、温度曲线等,可设警报级别。 5. 用户交互支持通过命令行交互向设备发送控制命令。 ## 安装使用步骤 1. 硬件连接连接Arduino、传感器、继电器和电源等硬件。
内容概要:本文详细介绍了利用MATLAB实现电动汽车负荷随机性下的蓄电池容量优化配置及其多时间尺度储能优化策略。首先,通过构建优化模型,考虑了电动汽车负荷的随机性和并网功率的波动性,旨在找到最佳的蓄电池容量和充放电功率配置。其次,采用了多目标灰狼算法进行求解,该算法通过初始化灰狼种群、迭代更新灰狼位置等步骤,最终得到优化结果。此外,还引入了多种数学工具如泊松分布、Beta分布等来模拟电动汽车的充电行为,并通过多时间尺度(月度、季度、年度)的约束处理,使得优化结果更加全面和实用。最后,展示了优化结果的可视化,特别是Pareto前沿图,帮助决策者在经济性和稳定性之间找到最佳平衡点。 适用人群:适用于从事电力系统研究、电动汽车充电设施规划、储能系统设计的研究人员和技术人员。 使用场景及目标:①用于研究电动汽车负荷随机性对电网的影响;②为电网规划者提供科学合理的蓄电池容量配置方案;③帮助决策者在经济性和稳定性之间做出最优选择。 其他说明:文中提供了详细的代码实现和解释,有助于读者理解和复现实验结果。同时,强调了模型的实际应用场景和工程价值,特别是在处理波动性和经济性之间的平衡方面。
内容概要:本文详细介绍了四种基于BP神经网络的回归预测模型(EWOA-BP、GA-BP、SSA-BP和传统BP)的实现与比较。首先,针对BP神经网络易陷入局部最优解的问题,引入了三种启发式优化算法:改进鲸鱼算法(EWOA)、遗传算法(GA)和麻雀搜索算法(SSA),分别用于优化BP神经网络的参数。文中展示了各个模型的数据预处理方法、具体实现步骤以及优化算法的关键代码片段。通过对多个评价指标(如R值、RMSE、MAE等)进行对比,验证了改进模型的有效性和优越性。此外,还提供了详细的实操建议和常见问题解决方案,帮助初学者快速上手。 适合人群:具有一定MATLAB编程基础,对机器学习尤其是神经网络感兴趣的科研人员、学生和技术爱好者。 使用场景及目标:适用于需要进行回归预测任务的研究项目,如房价预测、医疗数据分析等。通过对比不同优化算法的效果,选择最适合特定应用场景的模型,提高预测精度和稳定性。 其他说明:附带完整的代码包和数据接口,方便用户直接替换自己的数据集进行实验。建议使用MATLAB 2018b及以上版本,并确保安装了必要的工具箱。
内容概要:本文深入探讨了四桥臂三维空间矢量脉宽调制(3D-SVPWM)算法在电压型逆变器中的应用。首先介绍了四桥臂逆变器相较于传统三相逆变器的独特优势,即能够实现单桥臂电压的独立控制。接着详细解释了3D-SVPWM算法的工作原理,包括三维空间矢量的概念及其在逆变器输出电压控制中的应用。文中还提供了Python和Matlab的代码示例,展示了如何生成参考电压矢量并绘制负载电压波形。此外,重点讨论了负载电压的观察与分析,特别是在处理不对称负载时的表现。最后,强调了坐标变换、矢量选择以及占空比计算等关键技术细节,并通过实验数据验证了该算法的有效性和优越性能。 适合人群:从事电力电子、电机驱动、不间断电源等领域研究的技术人员和高校相关专业师生。 使用场景及目标:适用于需要深入了解四桥臂逆变器控制算法的研究人员和技术开发者,旨在帮助他们掌握3D-SVPWM算法的具体实现方法及其在实际应用中的表现。 其他说明:文章不仅提供了理论分析,还包括了大量的代码示例和实验结果,有助于读者更好地理解和应用该算法。
内容概要:本文详细介绍了光伏并网系统的仿真建模及其核心技术模块,包括Boost升压电路、三相逆变器、PLL锁相环以及MPPT控制策略。首先探讨了Boost电路的设计要点,如电感电流连续模式和参数设置;接着讲解了三相逆变器的SPWM生成和同步控制;然后深入分析了PLL锁相环的实现,尤其是Park变换和PI调节器的参数整定;最后讨论了MPPT的扰动观察法及其优化策略。此外,还涉及了dq解耦控制和电流内环电压外环控制的具体实现方法,并提供了多个MATLAB/Simulink代码片段用于辅助理解和实操。 适合人群:从事光伏并网系统研究和开发的技术人员,尤其是具有一定电力电子和控制系统基础知识的研发人员。 使用场景及目标:适用于希望深入了解光伏并网系统内部机制的研究人员和技术开发者,旨在帮助他们掌握各个模块的工作原理和仿真技巧,从而提高系统的性能和稳定性。 其他说明:文中不仅提供了详细的理论解释,还附带了大量的代码实例,便于读者进行实际操作和调试。同时,针对常见问题给出了具体的解决方案和调试建议,有助于解决实际工程中的难题。
初识网络 · udp的基本使用