`
wx1568847608
  • 浏览: 13760 次
文章分类
社区版块
存档分类
最新评论

Orange's 一个操作系统的实现(3)--- 从保护模式跳回到实模式

 
阅读更多

本篇主讲对应于 《Orange'S:一个操作系统的实现》第三章 b 代码 pmtest2.asm

; ==========================================
; pmtest2.asm
; 编译方法:nasm pmtest2.asm -o pmtest2.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_DATA:   Descriptor    0,      DataLen-1, DA_DRW    ; Data
LABEL_DESC_STACK:  Descriptor    0,     TopOfStack, DA_DRWA+DA_32; Stack, 32 位
LABEL_DESC_TEST:   Descriptor 0500000h,     0ffffh, DA_DRW
LABEL_DESC_VIDEO:  Descriptor  0B8000h,     0ffffh, DA_DRW    ; 显存首地址
; 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
SelectorData		equ	LABEL_DESC_DATA		- LABEL_GDT
SelectorStack		equ	LABEL_DESC_STACK	- LABEL_GDT
SelectorTest		equ	LABEL_DESC_TEST		- LABEL_GDT
SelectorVideo		equ	LABEL_DESC_VIDEO	- LABEL_GDT
; 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]


[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, 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

	; 为加载 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, SelectorTest
	mov	es, 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

	call	TestRead
	call	TestWrite
	call	TestRead

	; 到此停止
	jmp	SelectorCode16:0

; ------------------------------------------------------------------------
TestRead:
	xor	esi, esi
	mov	ecx, 8
.loop:
	mov	al, [es:esi]
	call	DispAL
	inc	esi
	loop	.loop

	call	DispReturn

	ret
; TestRead 结束-----------------------------------------------------------


; ------------------------------------------------------------------------
TestWrite:
	push	esi
	push	edi
	xor	esi, esi
	xor	edi, edi
	mov	esi, OffsetStrTest	; 源数据偏移
	cld
.1:
	lodsb
	test	al, al
	jz	.2
	mov	[es:edi], al
	inc	edi
	jmp	.1
.2:

	pop	edi
	pop	esi

	ret
; TestWrite 结束----------------------------------------------------------


; ------------------------------------------------------------------------
; 显示 AL 中的数字
; 默认地:
;	数字已经存在 AL 中
;	edi 始终指向要显示的下一个字符的位置
; 被改变的寄存器:
;	ax, edi
; ------------------------------------------------------------------------
DispAL:
	push	ecx
	push	edx

	mov	ah, 0Ch			; 0000: 黑底    1100: 红字
	mov	dl, al
	shr	al, 4
	mov	ecx, 2
.begin:
	and	al, 01111b
	cmp	al, 9
	ja	.1
	add	al, '0'
	jmp	.2
.1:
	sub	al, 0Ah
	add	al, 'A'
.2:
	mov	[gs:edi], ax
	add	edi, 2

	mov	al, dl
	loop	.begin
	add	edi, 2

	pop	edx
	pop	ecx

	ret
; DispAL 结束-------------------------------------------------------------


; ------------------------------------------------------------------------
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]


; 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]

 

首先看这一段代码较上一代代码 pmtest1.asm 多了很多新命令

lodsb 、test、jz、ja、test、push、pop、ret、call  

这些命令太多,不能在这里详细解释,会占用过多篇幅,请看我的另一篇文章 汇编常用命令总结 

 

以下开始正文讲解

PMMessage:        db    "In Protect Mode now. ^-^", 0 

  PMMessage:        db    "In Protect Mode now. ^-^", 0    这里面的0是什么意思?

    最后会加0,这个0是字符串结束字符,以后处理的时候有用

 

如何运行查看效果

因为字节超过了512字节,所以不能再用前面的方法来完成运行。我们这里采用书中的第二套方法。我们把程序编译成COM文件,然后让DOS来运行它。

书中采用了Ubuntu系统,本人一般用centos,所以用centos来完成操作。

1、首先下载一个FreeDos系统 

2、用bximage 生成一个软盘映像,起名为 pm.img

3、修改我们的bochsrc,确保其中有以下三行:

floppya: 1_44=freedos.img, status=inserted
floppyb: 1_44=pm.img, status=inserted
boot: a 

4、启动bochs,待FreeDos 启动完成后,格式化B: 盘

 format b:

5、编译成COM文件   

nasm pmtest2.asm -o pmtest2.com

6、在centos完成以下操作

    1、首先将两个文件(pm.img, pmtest2.com)传入到centos系统中,需要安装增强功能,然后设置共享

    2、创建文件夹         

# mkdir /mnt/floppy

    3、将pmtest2.com 复制到虚拟软盘pm.img上         

# mount -o loop pm.img  /mnt/floppy
# cp pmtest2.com /mnt/floppy
# umount /mnt/floppy

7、启动bochs,然后切换到 b 盘,执行com文件

b:\pmtest2.com

            

如何调试代码

我们如何在bochs里面调试 com 代码?  

1、在配置文件 bochsrc.bxrc 最后加上  magic_break: enabled=1

2、在 pmtest2.asm 开头加上 xchg  bx, bx    

以上两句话是看的别人的,亲测不好用,还是直接用dbg吧

运行bochsdbg.exe 直接启动debug模式,   加载配置文件bochsrc.bxrc开始调试

 部分 Bochs 调试指令
 

行为                                                               指令                                                         举例                                                           
在某物理地址设置断点 b addr b 0x7c00
显示当前所有断点信息 info break info break
继续执行,直至遇到断点 c c
单步执行 s s
单步执行(遇到函数跳过) n n
查看寄存器信息 info cpu
r
fp
sreg
creg
info cpu
r
fp
sreg
cre
查看堆栈 print-stack print-stack
查看内存物理地址内容 xp /nuf addr xp /40bx 0x9013e
查看线性地址内容 x /nuf addr x /40bx 0x13e
反汇编一段内存 u start end u 0x30400 0x3040d
反汇编执行的每一条指令 trace-on trace-on
每执行一条指令就打印 CPU 信息 trace-reg trace-reg

 

转载于:https://my.oschina.net/yangshj/blog/3057462

分享到:
评论

相关推荐

    orange's一个操作系统的实现-【自己动手写操作系统第二版】

    《orange's一个操作系统的实现-【自己动手写操作系统第二版】》是一本深入浅出的操作系统构建指南,作者为于渊。这本书旨在帮助读者通过实际操作来理解操作系统的原理和构造,适合对操作系统感兴趣的DIY爱好者和...

    ORANGE'S:一个操作系统的实现--电子书和源码

    "ORANGE'S:一个操作系统的实现" 是一本由作者于渊编写的关于操作系统设计与实现的专业书籍。这本书籍深入浅出地介绍了操作系统的核心概念、设计原理以及实现技术,旨在帮助读者理解并掌握操作系统的工作机制。同时...

    ORANGE'S:一个操作系统的实现

    ### ORANGE'S:一个操作系统的实现 —— 关键知识点概览 #### 一、操作系统的重要性与价值 **操作系统**作为连接计算机硬件与用户之间的桥梁,是计算机系统中最基础且核心的部分之一。它不仅管理着硬件资源,还为...

    ORANGE’S:一个操作系统的实现(高清晰版1

    《Orange'S:一个操作系统的实现》是一本详细指导读者如何从零开始构建操作系统的书籍,由作者于渊创作。该书的第二版旨在提供一个操作系统雏形实现的完整过程,适合那些希望深入了解操作系统原理并动手实践的程序员...

    Orange S:一个操作系统的实现(PDF+光盘).part4.rar )

    Orange S:一个操作系统的实现(PDF+光盘).part3.rar Orange S:一个操作系统的实现(PDF+光盘).part4.rar 四卷下载完后一起解压,资源非本人制作,也是从网上找来,本着方便大家学习的原则分享。 文档很清晰,...

    笔记_Orange_S一个操作系统的实现.pdf

    笔记_Orange_S一个操作系统的实现

    ORANGE’S:一个操作系统的实现.pdf

    ORANGE’S:一个操作系统的实现.pdf

    Orange S:一个操作系统的实现(PDF+光盘).part1.rar )

    Orange S:一个操作系统的实现(PDF+光盘).part3.rar Orange S:一个操作系统的实现(PDF+光盘).part4.rar 四卷下载完后一起解压,资源非本人制作,也是从网上找来,本着方便大家学习的原则分享。 文档很清晰,...

    Orange+S:一个操作系统的实现 有光盘

    《Orange S:一个操作系统的实现》从只有二十行的引导扇区代码出发,一步一步地向读者呈现一个操作系统框架的完成过程。书中不仅关注代码本身,同时关注完成这些代码的思路和过程。本书不同于其他的理论型书籍,而是...

    orange's 一个操作系统的实现源代码

    但是于渊的这本《orange's:一个操作系统的实现》却是一条难得的终南捷径。因为要理解如何让一个芯片正常工作,最简单的办法就是从头开始去写程序让它运行起来,然后操作它做自己想做的事情。如果是平时的编程,这些...

    ORANGE’S:一个操作系统的实现(高清晰版PDF)

    《Orange’s:一个操作系统的实现》是一本详细探讨操作系统构建的书籍,主要针对那些对操作系统原理和实现感兴趣的读者。这本书的高清晰版PDF版本解决了扫描版存在的文字不清、图片模糊的问题,提供了更好的阅读体验...

    Orange's 一个操作系统的实现

    从只有二十行的引导扇区代码出发,一步一步地向读者呈现一个操作系统框架的完成过程。书中不仅关注代码本身,同时关注完成这些代码的思路和过程。本书不同于其他的理论型书籍,而是提供给读者一个动手实践的路线图。...

    Orange'S:一个操作系统的实现

    根据提供的文件信息:“Orange'S:一个操作系统的实现”,我们可以从中提炼出关于操作系统实现的相关知识点。虽然部分内容为空,但可以从标题和描述中推测出该文档主要讲述了名为“Orange'S”的操作系统的实现过程...

    Orange's一个操作系统的实现(于渊《自己动手写操作系统第二版》)随书光盘

    Orange's是一个基于x86架构的操作系统,由于渊在其著作《自己动手写操作系统第二版》中详尽阐述了其设计与实现过程。这个随书光盘包含了作者在书中提到的源代码、实验环境和相关资源,是学习操作系统原理与实践操作...

    Orange S:一个操作系统的实现(PDF+光盘).part3.rar )

    Orange S:一个操作系统的实现(PDF+光盘).part3.rar Orange S:一个操作系统的实现(PDF+光盘).part4.rar 四卷下载完后一起解压,资源非本人制作,也是从网上找来,本着方便大家学习的原则分享。 文档很清晰,...

    Orange S:一个操作系统的实现(PDF+光盘).part2.rar )

    Orange S:一个操作系统的实现(PDF+光盘).part3.rar Orange S:一个操作系统的实现(PDF+光盘).part4.rar 四卷下载完后一起解压,资源非本人制作,也是从网上找来,本着方便大家学习的原则分享。 文档很清晰,...

    orange's一个操作系统的实现

    完整 拍照 版的orange's一个操作系统的实现

    orange's一个操作系统的实现源码

    "orange's一个操作系统的实现源码" 是一个与操作系统开发相关的项目,其核心内容是提供了自己动手编写操作系统过程中的源代码。这样的项目通常对学习操作系统原理、深入理解计算机系统工作方式以及想要尝试操作系统...

    ORANGE’S:一个操作系统的实现源码

    ORANGE’S是一个开源的操作系统项目,其核心目标是提供一个学习和研究操作系统内核实现的平台。这个项目为那些对操作系统原理感兴趣的开发者和学生提供了深入理解操作系统底层工作方式的机会。通过阅读和分析ORANGE...

Global site tag (gtag.js) - Google Analytics