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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
|
seg000:7C00 seg000 segment byte public 'CODE' use16
seg000:7C00 assume cs:seg000
seg000:7C00 ;org 7C00h
seg000:7C00 assume es:nothing, ss:nothing, ds:nothing, fs:nothing, gs:nothing
seg000:7C00
seg000:7C00 loc_7C00: ; CODE XREF: seg000:7D2A↓J
seg000:7C00 33 C0 xor ax, ax
seg000:7C02 8E D0 mov ss, ax ; 段地址为0
seg000:7C04 BC 00 7C mov sp, 7C00h
seg000:7C07 8E C0 mov es, ax
seg000:7C09 8E D8 mov ds, ax
seg000:7C0B BE 00 7C mov si, 7C00h
seg000:7C0E BF 00 06 mov di, 600h
seg000:7C11 B9 00 02 mov cx, 200h
seg000:7C14 FC cld
seg000:7C15 F3 A4 rep movsb ; 从ds:si 7C00h拷贝0x200个字节到 es:di 600h处;
seg000:7C15 ; 7C00h地址刚好是我们的MBR代码起始地址,大小为0x200,
seg000:7C15 ; 也就是说这段代码用于备份我们的MBR代码到600h处
seg000:7C17 50 push ax
seg000:7C18 68 1C 06 push 61Ch ; cs:ip = 00:61Ch;
seg000:7C18 ; retf 处理器先从栈中弹出一个字到IP,再弹出一个字到CS;
seg000:7C18 ; 跳转到61ch处执行;之前把MBR代码拷贝到了600h
seg000:7C1B CB retf
seg000:7C1C ; ---------------------------------------------------------------------------
seg000:7C1C FB sti ; 代码接着从这运行
seg000:7C1D B9 04 00 mov cx, 4 ; 分区表内一共四个分区项
seg000:7C20 BD BE 07 mov bp, 7BEh ; 7BE = 600+1BE BP为第一个分区项
seg000:7C23
seg000:7C23 loc_7C23: ; CODE XREF: seg000:7C30↓j
seg000:7C23 80 7E 00 00 cmp byte ptr [bp+0], 0 ; 比较分区表结构体中的活动标志位,用来查找活动分区
seg000:7C27 7C 0B jl short loc_7C34 ; 有符号数比较,小于0跳转
seg000:7C29 0F 85 0E 01 jnz loc_7D3B ; 跳转到错误处理,活动标志要么0x80要么0x00出去别的,说明出错
seg000:7C2D 83 C5 10 add bp, 10h ; bp+10h 到下一个分区表项进行查看是否为活动分区
seg000:7C30 E2 F1 loop loc_7C23 ; 比较分区表结构体中的活动标志位,用来查找活动分区
seg000:7C32 CD 18 int 18h ; TRANSFER TO ROM BASIC
seg000:7C32 ; causes transfer to ROM-based BASIC (IBM-PC)
seg000:7C32 ; often reboots a compatible; often has no effect at all
seg000:7C34
seg000:7C34 loc_7C34: ; CODE XREF: seg000:7C27↑j
seg000:7C34 ; seg000:7CAE↓j
seg000:7C34 88 56 00 mov [bp+0], dl ; 磁盘驱动器号,用于AX=41H 下的INT13,例如第一块硬盘则DL=80H,由BIOS主板设定完毕
seg000:7C37 55 push bp
seg000:7C38 C6 46 11 05 mov byte ptr [bp+11h], 5
seg000:7C3C C6 46 10 00 mov byte ptr [bp+10h], 0
seg000:7C40 B4 41 mov ah, 41h ; 'A'
seg000:7C42 BB AA 55 mov bx, 55AAh ; 构造用来测试是否支持INT13扩展 所需要的参数,当AH=41的时候,
seg000:7C42 ; int13则用于检测是否支持int13扩展,
seg000:7C42 ; CF Set On Not Present, Clear If Present
seg000:7C42 ; https://en.wikipedia.org/wiki/INT_13H#INT_13h_AH=41h:_Check_Extensions_Present
seg000:7C45 CD 13 int 13h ; DISK - Check for INT 13h Extensions
seg000:7C45 ; BX = 55AAh, DL = drive number
seg000:7C45 ; Return: CF set if not supported
seg000:7C45 ; AH = extensions version
seg000:7C45 ; BX = AA55h
seg000:7C45 ; CX = Interface support bit map
seg000:7C47 5D pop bp
seg000:7C48 72 0F jb short loc_7C59 ; CF=1 跳转,此时表示不支持INT13扩展
seg000:7C4A 81 FB 55 AA cmp bx, 0AA55h
seg000:7C4E 75 09 jnz short loc_7C59 ; bx是否为AA55h,不是则不支持
seg000:7C50 F7 C1 01 00 test cx, 1 ; cx=1 表示支持Device Access using the packet structure
seg000:7C54 74 03 jz short loc_7C59
seg000:7C56 FE 46 10 inc byte ptr [bp+10h] ; 到这表示支持,标志位加1
seg000:7C59
seg000:7C59 loc_7C59: ; CODE XREF: seg000:7C48↑j
seg000:7C59 ; seg000:7C4E↑j ...
seg000:7C59 66 60 pushad
seg000:7C5B 80 7E 10 00 cmp byte ptr [bp+10h], 0 ; 判断标志位,是否支持int13扩展
seg000:7C5F 74 26 jz short loc_7C87 ; 不支持跳转到标准INT13处
seg000:7C61 66 68 00 00 00 00 push large 0 ; 构造Packet Structure
seg000:7C61 ; struct DiskPacket
seg000:7C61 ; {
seg000:7C61 ; .packet_size db 0x10 ; use_transfer_64 ? 10h : 18h
seg000:7C61 ; .reserved db 0x00 ; always zero
seg000:7C61 ; .block_cout dw 0x00 ; number of sectors to read
seg000:7C61 ; .transfer_buffer dd 0x00 ; address to load in ram
seg000:7C61 ; .lba_value dq 0x00 ; LBA addres value
seg000:7C61 ; }
seg000:7C67 66 FF 76 08 push large dword ptr [bp+8] ; 读取的源地址,以扇区为单位,这里是0x800扇区,也就是0x100000字节处
seg000:7C6B 68 00 00 push 0
seg000:7C6E 68 00 7C push 7C00h ; 写入的目的地址,完成拷贝
seg000:7C71 68 01 00 push 1 ; 读取一个扇区
seg000:7C74 68 10 00 push 10h ; packet 大小
seg000:7C77 B4 42 mov ah, 42h ; 'B' ; AH=42H Extended Read Sectors From Drive
seg000:7C79 8A 56 00 mov dl, [bp+0]
seg000:7C7C 8B F4 mov si, sp ; 传入packet的地址
seg000:7C7E CD 13 int 13h ; DISK - IBM/MS Extension - EXTENDED READ (DL - drive, DS:SI - disk address packet)
seg000:7C80 9F lahf
seg000:7C81 83 C4 10 add sp, 10h
seg000:7C84 9E sahf
seg000:7C85 EB 14 jmp short loc_7C9B ; 恢复通用寄存器
seg000:7C87 ; ---------------------------------------------------------------------------
seg000:7C87
seg000:7C87 loc_7C87: ; CODE XREF: seg000:7C5F↑j
seg000:7C87 B8 01 02 mov ax, 201h ; AH=02 功能号为02 Read Sectors From Drive
seg000:7C87 ; AL=01 读取一个扇区 Sectors To Read Count
seg000:7C8A BB 00 7C mov bx, 7C00h
seg000:7C8D 8A 56 00 mov dl, [bp+0] ; 磁盘号
seg000:7C90 8A 76 01 mov dh, [bp+1] ; 磁头
seg000:7C93 8A 4E 02 mov cl, [bp+2] ; 扇区
seg000:7C96 8A 6E 03 mov ch, [bp+3] ; 柱面
seg000:7C99 CD 13 int 13h ; DISK - READ SECTORS INTO MEMORY
seg000:7C99 ; AL = number of sectors to read, CH = track, CL = sector
seg000:7C99 ; DH = head, DL = drive, ES:BX -> buffer to fill
seg000:7C99 ; Return: CF set on error, AH = status, AL = number of sectors read
seg000:7C9B
seg000:7C9B loc_7C9B: ; CODE XREF: seg000:7C85↑j
seg000:7C9B 66 61 popad ; 恢复通用寄存器
seg000:7C9D 73 1C jnb short loc_7CBB ; int13 读取成功 CF=0 JNB跳转
seg000:7C9F FE 4E 11 dec byte ptr [bp+11h] ; bp+11=5 一共会读取5次磁盘
seg000:7CA2 75 0C jnz short loc_7CB0
seg000:7CA4 80 7E 00 80 cmp byte ptr [bp+0], 80h ; 比较磁盘驱动器号是否为80h
seg000:7CA8 0F 84 8A 00 jz loc_7D36 ; 比较失败,进入打印错误的代码
seg000:7CAC B2 80 mov dl, 80h
seg000:7CAE EB 84 jmp short loc_7C34 ; 磁盘驱动器号,用于AX=41H 下的INT13,例如第一块硬盘则DL=80H,由BIOS主板设定完毕
seg000:7CB0 ; ---------------------------------------------------------------------------
seg000:7CB0
seg000:7CB0 loc_7CB0: ; CODE XREF: seg000:7CA2↑j
seg000:7CB0 55 push bp
seg000:7CB1 32 E4 xor ah, ah
seg000:7CB3 8A 56 00 mov dl, [bp+0]
seg000:7CB6 CD 13 int 13h ; DISK - RESET DISK SYSTEM
seg000:7CB6 ; DL = drive (if bit 7 is set both hard disks and floppy disks reset)
seg000:7CB8 5D pop bp
seg000:7CB9 EB 9E jmp short loc_7C59
seg000:7CBB ; ---------------------------------------------------------------------------
seg000:7CBB
seg000:7CBB loc_7CBB: ; CODE XREF: seg000:7C9D↑j
seg000:7CBB 81 3E FE 7D 55 AA cmp ds:word_7DFE, 0AA55h ; 再次检测是否包含0X55AA
seg000:7CC1 75 6E jnz short loc_7D31 ; 不包含则进入打印错误流程,CPU执行hlt指令并暂停运行
seg000:7CC3 FF 76 00 push word ptr [bp+0]
seg000:7CC6 E8 8D 00 call sub_7D56 ; 这个call里面的核心就是in al, 64h,从64H端口读1byte到al
seg000:7CC9 75 17 jnz short loc_7CE2 ; AX=0BB00 INT 1A 时为, TCG_StatusCheck
seg000:7CCB FA cli ; 关闭中断
seg000:7CCC B0 D1 mov al, 0D1h
seg000:7CCE E6 64 out 64h, al ; 8042 keyboard controller command register.
seg000:7CCE ; Write output port (next byte to port 60h):
seg000:7CCE ; 7: 1=keyboard data line pulled low (inhibited)
seg000:7CCE ; 6: 1=keyboard clock line pulled low (inhibited)
seg000:7CCE ; 5: enables IRQ 12 interrupt on mouse IBF
seg000:7CCE ; 4: enables IRQ 1 interrupt on keyboard IBF
seg000:7CCE ; 3: 1=mouse clock line pulled low (inhibited)
seg000:7CCE ; 2: 1=mouse data line pulled low (inhibited)
seg000:7CCE ; 1: A20 gate on/off
seg000:7CCE ; 0: reset the PC (THIS BIT SHOULD ALWAYS BE SET TO 1)
seg000:7CD0 E8 83 00 call sub_7D56
seg000:7CD3 B0 DF mov al, 0DFh
seg000:7CD5 E6 60 out 60h, al ; 8042 keyboard controller data register.
seg000:7CD7 E8 7C 00 call sub_7D56
seg000:7CDA B0 FF mov al, 0FFh
seg000:7CDC E6 64 out 64h, al ; 8042 keyboard controller command register.
seg000:7CDC ; Pulse output port.
seg000:7CDC ; Bits 0-3 indicate ports to pulse.
seg000:7CDE E8 75 00 call sub_7D56
seg000:7CE1 FB sti ; 开启中断
seg000:7CE2
seg000:7CE2 loc_7CE2: ; CODE XREF: seg000:7CC9↑j
seg000:7CE2 B8 00 BB mov ax, 0BB00h ; AX=0BB00 INT 1A 时为, TCG_StatusCheck
seg000:7CE5 CD 1A int 1Ah ; Trusted Computing Group call - TCG_StatusCheck
seg000:7CE5 ; Return: EAX = 0 if supported
seg000:7CE5 ; EBX = 41504354h ('TCPA')
seg000:7CE5 ; CH:CL = TCG BIOS Version
seg000:7CE5 ; EDX = BIOS TCG Feature Flags
seg000:7CE5 ; ESI = Pointer to Event Log
seg000:7CE5 ;
seg000:7CE7 66 23 C0 and eax, eax ; TCG 状态检测结果放在eax,eax!=0则说明不支持
seg000:7CEA 75 3B jnz short loc_7D27 ; dx = 0x80 驱动器号
seg000:7CEC 66 81 FB 54 43 50 41 cmp ebx, 41504354h ; TCG检测通过会在EBX中放入"TCPA"的Hex字节码
seg000:7CF3 75 32 jnz short loc_7D27 ; dx = 0x80 驱动器号
seg000:7CF5 81 F9 02 01 cmp cx, 102h ; TCG检查返回后会在ECX中放入TCG BIOS Version
seg000:7CF9 72 2C jb short loc_7D27 ; dx = 0x80 驱动器号
seg000:7CFB 66 68 07 BB 00 00 push large 0BB07h ; 又是跟TCG相关的一些东西
seg000:7D01 66 68 00 02 00 00 push large 200h
seg000:7D07 66 68 08 00 00 00 push large 8
seg000:7D0D 66 53 push ebx
seg000:7D0F 66 53 push ebx
seg000:7D11 66 55 push ebp
seg000:7D13 66 68 00 00 00 00 push large 0
seg000:7D19 66 68 00 7C 00 00 push large 7C00h
seg000:7D1F 66 61 popad
seg000:7D21 68 00 00 push 0
seg000:7D24 07 pop es
seg000:7D25 CD 1A int 1Ah
seg000:7D27
seg000:7D27 loc_7D27: ; CODE XREF: seg000:7CEA↑j
seg000:7D27 ; seg000:7CF3↑j ...
seg000:7D27 5A pop dx ; dx = 0x80 驱动器号
seg000:7D28 32 F6 xor dh, dh
seg000:7D2A EA 00 7C 00 00 jmp far ptr loc_7C00 ; 7C00经过之前的拷贝已经变为了VBR的代码,现在开始转入执行VBR
seg000:7D2F ; ---------------------------------------------------------------------------
seg000:7D2F CD 18 int 18h ; TRANSFER TO ROM BASIC
seg000:7D2F ; causes transfer to ROM-based BASIC (IBM-PC)
seg000:7D2F ; often reboots a compatible; often has no effect at all
seg000:7D31
seg000:7D31 loc_7D31: ; CODE XREF: seg000:7CC1↑j
seg000:7D31 A0 B7 07 mov al, ds:7B7h ;7B7内容为9A,也是就获取700+9A处的字符串
seg000:7D34 EB 08 jmp short loc_7D3E ; 这些都是打印错误信息
seg000:7D36 ; ---------------------------------------------------------------------------
seg000:7D36
seg000:7D36 loc_7D36: ; CODE XREF: seg000:7CA8↑j
seg000:7D36 A0 B6 07 mov al, ds:7B6h
seg000:7D39 EB 03 jmp short loc_7D3E
seg000:7D3B ; ---------------------------------------------------------------------------
seg000:7D3B
seg000:7D3B loc_7D3B: ; CODE XREF: seg000:7C29↑j
seg000:7D3B A0 B5 07 mov al, ds:7B5h
seg000:7D3E
seg000:7D3E loc_7D3E: ; CODE XREF: seg000:7D34↑j
seg000:7D3E ; seg000:7D39↑j
seg000:7D3E 32 E4 xor ah, ah
seg000:7D40 05 00 07 add ax, 700h
seg000:7D43 8B F0 mov si, ax
seg000:7D45
seg000:7D45 loc_7D45: ; CODE XREF: seg000:7D51↓j
seg000:7D45 AC lodsb
seg000:7D46 3C 00 cmp al, 0
seg000:7D48 74 09 jz short loc_7D53
seg000:7D4A BB 07 00 mov bx, 7
seg000:7D4D B4 0E mov ah, 0Eh
seg000:7D4F CD 10 int 10h ; - VIDEO - WRITE CHARACTER AND ADVANCE CURSOR (TTY WRITE)
seg000:7D4F ; AL = character, BH = display page (alpha modes)
seg000:7D4F ; BL = foreground color (graphics modes)
seg000:7D51 EB F2 jmp short loc_7D45
seg000:7D53 ; ---------------------------------------------------------------------------
seg000:7D53
seg000:7D53 loc_7D53: ; CODE XREF: seg000:7D48↑j
seg000:7D53 ; seg000:7D54↓j
seg000:7D53 F4 hlt
seg000:7D54 ; ---------------------------------------------------------------------------
seg000:7D54 EB FD jmp short loc_7D53
seg000:7D56
seg000:7D56 ; =============== S U B R O U T I N E =======================================
seg000:7D56
seg000:7D56
seg000:7D56 sub_7D56 proc near ; CODE XREF: seg000:7CC6↑p
seg000:7D56 ; seg000:7CD0↑p ...
seg000:7D56 2B C9 sub cx, cx
seg000:7D58
seg000:7D58 loc_7D58: ; CODE XREF: sub_7D56+8↓j
seg000:7D58 E4 64 in al, 64h ; 8042 keyboard controller status register
seg000:7D58 ; 7: PERR 1=parity error in data received from keyboard
seg000:7D58 ; +----------- AT Mode ----------+------------ PS/2 Mode ------------+
seg000:7D58 ; 6: |RxTO receive (Rx) timeout | TO general timeout (Rx or Tx)|
seg000:7D58 ; 5: |TxTO transmit (Tx) timeout | MOBF mouse output buffer full |
seg000:7D58 ; +------------------------------+-----------------------------------+
seg000:7D58 ; 4: INH 0=keyboard communications inhibited
seg000:7D58 ; 3: A2 0=60h was the port last written to, 1=64h was last
seg000:7D58 ; 2: SYS distinguishes reset types: 0=cold reboot, 1=warm reboot
seg000:7D58 ; 1: IBF 1=input buffer full (keyboard can't accept data)
seg000:7D58 ; 0: OBF 1=output buffer full (data from keyboard is available)
seg000:7D5A EB 00 jmp short $+2
seg000:7D5C ; ---------------------------------------------------------------------------
seg000:7D5C
seg000:7D5C loc_7D5C: ; CODE XREF: sub_7D56+4↑j
seg000:7D5C 24 02 and al, 2
seg000:7D5E E0 F8 loopne loc_7D58
seg000:7D60 24 02 and al, 2
seg000:7D62 C3 retn
seg000:7D62 sub_7D56 endp
seg000:7D62
seg000:7D62 ; ---------------------------------------------------------------------------
seg000:7D63 49 db 49h ; I
seg000:7D64 6E 76 61 6C 69 64 20 70+aNvalidPartitio db 'nvalid partition table',0
seg000:7D7B 45 db 45h ; E
seg000:7D7C 72 72 6F 72 20 6C 6F 61+aRrorLoadingOpe db 'rror loading operating system',0
seg000:7D9A 4D db 4Dh ; M
seg000:7D9B 69 73 73 69 6E 67 20 6F+aIssingOperatin db 'issing operating system',0
seg000:7DB3 00 00 63 7B 9A 73 0D 64+ db 2 dup(0), 63h, 7Bh, 9Ah, 73h, 0Dh, 64h, 36h, 2 dup(0)
seg000:7DB3 36 00 00 80 20 21 00 07+ db 80h, 20h, 21h, 0, 7, 7Fh, 39h, 6, 0, 8, 3 dup(0), 90h
seg000:7DB3 7F 39 06 00 08 00 00 00+ db 1, 2 dup(0), 7Fh, 3Ah, 6, 7, 0FEh, 2 dup(0FFh), 0, 98h
seg000:7DB3 90 01 00 00 7F 3A 06 07+ db 1, 0, 52h, 85h, 0ECh, 4, 0, 0FEh, 2 dup(0FFh), 27h
seg000:7DB3 FE FF FF 00 98 01 00 52+ db 0FEh, 2 dup(0FFh), 0, 20h, 0EEh, 4, 0, 0D0h, 11h, 11h dup(0)
seg000:7DFE 55 AA word_7DFE dw 0AA55h ; DATA XREF: seg000:loc_7CBB↑r
seg000:7DFE seg000 ends
seg000:7DFE
seg000:7DFE
seg000:7DFE end
|