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语言描述:
1 void LoadSector(int des,int src,int count) 2{ 3 int run = count / 64; //计算扇区的循环次数 为了提高效率不安扇区127的倍数取,取2的6次方64 4 int mod = count % 64; //计算剩余扇区 5 for(int i=0,i<run,i++) 6 { 7 ReadWriteSector(0x80,src,0,64,des,0x42); //每次读取64扇区 8 src = src +64; //重写计算扇区 9 des = des + 64*512; //重新计算目的地址 10 } 11 if(mod) //如果纯在剩余扇区,读取一次就ok了 12 { 13 ReadWriteSector(0x80,src,0,64,des,0x42); 14 } 15}
(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实现:
1 void LoadSector(int des,int src,int count) 2{ 3 int run = count / 64; //计算扇区的循环次数 为了提高效率不安扇区127的倍数取,取2的6次方64 4 int mod = count % 64; //计算剩余扇区 5 for(int i=0,i<run,i++) 6 { 7 ReadWriteSector(0x80,src,0,64,des,0x42); //每次读取64扇区 8 src = src +64; //重写计算扇区 9 des = des + 64*512; //重新计算目的地址 10 } 11 if(mod) //如果纯在剩余扇区,读取一次就ok了 12 { 13 ReadWriteSector(0x80,src,0,64,des,0x42); 14 } 15}
LoadSector的nasm源代码:
1 void LoadSector( 2; int des, 3; int src, 4; int count); 5LoadSector: 6;{ 7 push ebp 8 mov ebp, esp ;保存栈框架 这里是0x7c00-4-4-4-2=0x7bf2 进入LoadSector的三次push call LoadSector占2B 9 10 sub esp, 0E4h ;开辟栈空间0e4h=228 11 push ebx 12 push esi 13 push edi 14 15 ;int run = count / 64; 16 mov eax,dword [ebp+0Eh] ;ebp+0eh为进入函数后的esp+14及最开始的push count 17 cdq ;扩展edx为eax的高位 18 and edx, 3Fh 19 add eax, edx 20 sar eax, 6 ;右移6位及除以64 21 mov dword [ebp-8], eax ;保存循环次数ebp-8 22 23 ;int mod = count % 64; 24 mov eax, dword [ebp+0Eh] ;读取扇区数 这里就是将参数count的值传入给eax 就是最开始的ebp+14 25 and eax, 8000003Fh ;实现摸64操作 26 jns .set_mod 27 dec eax 28 or eax,0FFFFFFC0h 29 inc eax 30 31.set_mod: 32 mov dword [ebp-14h], eax ;将64的余数放到ebp - 14h中 最开始开辟了228B的空间 33 ;for(int i=0; i<run; i++) 34 mov dword [ebp-20h], 0 ;i的空间地址设置成为0 35 jmp _read 36 37_loop: 38 mov eax,dword [ebp-20h] 39 add eax,1 40 mov dword [ebp-20h],eax 41_read: 42 mov eax,dword [ebp-20h] ;将i的值给eax和次数比较 43 cmp eax,dword [ebp-8] ;eax和ebp-8及最开始的count比较 44 jge _left ;大于等于则跳转 退出循环 45 ;{ 46 ;ReadWriteSector(0x80, src, 0, 64, des, 0x42); 47 push dword 42h 48 mov eax, dword [ebp+6] 49 push eax 50 push dword 40h 51 push dword 0 52 mov ecx, dword [ebp+0Ah] 53 push ecx 54 push dword 80h 55 call ReadWriteSector 56 add esp, 24 57 ;src = src + 64; 58 mov eax, dword [ebp+0Ah] 59 add eax, 40h 60 mov dword [ebp+0Ah], eax 61 ;des = des + 64*512; 62 mov eax, dword [ebp+6] 63 add eax, 8000h 64 mov dword [ebp+6], eax 65 ;} 66 jmp _loop 67 ;if(mod) 68_left: 69 cmp dword [ebp-14h],0 70 je .return 71 ;{ 72 ;ReadWriteSector(0x80, src, 0, mod, des, 0x42); 73 push dword 42h 74 mov eax, dword [ebp+6] 75 push eax 76 mov ecx, dword [ebp-14h] 77 push ecx 78 push dword 0 79 mov edx, dword [ebp+0Ah] 80 push edx 81 push dword 80h 82 call ReadWriteSector 83 add esp, 24 84 ;} 85;} 86.return: 87 pop edi 88 pop esi 89 pop ebx 90 add esp, 0E4h 91 mov esp, ebp 92 pop ebp 93 ret 12 94 95 ReadWriteSector汇编代码 96相关的数据结构 97;Disk Address Packet 98struc DAP 99 .PacketSize resb 1 ;数据包的大小,固定为10h 100 .Reserved resb 1 ;预留空间固定为1字节 101 .BlockCount resw 1 ;0~127 要传输的扇区数目 102 .BufferOffset resw 1 ;传输缓冲的偏移地址 103 .BufferSegment resw 1 ;传输缓冲的地址段 104 .LBNLow resd 1 ;0 105 .LBNHigh resd 1 ; 106endstruc 107 108struc SectorFrame 109 .DriveNum resd 1 ;表示读取数据所在的磁盘 110 .LBNLow resd 1 ;要读取数据所在的骑士扇区号 111 .LBNHigh resd 1 ; 112 .BlockCount resd 1 ;一次读取的扇区数 113 .Buffer resd 1 ;所读取数据存放的物理地址 114 .ReadWrite resd 1 ;表示进行什么操作 读还是写 115endstruc 116 117 118;NTSTATUS 119;(_cdecl* ReadWriteSector)( 120; ULONG DriveNum, 121; ULONG LBNLow, 122; ULONG LBNHigh, 123; ULONG BlockCount, 124; PVOID Buffer, 125; ULONG ReadWrite); // Read=0x42,Write=0x43 126 127ReadWriteSector: 128 push bp 129 mov bp, sp 130 add bp, 4 131 push ds 132 push si 133 push bx 134 135 push 0 136 pop ds 137 138 sub sp, 16 139 mov si, sp 140 mov byte [si+DAP.PacketSize], 10h 141 mov byte [si+DAP.Reserved], 0 142 mov al,byte [bp+SectorFrame.BlockCount] 143 mov byte[si+DAP.BlockCount], al 144 mov byte[si+DAP.BlockCount+1], 0 145 mov eax, dword[bp+SectorFrame.Buffer] 146 mov bx, ax 147 and bx, 0fh 148 mov word[si+DAP.BufferOffset], bx 149 shr eax, 4 150 mov word[si+DAP.BufferSegment], ax 151 mov eax, dword[bp+SectorFrame.LBNLow] 152 mov dword[si+DAP.LBNLow], eax 153 mov eax, dword[bp+SectorFrame.LBNHigh] 154 mov dword[si+DAP.LBNHigh], eax 155 mov ah, byte [bp+SectorFrame.ReadWrite] 156 mov dl, byte [bp+SectorFrame.DriveNum] 157 int 13h 158 jc .error 159 xor eax, eax 160.error: 161 and eax, 0000ffffh 162 163 add sp, 16 164 pop bx 165 pop si 166 pop ds 167 168 pop bp 169 retn