首页
社区
课程
招聘
[旧帖] 关于硬盘MBR 和DPT 0.00雪花
发表于: 2013-3-10 21:01 11689

[旧帖] 关于硬盘MBR 和DPT 0.00雪花

2013-3-10 21:01
11689
昨天写了一个程序用PIO 将硬盘的 MBR 和 DPT 读取了出来。
结果一看 怎么才256B。
而且我完全找不到那里是DPT 连有效的BI(bootSign)都没找到。
我在虚拟机dos 下用FDISK 只有一个c盘 而且是active 也就是BI= 80H。
结果我用 winHEX 看数据完全没找到。 头疼啊 我下面发一下 MBR 数据的图吧。

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 0
支持
分享
最新回复 (21)
雪    币: 608
活跃值: (648)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
2
MBR=DBR+DiskSignature+DPT
楼主的图挂了 看不到~
2013-3-10 21:04
0
雪    币: 496
活跃值: (286)
能力值: ( LV13,RANK:400 )
在线值:
发帖
回帖
粉丝
3
// ReadMBR.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#define MBR_BYTE_COUNT 512


int _tmain(int argc, _TCHAR* argv[])
{
	HANDLE hDrive = NULL;
	UCHAR buffer[MBR_BYTE_COUNT];
	DWORD dwByteCount = 0;
	BOOL bRet = FALSE;

	hDrive = CreateFile(TEXT("\\\\.\\C:"), 	
		GENERIC_READ|GENERIC_WRITE, 
		FILE_SHARE_READ|FILE_SHARE_WRITE, 
		0, 
		OPEN_EXISTING,
		0, 0);

	if (hDrive == INVALID_HANDLE_VALUE)
	{
		_tprintf(TEXT("Fialed @CreateFile\n"));
		system("PAUSE");
		return 0;
	}

	bRet = ReadFile(hDrive, buffer, MBR_BYTE_COUNT, &dwByteCount, NULL);
	if (bRet == FALSE)
	{
		CloseHandle(hDrive);
		_tprintf(TEXT("Fialed @ReadFile\n"));
		system("PAUSE");
		return 0;
	}
	CloseHandle(hDrive);

	_tprintf(TEXT("Read done!\n"));

	HANDLE hBinFile = NULL;
	//hBinFile = CreateFile(TEXT(".\\MBR_bin.bin"), 
	hBinFile = CreateFile(TEXT(".\\DBR[C]_bin.bin"), 
		GENERIC_WRITE,
		0, 0, 
		CREATE_NEW,
		0, 0);

	if (hBinFile == NULL)
	{
		_tprintf(TEXT("Fialed @CreateFile\n"));
		system("PAUSE");
		return 0;
	}

	bRet = WriteFile(hBinFile, buffer, MBR_BYTE_COUNT, &dwByteCount, NULL);
	if (bRet == FALSE)
	{
		CloseHandle(hBinFile);
		_tprintf(TEXT("Fialed @WriteFile\n"));
		system("PAUSE");
		return 0;
	}
	CloseHandle(hBinFile);

	system("PAUSE");
	return 0;
}




MBR结构:

偏移    内容                         大小(字节)

0h      主引导程序                   最大446[之前手误写成了466]

01BEh   硬盘分区表(DPT)              64

01FEh   启动标志(0x55 0xAA)          2

十六进制标记55 AA,标志着一个有效的引导记录(Boot Sector)的结尾。每一个分区的引导记录中都必须有这个标记。同样Boot Sector的结尾两个字节也要为55 AA。

硬盘分区表(DPT)结构:

偏移    内容                         大小(字节)

01BEh   分区1的分区数据表            16

01CEh   分区2的分区数据表            16

01DEh   分区3的分区数据表            16

01FEh   分区4的分区数据表            16

分区数据表(Partition Data Table)结构:

偏移    内容                         大小(字节)

00h     引导ID标记(Boot indicator)   1

01h     起始扇区头号                 1

02h     起始扇区 (柱面号的最高2位)   1

03h     起始柱面号# (柱面号的低位)   1

04h     系统属性ID 标记              1

05h     结束扇区头号                 1

06h     结束扇区(柱面号的最高2位)    1

07h     结束柱面号# (柱面号的低位)   1

08h     此分区前的扇区总数目         4

0Bh     此分区的扇区总数目           4

引导ID标记(Boot indicator):

00h:不可启动分区

80h:可启动分区(只能有一个分区为此ID)

系统属性ID 标记(System Indicator ):

00h:未知操作系统

01h:DOS FAT12(16位扇区数)

02h:XENIX

04h:DOS FAT16(16位扇区数)

05h:DOS 扩展分区(DOS 3.3+)

06h:DOS 4.0 (Compaq 3.31), 32位扇区数

51h:Ontrack扩展分区

64h:Novell

75h:PCIX

DBh:CP/M

FFh:BBT

http://blog.csdn.net/otishiono/article/details/5906119
2013-3-10 21:18
0
雪    币: 608
活跃值: (648)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
4
话说,楼主的MBR读取代码不对啊~
MBR是位于硬盘物理扇区第一扇区才对,而不是C盘第一个扇区~
C盘的第一个扇区那叫VBR
再有就是没有设置读写指针位置

修改方案:
1.把设备名称从\\\\.\\C:改成\\\\.\\PhysicalDrive0
2.读扇区之前先SetFilePointer(hDrive,0,nil,FILE_BEGIN);
2013-3-10 21:35
0
雪    币: 496
活跃值: (286)
能力值: ( LV13,RANK:400 )
在线值:
发帖
回帖
粉丝
5
我不是楼主,我的代码只是给个读取DBR的列子,搂入想读MBR的

	//hDrive = CreateFile(TEXT("\\\\.\\PHYSICALDRIVE0"), 
	hDrive = CreateFile(TEXT("\\\\.\\C:"), 	
		GENERIC_READ|GENERIC_WRITE, 
		FILE_SHARE_READ|FILE_SHARE_WRITE, 
		0, 
		OPEN_EXISTING,
		0, 0);


自己取消注释,换一下就行了。

CreateFile返回的handle的FilePointer一定在FILE_BEGIN
2013-3-10 21:46
0
雪    币: 608
活跃值: (648)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
6
好吧是我眼花了~
2013-3-10 21:50
0
雪    币: 8
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
对不起口误。 的确是读的是 C:0 ,H:0 ,S:1
但是我读取出来怎么才 256个字节
1楼的那个图看不到么? 我在想个办法发一次吧。
2013-3-10 21:59
0
雪    币: 8
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8

使用了上传附件
上传的附件:
2013-3-10 22:15
0
雪    币: 8
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
我在最下面的补了图 请看看 这些资料其实我也有 。就是在对比的时候出现了问题。
2013-3-10 22:16
0
雪    币: 608
活跃值: (648)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
10
图又显示不出来啊~
2013-3-10 22:19
0
雪    币: 8
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
可以吧 我让我朋友试过的 在下面
2013-3-10 22:33
0
雪    币: 8
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
我发现可以修改 我修改了一下1楼也行了。
2013-3-10 22:34
0
雪    币: 496
活跃值: (286)
能力值: ( LV13,RANK:400 )
在线值:
发帖
回帖
粉丝
13
大哥啊,不要急。。。。
以后发图把图放在本地,然后在发帖的时候点击添加附件,然后选择插入附件就行了的。

读取的字节数是你自己控制的,你要知道为什么,就把你用于读取的代码贴出来。
2013-3-10 22:37
0
雪    币: 427
活跃值: (488)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
int 13 02
2013-3-10 22:39
0
雪    币: 8
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
[

include display.asm
code segment
assume cs:code
	
buffer equ (1f0H)
error_info equ (1f1H);
sector_c equ(1f2H)
sector equ (1F3H)
cylinder_L equ (1F4H)
cylinder_H equ (1f5H)
header equ (1f6H)
status_ctrl equ (1f7H)



start :
	mov dx,sector
        mov al,1H                                  //第一扇区
	out dx,al
	;setting  the number of sector
	mov dx,cylinder_l 
	mov al,0H                               //第0柱面(磁道)低位
	out dx,al
	;setting  the number of low cylinder
	mov dx,cylinder_h
	mov al,0H                                //第0柱面(磁道)高位
	out dx,al
	;setting the number of high cylinder
	mov dx,header
	mov al,10100000b               //第 0磁头 低4位 为磁头号
	out dx,al
	;setting the number of header
	mov dx,sector_c 
	mov al,01h                            //指定读取扇区数
	out dx,al
	;setting the count of sector
	
	mov dx,status_ctrl
	mov al,20H;                          //发送读指令
	out dx,al
	
wait_read:
	mov dx,status_ctrl
	in al,dx
	test al,00001000b		;if 3 bit of the status equals 0 ,so read action not over 
	jz wait_read		 
	;
	mov ax,2000H
	mov es,ax                       
	mov di,0H
	mov cx,512D
	mov dx,buffer
	

operation:
	in al,dx
        mov es:[di],al
	inc di                        ;将 512 位数据读入 地址 2000:0
	loop operation 


        mov ax,cs
        mov ds,ax
        mov dx,offset filepath
        mov ah,3Dh
        mov al,1h                           ;用21H 中断将文件地址引入dos 内部文件操作库
        int 21h



        
        mov bx,ax
        push bx
        mov ax,2000H
        mov ds,ax                 ;将 2000:0 的代码写入MBR.dat文件
        mov dx,0H        
        mov cx,512D
        mov ah,40H
        int 21H

        mov dl,ah
        call far ptr binaryShow
        mov dl,al
        call far ptr binaryShow
        ;
        pop bx
        mov ah,4eH               ;删除操作文件在dos 内部地址的映射
        int 21H

       
        mov ah,4Ch
        int 21H

        filepath  db 'c:\codes\test\hd\MBR.dat'            ;文件路径
        db 0H  


code ends
end start





关于binaryShow 是自己写的一个显示 2进制的一个函数库 这里就不贴代码了。
2013-3-10 23:33
0
雪    币: 8
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
我这是用的PIO 方式 没用dos 提供的中断函数(函数有可能是用的DMA 方式) 但是效果是一样的
2013-3-10 23:40
0
雪    币: 496
活跃值: (286)
能力值: ( LV13,RANK:400 )
在线值:
发帖
回帖
粉丝
17
[QUOTE=Ryanspears;1151383][

include display.asm
code segment
assume cs:code
       
buffer equ (1f0H)
error_info equ (1f1H);
sector_c equ(1f2H)
sector equ (1F3H)
cylinder_...[/QUOTE]

代码看起来没有问题,你再找找原因吧,插入打印语句,看看从哪里出错的。
2013-3-11 10:21
0
雪    币: 8
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
嗯  我试试
2013-3-11 13:37
0
雪    币: 206
活跃值: (85)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
Morgion是对的
2013-3-11 15:35
0
雪    币: 11026
活跃值: (17530)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
好资料啊,可惜我看不懂啊
2013-7-26 21:08
0
雪    币: 290
活跃值: (41)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
21
这个问题我遇过~~~
那个档案是虚拟硬盘的档->经过压缩的,只有虚拟机才能执行

把那个档用虚拟碟片精灵转成实际大小,
即是你虚拟硬盘设 2G 的空间,经过压缩只有 1.2 G
先转换成实际大小 2 G,WinHex读取格式就正确了
2013-7-26 21:40
0
雪    币: 8
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
这个程序本身是有点问题的. 问题虽然很小 原因就是 数据寄存器是 16位 的 而不是 8位的
所以 本来 512 扇区的硬盘 读取 分为 256次 但是 因为 8位读取 读取了 512 次 所以 后面的256 给予 FF的无效数据标识符
2013-9-22 01:24
0
游客
登录 | 注册 方可回帖
返回
//