-
Notifications
You must be signed in to change notification settings - Fork 1
/
OsFromScratch.txt
60 lines (48 loc) · 4.26 KB
/
OsFromScratch.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
Q1. 关于 chapter 3 下的示例在 real mode 中初始化 protect mode 下的 sgement descriptor 的 memo
; 初始化数据段描述符
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
上面这段的作用是:确定 LABEL_DATA 的线形地址,然后初始化其对应的 segment descriptor 中的 base address field。
示例的代码是数据和代码混合在一个 raw binary 文件中。无论是作为 bootsector,还是 dos 下的 .com 文件[1],当该可执行程序被加载进 ram 执行时,可以知道,加载后其cs寄存器是一个确定的值(bootsector 是 0,dos下如何确认这个值还不清楚)。
第三章下的示例代码一般开始几句将其余的段寄存器都初始化和cs一样的值,有一种适用 flat memory mode 的意思。
label 是什么? 程序 load 进 ram 后,其所在的 linear address 已经确定,cs已经确定,也即 segment 已确定,程序中的各种 position 都是相对于本 segment 而言,所以 label 是在这个 segment 中的地址,或者说 offset,如果代码开始用 org 伪指令指定一个 offset,那 label 的值还要加上 org 的值。
real mode 下的内存管理很简单,每个 segment 的 size 都是 64k。无论是作为 boot sector,还是 dos 下的 .com 可执行文件(dos 是 single-user, single-tasking 的操作系统,所以每一个 .com 都是从相同的地址 0100h 开始执行),被 load 到 ram 后,其 cs 是确定的,所以这个程序中看到的地址都是这个确定的 segment 中的 offset. 所以,汇编程序中的 Label 是距离 segment 起始位置的 offset,一般 segment 的起始地址都是0,但也可以通过 org 伪指令把第一条程序指令放在想要的地方,label 的值也就相应的加上这个 offset.
[1]http://blog.csdn.net/lophyxp/article/details/8426486
Q2. chapter3/b/pmtest2.asm
LABEL_SEG_CODE32 下有一段代码输出一个字符串:
.1:
lodsb ; The source operand is a memory location, the address of which is read from the DS:ESI or the DS:SI register, is read into al
test al, al ; pino: 按位与,根据结果设置 SF, ZF, and PF status flags.
jz .2 ; pino: jump if ZF is 0.
mov [gs:edi], ax
add edi, 2
jmp .1
.2: ; 显示完毕
Q3. chapter 3, h/pmtest8.asm 中关于页表切换的代码注释:
; 在此假设内存是大于 8M 的
mov eax, LinearAddrDemo
shr eax, 22 ; shift right, 22 = 10 + 12, which is offset in page, page table index. Got Page dir index after shift.
mov ebx, 4096 ; 4096 means the size(byte) of a page table. BTW, the size of paging struture all is 4k.
mul ebx
mov ecx, eax ; ecx = eax = 4 * 4096
mov eax, LinearAddrDemo
shr eax, 12 ; right shift 12 bits( and with following line) to get page table index
and eax, 03FFh ; 1111111111b (10 bits)
mov ebx, 4 ; 4 means the size of page table entry.
mul ebx ; eax = ebx = 4 * page table index
add eax, ecx ; Means to get the page table entry corresponding to LinearAddrDemo. the result is offset in bytes from PageTblBase1.
add eax, PageTblBase1
mov dword [es:eax], ProcBar | PG_P | PG_USU | PG_RWW ; fill the page table entry of LinearAddrDemo with phy address of ProcBar
chapter 6-d
kernel.asm: hwint00中,离开内核栈后做的如下操作
mov esp, [p_proc_ready] ; 离开内核栈
lldt [esp + P_LDT_SEL]
lea eax, [esp + P_STACKTOP]
mov dword [tss + TSS3_S_SP0], eax
这是为了回到被中断进程做的准备,应该包括哪儿些呢,如上面4条指令所示,进程的ltdr应该准备好;然后进程的tss的esp0,其意思是,当该进程被中断,跳转到中断程序后,esp应该指向进程结构体proc的恰当位置,以便于保存该进程的上下文(寄存器内容),看hwint00中断处理函数的开头部分就知道。保存好了后就可以切换到内核栈了,就可以做一些更复杂的操作