bochs:1 00000000000e[WGUI ] Sim client size(0, 0) != stretched size(640, 480)!
bochs:2 b 0x7c00
bochs:3 c
00000003740i[BIOS ] $Revision: 1.166 $ $Date: 2006/08/11 17:34:12 $
00000319045i[KBD ] reset-disable command received
00000321693i[PIDE ] new BM-DMA address: 0xc000
00000327577i[P2I ] PCI IRQ routing: PIRQA# set to 0x0b
00000327593i[P2I ] write: ELCR2 = 0x08
00000327613i[ACPI ] new irq line = 11
00000446187i[VBIOS] VGABios $Id: vgabios.c,v 1.66 2006/07/10 07:47:51 vruppert Exp $
00000446258i[BXVGA] VBE known Display Interface b0c0
00000446290i[BXVGA] VBE known Display Interface b0c4
00000449215i[VBIOS] VBE Bios $Id: vbe.c,v 1.58 2006/08/19 09:39:43 vruppert Exp $
00000759983i[BIOS ] ata0-0: PCHS=512/4/16 translation=none LCHS=512/4/16
00000800002i[WGUI ] dimension update x=720 y=400 fontheight=16 fontwidth=9 bpp=8
(0) Breakpoint 1, 0x0000000000007c00 in ?? ()
Next at t=957062
;中断与0x7c00 开始MBR程序
;关中断
(0) [0x0000000000007c00] 0000:7c00 (unk. ctxt): cli ; fa
bochs:4 n
Next at t=957063
(0) [0x0000000000007c01] 0000:7c01 (unk. ctxt): xor ax, ax ; 31c0
bochs:5 n
Next at t=957064
;设置段寄存器
(0) [0x0000000000007c03] 0000:7c03 (unk. ctxt): mov ss, ax ; 8ed0
bochs:6 n
Next at t=957065
;设置栈顶
(0) [0x0000000000007c05] 0000:7c05 (unk. ctxt): mov sp, 0x7c00 ; bc007c
bochs:7 n
Next at t=957066
;开中断
(0) [0x0000000000007c08] 0000:7c08 (unk. ctxt): sti ; fb
bochs:8 n
Next at t=957067
;设置数据段寄存器 就是把0x7c0 赋值给数据段寄存器 这里估计是源代码写重复了已经赋值了结果下面还用ax赋值给ds
;源代码中作者果然写重复了
;这里写重复了push和pop以及下面的都是已经把07c0h赋值给ds数据段寄存器了
push 07c0h
pop ds
mov ax, 07c0h
mov ds, ax
;//////////////////////////////////////////////////分割线////////////////////////////////////
(0) [0x0000000000007c09] 0000:7c09 (unk. ctxt): push 0x07c0 ; 68c007
bochs:9 n
Next at t=957068
(0) [0x0000000000007c0c] 0000:7c0c (unk. ctxt): pop ds ; 1f
bochs:10
Next at t=957069
(0) [0x0000000000007c0d] 0000:7c0d (unk. ctxt): mov ax, 0x07c0 ; b8c007
bochs:11 n
Next at t=957070
(0) [0x0000000000007c10] 0000:7c10 (unk. ctxt): mov ds, ax ; 8ed8
bochs:12 n
Next at t=957071
;加载ntldr
;count - ntldr扇区总数 80000h/512-8=0x3f8
(0) [0x0000000000007c12] 0000:7c12 (unk. ctxt): push 0x000003f8 ; 6668f8030000
bochs:13 n
Next at t=957072
;src开始读取的扇区号
(0) [0x0000000000007c18] 0000:7c18 (unk. ctxt): push 0x00000008 ; 666808000000
bochs:14 n
Next at t=957073
;des - 存放数据的目的地址(物理内存地址)
(0) [0x0000000000007c1e] 0000:7c1e (unk. ctxt): push 0x00020000 ; 666800000200
bochs:15 n
Next at t=957074
;这里是call LoadSector(int des,int src,int count);
;用c语言描述:
void LoadSector(int des,int src,int count)
{
int run = count / 64; //计算扇区的循环次数 为了提高效率不安扇区127的倍数取,取2的6次方64
int mod = count % 64; //计算剩余扇区
for(int i=0,i<run,i++)
{
ReadWriteSector(0x80,src,0,64,des,0x42); //每次读取64扇区
src = src +64; //重写计算扇区
des = des + 64*512; //重新计算目的地址
}
if(mod) //如果纯在剩余扇区,读取一次就ok了
{
ReadWriteSector(0x80,src,0,64,des,0x42);
}
}
(0) [0x0000000000007c24] 0000:7c24 (unk. ctxt): call .+7 (0x00007c2e) ; e80700
bochs:16 n
Next at t=1171020
;采用fastboot跳转至 0x2000:0003 如果是NTFS boot则跳转至0x2000:0000刚好执行 jmp RealStart 而fatboot则会忽略3B这条指令
(0) [0x0000000000007c27] 0000:7c27 (unk. ctxt): push 0x2000 ; 680020
bochs:17 n
Next at t=1171021
(0) [0x0000000000007c2a] 0000:7c2a (unk. ctxt): push 0x0000 ; 680000
bochs:18 n
Next at t=1171022
(0) [0x0000000000007c2d] 0000:7c2d (unk. ctxt): retf ; cb
bochs:19 n
Next at t=1171023
(0) [0x0000000000020000] 2000:0000 (unk. ctxt): jmp .+509 (0x00020200) ; e9fd01
bochs:20
LoadSector实现:
void LoadSector(int des,int src,int count)
{
int run = count / 64; //计算扇区的循环次数 为了提高效率不安扇区127的倍数取,取2的6次方64
int mod = count % 64; //计算剩余扇区
for(int i=0,i<run,i++)
{
ReadWriteSector(0x80,src,0,64,des,0x42); //每次读取64扇区
src = src +64; //重写计算扇区
des = des + 64*512; //重新计算目的地址
}
if(mod) //如果纯在剩余扇区,读取一次就ok了
{
ReadWriteSector(0x80,src,0,64,des,0x42);
}
}
LoadSector的nasm源代码:
void LoadSector(
; int des,
; int src,
; int count);
LoadSector:
;{
push ebp
mov ebp, esp ;保存栈框架 这里是0x7c00-4-4-4-2=0x7bf2 进入LoadSector的三次push call LoadSector占2B
sub esp, 0E4h ;开辟栈空间0e4h=228
push ebx
push esi
push edi
;int run = count / 64;
mov eax,dword [ebp+0Eh] ;ebp+0eh为进入函数后的esp+14及最开始的push count
cdq ;扩展edx为eax的高位
and edx, 3Fh
add eax, edx
sar eax, 6 ;右移6位及除以64
mov dword [ebp-8], eax ;保存循环次数ebp-8
;int mod = count % 64;
mov eax, dword [ebp+0Eh] ;读取扇区数 这里就是将参数count的值传入给eax 就是最开始的ebp+14
and eax, 8000003Fh ;实现摸64操作
jns .set_mod
dec eax
or eax,0FFFFFFC0h
inc eax
.set_mod:
mov dword [ebp-14h], eax ;将64的余数放到ebp - 14h中 最开始开辟了228B的空间
;for(int i=0; i<run; i++)
mov dword [ebp-20h], 0 ;i的空间地址设置成为0
jmp _read
_loop:
mov eax,dword [ebp-20h]
add eax,1
mov dword [ebp-20h],eax
_read:
mov eax,dword [ebp-20h] ;将i的值给eax和次数比较
cmp eax,dword [ebp-8] ;eax和ebp-8及最开始的count比较
jge _left ;大于等于则跳转 退出循环
;{
;ReadWriteSector(0x80, src, 0, 64, des, 0x42);
push dword 42h
mov eax, dword [ebp+6]
push eax
push dword 40h
push dword 0
mov ecx, dword [ebp+0Ah]
push ecx
push dword 80h
call ReadWriteSector
add esp, 24
;src = src + 64;
mov eax, dword [ebp+0Ah]
add eax, 40h
mov dword [ebp+0Ah], eax
;des = des + 64*512;
mov eax, dword [ebp+6]
add eax, 8000h
mov dword [ebp+6], eax
;}
jmp _loop
;if(mod)
_left:
cmp dword [ebp-14h],0
je .return
;{
;ReadWriteSector(0x80, src, 0, mod, des, 0x42);
push dword 42h
mov eax, dword [ebp+6]
push eax
mov ecx, dword [ebp-14h]
push ecx
push dword 0
mov edx, dword [ebp+0Ah]
push edx
push dword 80h
call ReadWriteSector
add esp, 24
;}
;}
.return:
pop edi
pop esi
pop ebx
add esp, 0E4h
mov esp, ebp
pop ebp
ret 12
ReadWriteSector汇编代码
相关的数据结构
;Disk Address Packet
struc DAP
.PacketSize resb 1 ;数据包的大小,固定为10h
.Reserved resb 1 ;预留空间固定为1字节
.BlockCount resw 1 ;0~127 要传输的扇区数目
.BufferOffset resw 1 ;传输缓冲的偏移地址
.BufferSegment resw 1 ;传输缓冲的地址段
.LBNLow resd 1 ;0
.LBNHigh resd 1 ;
endstruc
struc SectorFrame
.DriveNum resd 1 ;表示读取数据所在的磁盘
.LBNLow resd 1 ;要读取数据所在的骑士扇区号
.LBNHigh resd 1 ;
.BlockCount resd 1 ;一次读取的扇区数
.Buffer resd 1 ;所读取数据存放的物理地址
.ReadWrite resd 1 ;表示进行什么操作 读还是写
endstruc
;NTSTATUS
;(_cdecl* ReadWriteSector)(
; ULONG DriveNum,
; ULONG LBNLow,
; ULONG LBNHigh,
; ULONG BlockCount,
; PVOID Buffer,
; ULONG ReadWrite); // Read=0x42,Write=0x43
ReadWriteSector:
push bp
mov bp, sp
add bp, 4
push ds
push si
push bx
push 0
pop ds
sub sp, 16
mov si, sp
mov byte [si+DAP.PacketSize], 10h
mov byte [si+DAP.Reserved], 0
mov al,byte [bp+SectorFrame.BlockCount]
mov byte[si+DAP.BlockCount], al
mov byte[si+DAP.BlockCount+1], 0
mov eax, dword[bp+SectorFrame.Buffer]
mov bx, ax
and bx, 0fh
mov word[si+DAP.BufferOffset], bx
shr eax, 4
mov word[si+DAP.BufferSegment], ax
mov eax, dword[bp+SectorFrame.LBNLow]
mov dword[si+DAP.LBNLow], eax
mov eax, dword[bp+SectorFrame.LBNHigh]
mov dword[si+DAP.LBNHigh], eax
mov ah, byte [bp+SectorFrame.ReadWrite]
mov dl, byte [bp+SectorFrame.DriveNum]
int 13h
jc .error
xor eax, eax
.error:
and eax, 0000ffffh
add sp, 16
pop bx
pop si
pop ds
pop bp
retn