zoukankan      html  css  js  c++  java
  • Chapter3 保护模式a

    先贴代码:

    ; ==========================================
    ; pmtest1.asm
    ; 编译方法:nasm pmtest1.asm -o pmtest1.bin
    ; ==========================================
    
    %include	"pm.inc"	; 常量, 宏, 以及一些说明
    
    org	07c00h
    	jmp	LABEL_BEGIN
    
    [SECTION .gdt]
    ; GDT
    ;                              段基址,       段界限     , 属性
    LABEL_GDT:	   Descriptor       0,                0, 0           ; 空描述符
    LABEL_DESC_CODE32: Descriptor       0, SegCode32Len - 1, DA_C + DA_32; 非一致代码段
    LABEL_DESC_VIDEO:  Descriptor 0B8000h,           0ffffh, DA_DRW	     ; 显存首地址
    ; GDT 结束
    
    GdtLen		equ	$ - LABEL_GDT	; GDT长度
    GdtPtr		dw	GdtLen - 1	; GDT界限
    		dd	0		; GDT基地址
    
    ; GDT 选择子
    SelectorCode32		equ	LABEL_DESC_CODE32	- LABEL_GDT
    SelectorVideo		equ	LABEL_DESC_VIDEO	- LABEL_GDT
    ; END of [SECTION .gdt]
    
    [SECTION .s16]
    [BITS	16]
    LABEL_BEGIN:
    	mov	ax, cs
    	mov	ds, ax
    	mov	es, ax
    	mov	ss, ax
    	mov	sp, 0100h
    
    	; 初始化 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
    
    	; 为加载 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  处
    ; END of [SECTION .s16]
    
    
    [SECTION .s32]; 32 位代码段. 由实模式跳入.
    [BITS	32]
    
    LABEL_SEG_CODE32:
    	mov	ax, SelectorVideo
    	mov	gs, ax			; 视频段选择子(目的)
    
    	mov	edi, (80 * 11 + 79) * 2	; 屏幕第 11 行, 第 79 列。
    	mov	ah, 0Ch			; 0000: 黑底    1100: 红字
    	mov	al, 'P'
    	mov	[gs:edi], ax
    
    	; 到此停止
    	jmp	$
    
    SegCode32Len	equ	$ - LABEL_SEG_CODE32
    ; END of [SECTION .s32]
    
    ;新增代码
    times    382-($-$$)    db    0
    dw    0xaa55
    

    其中代码最底部的两行代码为新增代码,如果使用书中的代码进行编译(步骤如下):

    1. bximage一个a.img的软盘

    2. nasm -o pmtest1.bin pmtest1.asm

    3. dd if=pmtest1.bin of=a.img bs=512 count=1 conv=notrunc

    4. 启动Bochs

    5. 运行程序(c键回车)

    将会提示:[BIOS] error,No Boot Device

    这是什么原因呢?这主要是因为我们在第二步中产生的pmtest1.bin文件超出512B的原因,所以在拷贝的时候发生了截断,为了让其保持在512B以内,并且最后是以AA55结尾的,我们使用了新增部分,其中的382是这么来的:

    第2步产生的pmtest1.bin文件大小是640B,比512要大128B,本来在代码最后处应该是

    times    510-($-$$)    db    0
    

     但是为了保证文件的大小是512B,所以使用510-128=382来填充,这样写入到a.img中,再运行程序就不会出错了。

    当然如果nasm编译后的文件太大,超过1KB以上,那么我们就不能使用这种直接引导的方式来运行程序了,这时候我们有两种方法:

    1. 写一个引导扇区,让其可以读取我们的程序并运行它。

    2. 借助别的东西,比如DOS,我们可以将程序编译成COM文件,然后行DOS来执行它。

    所以在第三章以后(包含第三章)我都是通过DOS来执行我们的程序的。

  • 相关阅读:
    链接Caffe,程序报错应用程序无法正常启动(0xc000007b)
    C++ 11的移动语义
    C++ 11的右值引用
    (持续更新)Qt3D 学习资源
    Qt3D 设置窗口背景颜色和图案
    C++ chrono 库中的 steady_clock 和 system_clock
    VS2017+CMake+OpenCV下报错 set OpenCV_FOUND to FALSE
    C++可继承的单例基类模板
    AngularJS的基础知识
    gulp入门详情
  • 原文地址:https://www.cnblogs.com/fingertouch/p/3057227.html
Copyright © 2011-2022 走看看