Hoofdstuk – 12
Lezen en wijzigen van MBR met behulp van programmering
Master Boot Record (MBR) of Master Partition Table (MPT)
De Master Boot Record (MBR), soms ook wel Master Partition Table (MPT) genoemd, wordt op de harde schijf gemaakt door de DOS-opdracht FDISK.EXE uit te voeren.
De MBR bevat een klein programma voor het laden en uitvoeren van de actieve (of opstart)partitie van de harde schijf. De Master Boot Record bevat informatie over alle vier de primaire partities op de harde schijf, zoals de startsector, eindsector, partitiegrootte, enzovoort.
De MBR bevindt zich in absolute sector 0, of we kunnen zeggen in cilinder 0, kop 0 en sector 1. Als er meer dan één partitie op de schijf staat, bevinden zich uitgebreide master boot records aan het begin van elk volume van de uitgebreide partitie.
Voor een gedetailleerde beschrijving, zie het hoofdstuk "Een logische benadering van schijven en besturingssystemen", dat eerder in dit boek is besproken.
Master Boot Record-formaat
We kunnen de harde schijf partitioneren in meerdere logische stations, waaraan DOS doorgaans een eigen stationsletter toewijst. Er kan slechts één partitie tegelijk als actieve (of opstart-)partitie worden gemarkeerd.

De master boot record heeft een limiet van vier vermeldingen in de primaire partitietabel. De locatie van de uitgebreide MBR kan echter worden verkregen via de MBR die de uitgebreide partitietabellen bevat. Deze heeft dezelfde indeling als de primaire partitietabel, behalve dat deze geen opstartcode bevat en dat 446 bytes aan ruimte doorgaans is gereserveerd voor opstartcode en leeg wordt gelaten.
De volledige 512 bytes van het master boot record zijn onderverdeeld zoals weergegeven in de tabel:

Alle uitgebreide partities moeten zich in de ruimte bevinden die is gereserveerd door de uitgebreide partitie-invoer. Er zijn slechts twee uitgebreide partities bedoeld om te worden gebruikt: de eerste als een normale partitie en de tweede als een andere uitgebreide partitie, indien aanwezig.
Met behulp van één Master Partition Table kunnen we dus de locatie van een andere Extended Master Partition Table ernaast bepalen, indien aanwezig.
Partitietabel-invoerformaat
De partitietabelinvoerindeling van elke partitie in de MBR wordt in de volgende tabel weergegeven. Elke partitie-invoer van een MBR kan worden opgesplitst in de volgende bytes met hun specifieke betekenissen:

Een programma schrijven om de MBR-partitietabel te lezen
Hieronder vindt u een programma waarmee u alle vier de partitie-items uit de MBR-partitietabel kunt lezen. Het programma geeft alle parameters van de partitie-informatie weer die in de MBR-partitietabel zijn vastgelegd.
De programmacodering ziet er als volgt uit:
/* Programma voor het lezen van MBR-partitietabel */
# voeg <bios.h> toe
/* structuur voor het lezen van partitie-invoer uit partitietabel */
structurele sectie
{
ongetekende char opstartbaar; /* Actieve byte van sectie */
unsigned char start_side ;/* Starthoofd */
ongetekend int start_sec_cyl ; /* combinatie
Startsector en
cilindernummer */
ongetekend char-onderdeeltype; /* Bestandssysteem
Indicatorbyte */
ongetekende char end_side; /* Einde header */
ongetekend geheel getal end_sec_cyl; /* combinatie
Startsector en
cilindernummer */
ongetekend lang part_beg ; /* Relatieve sector
Nummer */
ongetekend lang geheel getal; /* Sectielengte in
sector */
} ;
/* Structuur voor het lezen van MBR */
deel van de structuur
{
ongetekende char master_boot[446] ; /* IPL (initieel
Programmalader)*/
struct partitie pt[4] ; /* Partitietabel */
int laatste twee ; /* Magisch getal */
} ;
deel van de structuur p;
ongeldige main()
{
clrscr();
/* De eerste sector van de eerste harde schijf lezen */
biosdisk ( 2, 0x80, 0, 0, 1, 1, &p );
weergave(); /* MBR-informatie weergeven
Partitietabel */
krijgen();
}
/* Functie om informatie over de MBR-partitietabel weer te geven */
weergave()
{
ongetekend geheel getal s_sec, s_trk, e_sec, e_trk, i, t1, t2;
karaktertype[20], boot[5] ;
printf("\n\nDeel. Initiële laadlocatie
Eindlocatie Relatieve hoeveelheid");
printf("\nType Zijcilinder Sector
Zijcilinder Sector Sectoren Sectoren\n");
voor ( i = 0 ; i <= 3 ; i++ )
{
als ( p.pt[i].bootable == 0x80 )
strcpy ( boot, "Ja" );
anders
strcpy ( boot, "Nee" );
schakelaar ( p.pt[i].parttype )
{
geval 0x00 :
strcpy ( type, "Ongebruikt" ) ; break ;
geval 0x1 :
strcpy (type, "FAT12"); breken;
geval 0x2 :
strcpy (type, "Xenix"); breken;
geval 0x3 :
strcpy (type, "Xenix:usr"); breken;
geval 0x4 :
strcpy (type, "FAT16<32M"); breken;
geval 0x5 :
strcpy ( type, "DOS-Ext." ) ; breken ;
geval 0x6 :
strcpy (type, "FAT16>32M"); breken;
geval 0x7 :
strcpy (type, "NTFS"); breken;
geval 0x0b :
strcpy (type, "FAT32"); breken;
geval 0x0c :
strcpy (type, "FAT32-LBA"); breken;
geval 0x0d :
strcpy (type, "VFAT16"); breken;
geval 0x0e :
strcpy (type, "VFAT16-LBA"); breken;
geval 0x0f :
strcpy (type, "VFAT EXT"); breken;
geval 0x17 :
strcpy (type, "HPFS"); breken;
geval 0x81 :
strcpy ( type, "Oude LINUX" ) ; break ;
geval 0x82 :
strcpy (type, "LinuxSwap"); breken;
geval 0x83 :
strcpy (type, "LinuxNative"); breken;
geval 0x85 :
strcpy ( type, "Linux Ext." ) ; breken ;
standaard :
strcpy( type, "Onbekend" ) ; break ;
}
s_sec = ( p.pt[i].start_sec_cyl & 0x3f ); /* startend
Sector van de
partitie */
t1 = ( p.pt[i].start_sec_cyl & 0xff00 ) >> 8 ;
t2 = ( p.pt[i].start_sec_cyl & 0x00c0 ) << 2 ;
s_trk = t1 | t2 ; /* Startcilinder */
e_sec = ( p.pt[i].end_sec_cyl & 0x3f ) ; /*Eindsector */
t1 = ( p.pt[i].end_sec_cyl & 0xff00 ) >> 8 ;
t2 = ( p.pt[i].end_sec_cyl & 0x00c0 ) << 2 ;
e_trk = t1 | t2 ; /* eindcilinder */
printf ( "\n%6s %3s", type, boot ) ;
printf ( "%4d %6d %8d", p.pt[i].start_zijde, s_trk,s_sec ) ;
printf ( "%7d %6u %8u", p.pt[i].end_side, e_trk, e_sec ) ;
printf ( " %10lu %10lu", p.pt[i].part_beg,
p.pt[i].plen ) ;
}
retourneer 0;
}
De informatie die de uitvoer van het programma geeft, wordt ongeveer als volgt weergegeven:

Opmerkingen over codering:
De structuurpartitie wordt gebruikt om de verschillende parameters van de partitie-invoer van de partitie in de partitietabel van MBR te lezen. Het structuurdeel wordt gebruikt om MBR-informatie te lezen.
De functie display() geeft de informatie van MBR Partition Table-parameters weer op het scherm. Zoals we de uitvoer van het programma zien, worden de start- en eindcilinder en het sectornummer als volgt weergegeven:
Startsector = 1
Startcilinder = 0
Eindsector = 63
Eindcilinder = 701
Deze sector- en cilindernummers worden berekend uit de combinatie van twee bytes. De volgende tabellen laten zien hoe deze nummers worden berekend:

Dus start CHS van de partitie = 0-0-1.
Op dezelfde manier zijn de codering voor de eindcilinder en het sectornummer van de partitie in de volgende tabel weergegeven:

De eind-CHS van de partitie is dus 701-254-63.
Programma om alle logische partities en hun informatie te vinden
Het programma dat we eerder bespraken was om de partitie-informatie te lezen van de partitietabel van MBR. Maar alleen door de MBR te lezen, kunnen we niet de informatie krijgen van andere logische partities die zich in de uitgebreide partitie van de schijf bevinden.
We hebben al besproken dat de Master Boot Record de limiet van vier entries in de Master Partition Table heeft . De locatie van de Extended Master Boot Record kan echter worden verkregen met behulp van de Master Boot Record die Extended Partition Tables bevat , waarvan de indeling exact hetzelfde is als die van de hoofdpartitietabel.
Alle uitgebreide partities moeten bestaan binnen de ruimte die is gereserveerd door de uitgebreide partitie-invoer. Slechts twee van de uitgebreide partities zijn bedoeld om te worden gebruikt, de eerste als een normale partitie en de tweede als een andere uitgebreide partitie als die bestaat.
Met behulp van één Master Partition Table kunnen we dus de locatie van een andere Extended Master Partition Table ernaast vinden, indien aanwezig.
Het volgende programma is voor het vinden van alle logische partities en hun partitie-invoerinformatie, het lezen van MBR en Extended MBR's van de schijf. De codering van het programma is als volgt:
/* Programma om de parameters van alle logische partities op de schijf te lezen */
#include<dos.h>
heeft buffer[512], report_par[20];
ongetekende drive_num =0x80;
ongetekende lange star_sec[20], sec;
/* Structuur van het schijfadrespakketformaat, te gebruiken door de readabsolutesectors-functie */
structuur diskaddrpacket
{
char packetsize ; /* Grootte van het pakket, over het algemeen 10H */
char gereserveerd ; /* Gereserveerd (0) */
int blockcount ; /* Aantal blokken om over te dragen */
char far *bufferadres ; /* adres om over te dragen
Buffertje */
ongetekend lang bloknummer[2] ; /* Beginnend Absoluut
Bloknummer */
} ;
leeg hoofd()
{
int niet_even,i;
clrscr();
geen_even = 0;
Alle_partitie_informatie (star_sec,&no_par, &sec, buffer,
rapport_par);
printf(" \n\n Totaal aantal partities op schijf = %d\n ",
geen_even);
voor(i=0;i<no_par;i++)
{
printf("\n Startsectornummer van partitie %d =
%lu " , i+1, ster_sec[i]);
}
afdrukkenf("\n");
halen();
}
De uitvoer van het programma wordt ongeveer als volgt weergegeven:
Partitie 1 - FAT32
Partitie 2 - FAT32
Partitie 3 - FAT32
Totaal aantal partities op schijf = 3
Startsectornummer van partitie 1 = 63
Startsectornummer van partitie 2 = 11277693
Startsectornummer van partitie 3 = 25623738
Opmerkingen over codering:
De structuur diskaddrpacket wordt gebruikt om het schijfadrespakketformaat te lezen, dat door de functie readabsolutesectors wordt gebruikt.
De functie All_partition_information( ) wordt gebruikt om alle parameters van alle partities uit de partitie-invoer te vinden.
Hoewel we in dit programma alleen de bestandssysteem- en relatieve sectorinformatie van alle beschikbare logische partities op de schijf hebben weergegeven, kunt u ook de informatie van andere parameters van de partitie-informatie afdrukken met behulp van de functie All_partition_information( ) met wat extra printf.
De codering van de functie is als volgt:
/* Functie om alle informatie over logische partities te vinden door hun partitie-invoer te lezen */
All_partition_information(unsigned long *star_sec,
niet ondertekend *no_par,
lang *sec, char *buffer,
ongetekende char *report_par )
{
ongetekende lange fat_check;
ongetekend lang *sectors_part;
statisch lang se_p;
int temp_var1,actieve_offset,actieve_pos=0,i, uitgebreide_pos=0, partloc1;
ongetekend lang b_sec,se;
ongetekende char active_par;
lang relatief_sec;
lang geen_sectoren;
als(*sec==0 || *sec==1)
se_p=0;
Doen{
zo=*sec;
/* Lees absolute sector gespecificeerd door *sec */
readabsolutesectors (drive_num,*sec,1,buffer);
/* ***** controleren op actieve partitie ***** */
if(*sec==se && *no_par==0) /*als primair
partitie */
{
*sec=se=0;
voor(actieve_offset=446; actieve_offset<=494; actieve_offset+=16)
{
active_par=buffer[actieve_offset];
if(active_par==0x80) /* controleer op actief
partitie */
pauze;
anders
active_pos++; /* positie van actief
partitie */
}
/* voor uitgebreide partitie */
voor(actieve_offset=450; actieve_offset<=511; actieve_offset+=16)
{
active_par=buffer[actieve_offset];
als(actieve_par==0x05 | actieve_par==0x0F)
/*controleren op uitgebreide partitie */
pauze;
anders
extended_pos++; /*positie van uitgebreide
partitie */
}
als(actieve_pos==4)
actief_pos=1;
als(uitgebreide_pos==4)
uitgebreide_pos=1;
partloc1=0x1C0+extended_pos*16;
}
anders
{
actieve_pos=0;
uitgebreide_pos=1;
deelloc1=0x1D0;
als(se_p!=0)
{
*sec=se=se_p; /*start van uitgebreide
partitie */
}
}
/* Relatieve sectoren in partitie */
relatieve_sec= *(unsigned long *)(buffer+454+actieve_pos*16);
/* Aantal sectoren in partitie */
geen_sectoren=*(lang *)(buffer+458+actieve_pos*16);
/* Identificeer de bestandssysteemindicatorbyte */
als( buffer[0x1C2+actieve_pos*16]==0x04 ||
buffer[0x1C2+actieve_pos*16]==0x05 ||
buffer[0x1C2+actieve_pos*16]==0x06 ||
buffer[0x1C2+actieve_pos*16]==0x0B ||
buffer[0x1C2+actieve_pos*16]==0x0C ||
buffer[0x1C2+actieve_pos*16]==0x0E ||
buffer[0x1C2+actieve_pos*16]==0x0F ||
buffer[0x1C2+actieve_pos*16]==0x07)
{
schakelaar(buffer[0x1C2+actieve_pos*16])
{
/* Voor NTFS-partitie */
geval 0x07: report_par[*no_par]='N';
printf("\n Partitie -%d = NTFS",
*niet_even+1);
pauze;
/* Voor FAT32-partitie */
geval 0x0B:
geval 0x0C: report_par[*no_par]='3';
printf("\n Partitie -%d = FAT32",
*niet_even+1);
pauze;
/* Voor FAT16-partitie */
geval 0x04:
geval 0x06:
geval 0x0E: report_par[*no_par]='1';
printf("\n Partitie -%d = FAT16",
*niet_even+1);
pauze;
} // Einde van de schakelaar
b_sec=*sec+relatieve_sec;
sectors_part[*no_par]=no_sectors; /* Array om het aantal sectoren van partities op te slaan */
} //Einde van if-voorwaarde
anders
{ /* als de partitie-indicator niet overeenkomt */
als(*sec==0)
{ geen_par=0;
pauze;
}
als((fat_check!=0x3631)&&(fat_check!=0x3233))
b_sec=*sec=0;
}
als((b_sec!=0)&&(sec!=0))
{
ster_sec[*geen_par]=b_sec;
(*niet_even)++;
}
anders
pauze;
/* controleren of uitgebreide partitie bestaat */
als(buffer[0x1C2+extended_pos*16]==0x05 ||
buffer[0x1C2+extended_pos*16]==0x0F )
{
temp_var1=(ongetekend)buffer[partloc1];
*sec=temp_var1 & 0x003F; /* sector van
verlengd
partitie */
als(*sec!=0)
{
se_p=se+relatieve_sec+geen_sectoren;
*sec=se_p;
}
anders
{ *sec=-1;
pauze;
}
} // sluiten van if-statement
anders
{
als(*sec>0)
*seconde=-1;
pauze;
}
} while(1); // sluit de do–while-lus
/* controleer op andere niet-actieve primaire partities op sector 0 */
als(*sec==0)
{
voor(i=0;i<4;i++)
{
actieve_par=buffer[446+i*16];
/* Identificeer de bestandssysteemindicator Byte */
als((buffer[0x1C2+i*16]==(teken)0x06 ||
buffer[0x1C2+i*16]==(teken)0x0B ||
buffer[0x1C2+i*16]==(teken)0x0C ||
buffer[0x1C2+i*16]==(teken)0x07 ||
buffer[0x1C2+i*16]==(teken)0x0E ||
buffer[0x1C2+i*16]==(teken)0x04) && actieve_par!=0x80)
{
schakelaar(buffer[0x1C2+actieve_pos*16])
{
/* Voor NTFS-partitie */
geval 0x07: report_par[*no_par]='N';
printf("\n Partitie -%d = NTFS",
*niet_even+1);
pauze;
/* Voor FAT32-partitie */
geval 0x0B:
geval 0x0C: report_par[*no_par]='3';
printf("\n Partitie -%d = FAT32",
*niet_even+1);
pauze;
/* Voor FAT16-partitie */
geval 0x04:
geval 0x06:
geval 0x0E: report_par[*no_par]='1';
printf("\n Partitie -%d = FAT16",
*niet_even+1);
pauze;
} // Einde van de schakelaar
/* relatieve sectoren Aantal partities */
relatieve_sec=*(lang *)(buffer+454+i*16);
no_sectors=*(long *)(buffer+458+i*16); /* aantal
sectoren in
partitie*/
sectors_part[*no_par]=no_sectors; /* Array om op te slaan
Aantal
sectoren van
partities */
*sec=ster_sec[*geen_par]=relatieve_sec;
(*niet_even)++;
}
} //lus sluiten van for(i=0;i<4;i++)
} //lus sluiten van if(*sec==0)
opbrengst;
}
Opmerkingen over codering:
De functie begint met het lezen van de partitie-informatie van de MBR en leest vervolgens de Extended MBR's indien nodig. De functie readabsolutesectors leest de absolute sector, gespecificeerd door *sec.
sectors_part[*no_par] is de array om het aantal sectoren van partities op te slaan. Het partitienummer wordt gespecificeerd door *no_par, beginnend bij 0.
no_sectors is het aantal sectoren in de partitie en relative_sec is het relatieve sectornummer voor die partitie.
star_sec[*no_par] is de array om de opgave sectornummers van partities op te slaan. Het partitienummer wordt gespecificeerd door *no_par beginnend bij 0.
star_cyl, star_hea en star_sec zijn de arrays die de informatie over het starten van elke partitie in termen van CHS bijhouden. star_cyl slaat de informatie over startcilinders op, star_hea slaat de informatie over startkoppen op en star_sec slaat de informatie over startsectoren van partities op.
Voor een beschrijving van de functie readabsolutesectors verwijzen wij u naar de hoofdstukken eerder in dit boek.
MBR aanpassen door programmeren
Het voorbeeldprogramma om te laten zien hoe we de waarden van de MBR-partitietabelinvoer kunnen wijzigen , is hieronder gegeven. Het programma wijzigt de waarden van de tweede partitie-invoer van de MBR-partitietabel .
De codering van het programma is hieronder weergegeven:
/* Programma om de waarden van de partitietabelinvoer van MBR te wijzigen */
# voeg <bios.h> toe
/* structuur om de partitie-invoer uit de partitietabel te lezen */
struct partitie
{
unsigned char bootable ; /* Actieve partitie
Byte */
unsigned char start_side ; /* Starthoofd */
unsigned int start_sec_cyl ; /* combinatie van
Startsector en
cilindernummer */
ongetekende char parttype ; /* Bestandssysteem
Indicatorbyte */
unsigned char end_side ; /* Eindkop */
unsigned int end_sec_cyl ; /* combinatie van
Startsector en
cilindernummer */
unsigned long part_beg ; /* Relatieve sector
Nummer */
unsigned long plen ; /* Partitielengte in
sectoren */
} ;
/* Structuur om MBR te lezen */
structuur onderdeel
{
ongetekende char master_boot[446] ; /* IPL (Initiaal
Programmalader)*/
struct partition pt[4] ; /* Partitietabel*/
int laatste twee ; /* Magisch getal */
} ;
struct deel p;
leeg hoofd()
{
ongetekende int t1,t2;
clrscr();
biosdisk ( 2, 0x80, 0, 0, 1, 1, &p );
display(); /* de partitie weergeven
Tabelinformatie */
halen();
/* Laten we aannemen dat we de partitie-informatie van de tweede partitie-invoer uit de partitietabel van MBR willen wijzigen met deze waarden */
p.pt[1].bootable = 0x80; /* Actieve opstartpartitie */
p.pt[1].parttype = 0x7; /* NTFS-partitie */
p.pt[1].start_side = 0; /* Starthoofd = 0 */
p.pt[1].eind_zijde = 31; /* Einde header == 31 */
p.pt[1].part_beg = 808416;/* Relatieve sector = 808416 */
p.pt[1].full = 405216; /* Totaal aantal sectoren in partitie = 405216 */
/* Schrijf nieuwe informatie naar MBR *\
/* Om waarden naar de MBR-partitietabel te schrijven, verwijdert u de commentaartekens van de onderstaande biosdisk-functie */
// biosschijf ( 3, 0x80, 0, 0, 1, 1, &p ) ;
weergave(); /* Weergave gewijzigd
Informatie */
krijgen();
}
Opmerkingen bij codering:
Het bovenstaande programma is een voorbeeldprogramma om te laten zien hoe we de waarden van een MBR-partitietabelvermelding kunnen wijzigen . Als u de partitie-invoerwaarden voor logische partities die zich in een uitgebreide partitie bevinden, wilt wijzigen, moet u de waarden in de uitgebreide MBR-partitietabel wijzigen .
De waarden die hier zijn gegeven om de partitietabelinvoer te wijzigen, dienen alleen om te laten zien hoe u dit kunt doen. Wijzig de partitietabel nooit met ongeldige of onlogische waarden. Hierdoor kan het zijn dat de gehele sectie ontoegankelijk wordt.
Het structuurgedeelte wordt gebruikt om de partitie-record uit de partitietabel te lezen, en het structuurgedeelte wordt gebruikt om de MBR te lezen. Om wijzigingen in de partitietabel aan te brengen, verwijdert u de commentaarmarkering voor de functie biosdisk() .
Als u de begin- en eindwaarden, sector- en cilindernummers van een partitie wilt wijzigen, berekent u de waarden zoals beschreven in de opmerkingen voor het programma voor het lezen en weergeven van de MBR-partitietabel, die aan het begin van dit hoofdstuk zijn besproken.