【日拱一卒行而不辍20220919】自制操作系统

打开A20地址线-初次运行

参照《ORANGE’S:一个操作系统的实现》

以下是pm.inc

 1 DA_32           EQU     4000h   ; 32 位段
 2
 3 DA_DPL0         EQU       00h   ; DPL = 0
 4 DA_DPL1         EQU       20h   ; DPL = 1
 5 DA_DPL2         EQU       40h   ; DPL = 2
 6 DA_DPL3         EQU       60h   ; DPL = 3
 7
 8 ; 存储段描述符类型
 9 DA_DR           EQU     90h     ; 存在的只读数据段类型值
10 DA_DRW          EQU     92h     ; 存在的可读写数据段属性值
11 DA_DRWA         EQU     93h     ; 存在的已访问可读写数据段类型值
12 DA_C            EQU     98h     ; 存在的只执行代码段属性值
13 DA_CR           EQU     9Ah     ; 存在的可执行可读代码段属性值
14 DA_CCO          EQU     9Ch     ; 存在的只执行一致代码段属性值
15 DA_CCOR         EQU     9Eh     ; 存在的可执行可读一致代码段属性值
16
17 ; 系统段描述符类型
18 DA_LDT          EQU       82h   ; 局部描述符表段类型值
19 DA_TaskGate     EQU       85h   ; 任务门类型值
20 DA_386TSS       EQU       89h   ; 可用 386 任务状态段类型值
21 DA_386CGate     EQU       8Ch   ; 386 调用门类型值
22 DA_386IGate     EQU       8Eh   ; 386 中断门类型值
23 DA_386TGate     EQU       8Fh   ; 386 陷阱门类型值
24
25 SA_RPL0         EQU     0       ; ┓
26 SA_RPL1         EQU     1       ; ┣ RPL
27 SA_RPL2         EQU     2       ; ┃
28 SA_RPL3         EQU     3       ; ┛
29
30 SA_TIG          EQU     0       ; ┓TI
31 SA_TIL          EQU     4       ; ┛
32
33 %macro Descriptor 3
34         dw      %2 & 0FFFFh                             ; 段界限1
35         dw      %1 & 0FFFFh                             ; 段基址1
36         db      (%1 >> 16) & 0FFh                       ; 段基址2
37         dw      ((%2 >> 8) & 0F00h) | (%3 & 0F0FFh)     ; 属性1 + 段界限2 + 属性2
38         db      (%1 >> 24) & 0FFh                       ; 段基址3
39 %endmacro ; 共 8 字节
40 ;
41 ; 门
42 ; usage: Gate Selector, Offset, DCount, Attr
43 ;        Selector:  dw
44 ;        Offset:    dd
45 ;        DCount:    db
46 ;        Attr:      db
47 %macro Gate 4
48         dw      (%2 & 0FFFFh)                           ; 偏移1
49         dw      %1                                      ; 选择子
50         dw      (%3 & 1Fh) | ((%4 << 8) & 0FF00h)       ; 属性
51         dw      ((%2 >> 16) & 0FFFFh)                   ; 偏移2
52 %endmacro ; 共 8 字节

以下是pmtest1.S

 1 ; ==========================================
 2 ; pmtest1.asm
 3 ; 编译方法:nasm pmtest1.asm -o pmtest1.bin
 4 ; ==========================================
 5
 6 %include        "pm.inc"        ; 常量, 宏, 以及一些说明
 7
 8 org     07c00h
 9         jmp     LABEL_BEGIN
10
11 [SECTION .gdt]
12 ; GDT
13 ;                              段基址,       段界限     , 属性
14 LABEL_GDT:         Descriptor       0,                0, 0           ; 空描述符
15 LABEL_DESC_CODE32: Descriptor       0, SegCode32Len - 1, DA_C + DA_32; 非一致代码段
16 LABEL_DESC_VIDEO:  Descriptor 0B8000h,           0ffffh, DA_DRW      ; 显存首地址
17 ; GDT 结束
18
19 GdtLen          equ     $ - LABEL_GDT   ; GDT长度
20 GdtPtr          dw      GdtLen - 1      ; GDT界限
21                 dd      0               ; GDT基地址
22
23 ; GDT 选择子
24 SelectorCode32          equ     LABEL_DESC_CODE32       - LABEL_GDT
25 SelectorVideo           equ     LABEL_DESC_VIDEO        - LABEL_GDT
26 ; END of [SECTION .gdt]
27
28 [SECTION .s16]
29 [BITS   16]
30 LABEL_BEGIN:
31         mov     ax, cs
32         mov     ds, ax
33         mov     es, ax
34         mov     ss, ax
35         mov     sp, 0100h
36
37         ; 初始化 32 位代码段描述符
38         xor     eax, eax
39         mov     ax, cs
40         shl     eax, 4
41         add     eax, LABEL_SEG_CODE32
42         mov     word [LABEL_DESC_CODE32 + 2], ax
43         shr     eax, 16
44         mov     byte [LABEL_DESC_CODE32 + 4], al
45         mov     byte [LABEL_DESC_CODE32 + 7], ah
46
47         ; 为加载 GDTR 作准备
48         xor     eax, eax
49         mov     ax, ds
50         shl     eax, 4
51         add     eax, LABEL_GDT          ; eax <- gdt 基地址
52         mov     dword [GdtPtr + 2], eax ; [GdtPtr + 2] <- gdt 基地址
53
54         ; 加载 GDTR
55         lgdt    [GdtPtr]
56
57         ; 关中断
58         cli
59
60         ; 打开地址线A20
61         in      al, 92h
62         or      al, 00000010b
63         out     92h, al
64
65         ; 准备切换到保护模式
66         mov     eax, cr0
67         or      eax, 1
68         mov     cr0, eax
69
70         ; 真正进入保护模式
71         jmp     dword SelectorCode32:0  ; 执行这一句会把 SelectorCode32 装入 cs,
72                                         ; 并跳转到 Code32Selector:0  处
73 ; END of [SECTION .s16]
74
75
76 [SECTION .s32]; 32 位代码段. 由实模式跳入.
77 [BITS   32]
78
79 LABEL_SEG_CODE32:
80         mov     ax, SelectorVideo
81         mov     gs, ax                  ; 视频段选择子(目的)
82
83         mov     edi, (80 * 11 + 79) * 2 ; 屏幕第 11 行, 第 79 列。
84         mov     ah, 0Ch                 ; 0000: 黑底    1100: 红字
85         mov     al, 'P'
86         mov     [gs:edi], ax
87
88         ; 到此停止
89         jmp     $
90
91 SegCode32Len    equ     $ - LABEL_SEG_CODE32
92 ; END of [SECTION .s32]
93

执行之后效果如下No bootable device.

【日拱一卒行而不辍20220919】自制操作系统_第1张图片

 初步分析认为是初次接触此类代码,没有理解关键变量的含义,囫囵运行之后无法达到预期目的。

详细分析

第一感觉是以下的标签代码怎么不见了?

dw 	0xaa55				; boot record signature

查看对应的os.raw二进制文件,也不足512字节

【日拱一卒行而不辍20220919】自制操作系统_第2张图片

正常的第一扇区应该是标准的512字节,如第一章的最简单OS的二进制内容如下

【日拱一卒行而不辍20220919】自制操作系统_第3张图片

再次测试

经过对第一扇区的补齐之后,奇迹般地,显示出了书中预想的红色的P 

【日拱一卒行而不辍20220919】自制操作系统_第4张图片 

 补齐后的pmtest2.S文件如下

; ==========================================
; 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	$
	times	22 db 0
	times 	64 db 0
	times 	64 db 0
	times	64 db 0
	times 	64 db 0
	times 	83 db 0
	dw 	0xaa55

SegCode32Len	equ	$ - LABEL_SEG_CODE32
; END of [SECTION .s32]

 补齐后的二进制文件如下

【日拱一卒行而不辍20220919】自制操作系统_第5张图片

 

 

你可能感兴趣的:(Linux,OS,开发语言,linux)