初始化寄存器
我将物理地址0x050000-0x070008
之间的内存分配给了堆栈。栈顶设置为0x070008
的原因是,kernel函数在编译后会在函数开头加上这样一行汇编代码sub $0x8,%rsp
,将栈顶设置为0x070008
可以保证在经过此操作后,栈顶为0x070000
。
段寄存器
CS
: 指向存放程序的内存段,IP
用来存放下条待执行的指令在该段的偏移量。CS:IP
所指向的指令就是下次要执行的指令。SS
: 指向用于堆栈的内存段,SP
用来指向该堆栈的栈顶。DS
: 指向数据段ES
: 指向附加段 (辅助段寄存器)FS
: 指向标志段 (辅助段寄存器)GS
: 指向全局段 (辅助段寄存器)
缺省段寄存器
- 当偏移量用到了指针寄存器
BP
,则其缺省的段寄存器也是SS
,并且用BP可访问整个堆栈,不仅仅是只访问栈顶。 - 通常,缺省的数据段寄存器是
DS
- 在进行串操作时,其目的地址的段寄存器规定为
ES
代码
Use this command to check your USB Stick FAT32 Fields
1sudo hexdump -C -n 512 /dev/sdb
Write the bootloader to first 512 bytes of the usb stick
1sudo dd if=boot.bin of=/dev/sdb conv=notrunc
boot.asm
1[BITS 16]
2
3[ORG 0x7c00]
4
5;----------------------------------------------- [Jump Instruction; offset: 0x00; length: 3 Bytes]
6
7 jmp short Label_Start ; 2 Bytes
8 nop ; 1 Bytes
9
10;----------------------------------------------- [FAT32; offset: 0x03; length: 87 Bytes]
11
12%include "fat32.asm"
13
14;----------------------------------------------- [Bootstrap Code; offset: 0x5A; length: 420 Bytes]
15
16Label_Start:
17 call Print_StartBoot
18
19 mov sp, BaseOfStack
20
21 push cs
22 pop ds
23
24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
25;; Search and Read "loader.bin" ;;
26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
27
28 and byte [BS_RootDirectoryStart+3], 0x0F ; mask cluster value
29 mov esi, [BS_RootDirectoryStart] ; esi=cluster # of root dir
30
31RootDirReadContinue:
32 push BaseOfLoader
33 pop es
34 xor bx, bx
35 call ReadCluster ; read one cluster of root dir
36 push esi ; save esi=next cluster # of root dir
37 pushf ; save carry="not last cluster" flag
38
39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
40;; Look for the loader file to load and run ;;
41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
42
43 push BaseOfLoader
44 pop es
45 xor di, di ; es:di -> root entries array
46 mov si, Filename_Loader ; ds:si -> program name
47
48 mov al, [BPB_SectorsPerCluster]
49 cbw
50 mul word [BPB_BytesPerSector] ; ax = bytes per cluster
51 shr ax, 5
52 mov dx, ax ; dx = # of dir entries to search in
53
54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
55;; Looks for a file/dir by its name ;;
56;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
57;; Input: DS:SI -> file name (11 chars) ;;
58;; ES:DI -> root directory array ;;
59;; DX = number of root entries ;;
60;; Output: ESI = cluster number ;;
61;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
62
63 mov cx, 11 ; the length of loader filename
64
65FindNameCycle:
66 cmp byte [es:di], 0xC
67 jne FindNameNotEnd
68 jmp Print_Error_NoLoader ; end of root directory (NULL entry found)
69FindNameNotEnd:
70 pusha
71 repe cmpsb
72 popa
73 je FindNameFound
74 add di, 32
75 dec dx
76 jnz FindNameCycle ; next root entry
77 popf ; restore carry="not last cluster" flag
78 pop esi ; restore esi=next cluster # of root dir
79 jc RootDirReadContinue ; continue to the next root dir cluster
80 jmp Print_Error_NoLoader ; end of root directory (dir end reached)
81FindNameFound:
82 push word [es:di+0x14]
83 push word [es:di+0x1A]
84 pop esi ; si = cluster no.
85
86;;;;;;;;;;;;;;;;;;;;;;;;;;
87;; Load the entire file ;;
88;;;;;;;;;;;;;;;;;;;;;;;;;;
89
90 push BaseOfLoader
91 pop es
92 xor bx, bx
93FileReadContinue:
94 call ReadCluster ; read one cluster of root dir
95
96 pushf
97 pusha
98 inc byte [CLU]
99 mov ax, 0xB800
100 mov gs, ax
101 mov ah, 0x0F ; 0000: 黑底 1111: 白字
102 mov al, [CLU]
103 mov [gs:((80 * 0 + 39) * 2)], ax ; 屏幕第 0 行, 第 39 列。
104 popa
105 popf
106
107 jc FileReadContinue
108
109EnterLoader:
110 mov bl, byte [LINE] ; save line number
111 jmp BaseOfLoader:OffsetOfLoader
112
113;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
114;; Reads a FAT32 cluster ;;
115;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
116;; Inout: ES:BX -> buffer ;;
117;; ESI = cluster no ;;
118;; Output: ESI = next cluster ;;
119;; ES:BX -> next addr ;;
120;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
121
122ReadCluster:
123 mov ax, [BPB_BytesPerSector]
124 shr ax, 2 ; ax=# of FAT32 entries per sector
125 cwde
126 mov ebp, esi ; ebp=esi=cluster #
127 xchg eax, esi
128 cdq
129 div esi ; eax=FAT sector #, edx=entry # in sector
130 movzx edi, word [BPB_ReservedSectors]
131 add edi, [BPB_HiddenSectors]
132 add eax, edi
133
134 push dx ; save dx=entry # in sector on stack
135 mov cx, 1
136 call ReadSectorLBA ; read 1 FAT32 sector
137
138 pop si ; si=entry # in sector
139 add si, si
140 add si, si
141 and byte [es:si+3], 0x0F ; mask cluster value
142 mov esi, [es:si] ; esi=next cluster #
143
144 lea eax, [ebp-2]
145 movzx ecx, byte [BPB_SectorsPerCluster]
146 mul ecx
147 mov ebp, eax
148
149 movzx eax, byte [BPB_TotalFATs]
150 mul dword [BS_BigSectorsPerFAT]
151
152 add eax, ebp
153 add eax, edi
154
155 call ReadSectorLBA
156
157 mov ax, [BPB_BytesPerSector]
158 shr ax, 4 ; ax = paragraphs per sector
159 mul cx ; ax = paragraphs read
160
161 mov cx, es
162 add cx, ax
163 mov es, cx ; es:bx updated
164
165 cmp esi, 0x0FFFFFF8 ; carry=0 if last cluster, and carry=1 otherwise
166 ret
167
168;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
169;; Reads a sector using BIOS Int 13h fn 42h ;;
170;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
171;; Input: EAX = LBA ;;
172;; CX = sector count ;;
173;; ES:BX -> buffer address ;;
174;; Output: CF = 1 if error ;;
175;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
176
177ReadSectorLBA:
178 pushad
179
180ReadSectorLBANext:
181 pusha
182
183 push byte 0
184 push byte 0 ; 32-bit LBA only: up to 2TB disks
185 push eax
186 push es
187 push bx
188 push byte 1 ; sector count word = 1
189 push byte 16 ; packet size byte = 16, reserved byte = 0
190
191 mov ah, 42h
192 mov dl, [BS_DriveNumber]
193 mov si, sp
194 push ss
195 pop ds
196 int 13h
197 push cs
198 pop ds
199
200 jc short Print_Error_Read
201 add sp, 16 ; the two instructions are swapped so as not to overwrite carry flag
202
203 popa
204 dec cx
205 jz ReadSectorLBADone2 ; last sector
206
207 add bx, [BPB_BytesPerSector] ; adjust offset for next sector
208 add eax, byte 1 ; adjust LBA for next sector
209 jmp short ReadSectorLBANext
210
211ReadSectorLBADone2:
212 popad
213 ret
214
215Print_StartBoot:
216 pusha
217 mov cx, 10
218 mov bp, Message_StartBoot
219 mov bx, 0x000f
220 call Message_Print_End
221 popa
222 ret
223
224Print_Error_Read:
225 mov cx, 11
226 mov bp, Message_ReadError
227 mov bx, 0x000f
228 call Message_Print_End
229 jmp $
230
231Print_Error_NoLoader:
232 mov cx, 15
233 mov bp, Message_NoLoader
234 mov bx, 0x000c
235 call Message_Print_End
236 jmp $
237
238Message_Print_End:
239 push es
240 push ds
241 mov ax, 0
242 mov ds, ax
243 mov es, ax
244 mov ax, 0x1301
245 mov dl, 0
246 mov dh, [LINE]
247 inc byte [LINE]
248 int 10h
249 pop ds
250 pop es
251 ret
252
253
254BaseOfLoader: EQU 0x1000
255OffsetOfLoader: EQU 0x0000
256BaseOfStack: EQU 0x7C00
257
258
259Message_StartBoot: DB "Start Boot" ; 10
260Message_ReadError: DB "ERROR: Read" ; 11
261Message_NoLoader: DB "No Loader Found" ; 15
262Filename_Loader: DB "LOADER BIN" ; 11
263
264LINE: DB 0x00
265CLU: DB 0x41
266
267 TIMES 510 - ($ - $$) DB 0
268
269;----------------------------------------------- [End of Sector Marker; offset: 0x1FE; length: 2 Bytes]
270
271 DW 0xAA55
除另有声明外,本博客文章均采用 知识共享 (Creative Commons) 署名 4.0 国际许可协议 进行许可。转载请注明原作者与文章出处。