c ++ - Hvorfor er DWORD-værdier almindeligt repræsenteret i hexadecimal?

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg forsøger at forstå, hvorfor en DWORD-værdi ofte beskrives i hexadecimal på MSDN.


Grunden til, at jeg analyserer dette er, fordi jeg forsøger at forstå fundamentalt, hvorfor alle disse forskellige datatyper findes. En lokal mentor fortalte mig, at oprettelsen af ​​DWORD og andre Microsoft-typer havde noget at gøre med udviklingen af ​​processorer. Dette giver mening og sammenhæng til min forståelse af disse datatyper. Jeg vil gerne have mere sammenhæng og baggrund.


På nogen måde kan jeg bruge nogle forklaringer eller nogle ressourcer til at huske forskellen mellem DWORD, usignerede heltal, byte, bits, WORD osv.


Sammenfattende er mine spørgsmål:
1) Hvorfor er DWORD'er repræsenteret i Hex?
2) Kan du give ressourcer på forskellene mellem numeriske datatyper og hvorfor de blev oprettet?

Bedste reference


Alt i en computer er en flok 0s og 1s. Men at skrive en hel DWORD i binær er ret kedelig:


00000000 11111111 00000000 11111111


For at spare plads og forbedre læsbarheden, kan vi skrive det i kortere form. Decimalt er det, vi er mest bekendt med, men kortlægger det ikke godt for binært. Octal og Hexadecimal kort ganske bekvemt, der passer perfekt til de binære bits:


// each octal digit is exactly 3 binary digits
01 010 100 binary  =  124 octal

// each hexadecimal digit is exactly 4 binary digits
0101 0100 binary   =  54 hexadecimal


Da hex linjer op er meget pæne med 8 bit byte (2 hex siffer gør en byte), notationen sidder fast, og det er det der bliver brugt mest. Det er lettere at læse, lettere at forstå, lettere at lineere op rundt med bitmasker.


Den normale stenografi for at identificere hvilken base der anvendes:


  1234543 = decimal
 01234543 = octal (leading zero)
0x1234543 = hexadecimal (starts with 0x)


Hvad angår dit spørgsmål om BYTE, WORD, DWORD osv. ...


Computere startede med en smule. Kun 1 eller 0. Han havde en cameo i den oprindelige Tron.


Bytes er 8 bit lange (godt, engang var der 7-bit bytes, men vi kan ignorere dem). Dette giver dig mulighed for at have et nummer fra 0-255 eller et underskrevet nummer fra -128 til 127. Bedre end blot 1/0, men stadig begrænset. Du har måske hørt referencer til '8-bit gaming'. Det er det, vi refererer til. Systemet blev bygget omkring Bytes.


Derefter voksede computere til at have 16-bit registre. Dette er 2 byte og blev kendt som et ord (nej jeg ved ikke hvorfor). Nu kunne tal være 0-65535 eller -32768 til 32767.


Vi fortsatte med at have mere strøm, og computere blev udvidet til 32-bit registre. 4 byte, 2 ord, også kendt som en DWORD (dobbeltord). Indtil i dag kan du se i 'C: \ Windows' og se en mappe til 'system' (gamle 16 bit-stykker) og 'system32' (nye 32-bit-komponenter).


Så kom QWORD (quad-word). 4 ord, 8 byte, 64 bit. Har du nogensinde høre om Nintendo-64? Det er her navnet kom fra. Den moderne arkitektur er nu her. Cpu's internals indeholder 64-bit registre. Du kan generelt køre et 32- eller 64-bit operativsystem på sådanne cpus.


Det dækker Bit, Byte, Word, Dword. Det er rå typer, og bruges ofte til flag, bitmasker osv. Hvis du vil holde et faktisk nummer, er det bedst at bruge underskrevet/usigneret heltal, lang osv.


Jeg dækkede ikke flydende punktnumre, men forhåbentlig hjælper det med den generelle ide.

Andre referencer 1


DWORD-konstanter er typisk skrevet i hex, når de bruges som flag, der kan være OR 'd sammen i bitvis måde. Det gør det lettere at se, at det er sådan. Det er derfor du ser 0x01, 0x02, 0x04, 0x08, 0x10, 0x08, 0x10, 0x20 osv. Programmører genkender blot disse værdier som at have binære repræsentationer med blot en enkelt bitsæt.


Når det er en opregning, så ser du 0x01, 0x02, 0x03 osv. De er ofte stadig skrevet i hex, fordi programmerere har tendens til at komme ind i disse vaner!

Andre referencer 2


Blot til optegnelsen er 16 bit usignerede data navngivet WORD beacause på nuværende tidspunkt havde computere 16 bits registre.


I computerhistorikken, 8 bits data, hvor de største data du kan gemme på et register. Da det kunne gemme et ascii-tegn, blev det almindeligt kaldet CHAR.


Men 16 bit computer kom ud og CHAR var ikke hensigtsmæssigt at navngive 16 bits data.
Så 16 bits data blev almindeligt kaldet et ord fordi det var den største dataenhed, du kunne gemme på et register, og det var en god analogi at fortsætte den, der blev lavet for CHAR.


Så på nogle computere, der bruger et andet CPU WORD, refererer det ofte til registreringsstørrelsen. På Saturn CPU, som bruger 64 bit register, er et WORD 64 bit.


Da 32 bit x86-processorer kom ud, forblev WORD 16 bit for kompatibilitetsårsager, og DWORD blev oprettet for at udvide den til 32 bit. Det samme gælder for QWORD og 64 bit.


Hvad angår hvorfor hexadecimalt almindeligvis bruges til at beskrive et ord, har det at gøre med karakteren af ​​definitionen af ​​et ord, der er bundet til dets register oprindelse. I assembler programmering bruger du hexadecimal til at beskrive data, fordi processorer kun kender binray intergers (0 og 1). Og hexadecimal er en mere kompakt måde at bruge binær og stadig holder nogle af dens egenskaber.

Andre referencer 3


For at uddybe Tims svar er det fordi konvertering af hex til binær og tilbage er meget let - hvert hex ciffer er 4 binære cifre:


0x1 = 0001
0x2 = 0010
...
0xD = 1101
0xE = 1110
0xF = 1111


Så, 0x2D=0010 1101

Andre referencer 4


Du har meget intereserende og besværligt spørgsmål.


Kort sagt var der to chauffører, der førte til eksisterende af konkurrerende type familier - DWORD-baserede og int-baserede:


1) Ønsker at have crosspltformity på den ene side og stricktly størrelse typer på den anden hånd.


2) Folks konservatisme.


Under alle omstændigheder for at give ful detaljeret svar på jer spørgsmål og god nok baggrund af dette felt skal vi grave i computerens historie. Og start vores historie fra de tidlige dage af computing.


For det første er der et sådant begreb som et maskinord. Maskinord er en stricktly stor del af binære data, der er naturlig for behandling i den pågældende processor. Så maskinens ordstørrelse er næppe processorafhængig og er generelt lig med størrelsen af ​​de genealske interne processorregistre. Normalt kan det opdeles i de to lige dele, som også kan åbnes af processoren som uafhængige databaser. For eksempel på x86-processorer er maskinordstørrelsen 32 bits. Det betyder, at alle generelle registre (eax, ebx, ecx, edx, esi, edi, ebp, esp og eip) har samme størrelse - 32 bit. Men mange af dem er tilgængelige som en del af registret. For eksempel kan du få adgang til eax som 32 bit data chunk, ax, som 16 bit data chunk eller endda al som 8 bit data chunk. Men ikke så fysisk er det alle et 32 ​​bit register. Jeg tror, ​​at du kan finde meget god baggrund på dette felt på Wikipedia (http://en.wikipedia.org/wiki/Word\_(computer\_architecture)). Kort sagt er maskinord, hvor meget bit data chunk kan bruges som et heltal operand til den enkelte instruktion. Selv i dag har forskellige processorarkitekturer forskellige maskinordstørrelser.


Ok, vi har en vis forståelse for computerordet. Det er tid til at komme tilbage til computerens historie. De første Intel x86-processorer, der var populære, havde 16 bit ordstørrelse. Det kom til markedet i 1978. På den tid var montøren meget populær, hvis ikke et primært programmeringssprog. Som du ved, er assembler bare en meget tynd wrapper under det native processorsprog. På grund af dette er det underholdende hardwareafhængigt. Og da Intel skubber de nye 8086-processorer ind på markedet, var det første, de var nødvendige for at opnå succes, at skubbe eksemplet på den nye processor på markedet også. Ingen ønsker en processor, som ingen ved, hvordan man programmerer. Og da Intel gav navnene til de forskellige datatyper i assembleren til 8086, laver de det indlysende chois og navngiver 16-bit data chunk som et ord, fordi maskinordet i 8086 har 16-bit størrelse. Halvdelen af ​​maskinordet blev kaldt byte (8-bit) og to ord, der blev brugt som en operand, blev kaldt dobbeltord (32-bit).
Intel anvendte disse vilkår i processorer manualer og i assembler mnemonics (db, dwd dd for statisk tildeling af byte, ord og dobbelt ord).


År gået og 1985 Intel flyttede fra 16-bit arkitektur til 32-bit arkitektur med introduktion af 80386 processor. Men på det tidspunkt var der et stort antal udviklere, der var vant til at ordet er en 16-bit værdi. Udover det var der stort antal bløde, der blev skrevet med ægte belive, at ordet er 16-bit. Og mange af de allerede skrevne kode stole på, at ordet er 16 bit. På grund af dette var, ved siden af ​​det faktum, at maskinens ordstørrelse rent faktisk blev ændret, forblev den samme, bortset fra det faktum, at den nye datatype ankom til assembler-quad-ordet (64-bit), fordi instruktionen, der er afhængig af de to maskine ord forblev det samme, men maskinordet blev forlænget. På samme måde ankom det dobbelte quad-ord (128 bit) nu med 64-bit AMD64-arkitektur. Som resultat har vi


byte    =   8 bit
word    =  16 bit
dword   =  32 bit
qword   =  64 bit
dqword  = 128 bit


Bemærk det vigtigste i den type familie er, at det er stærkt mellemstore typer familie. Fordi det kommer fra og det er meget brugt i assembler, der kræver datatyper med konstant størrelse. Bemærk, at årene går i gang med en, men datatyperne fra denne familie fortsætter med samme konstante størrelse, foruden det faktum, at dets navn ikke allerede har den oprindelige betydning.


På den anden side, på samme tid år for år, blev sprogene på højt niveau mere og mere populære. Og fordi de languges blev udviklet med platform-applikation i sindet, kiggede de på størrelserne af dens interne datatyper helt andet set. Hvis jeg korrekt forstår, er ingen sprog på højt niveau ikke helt klart, at nogle af dens interne datatyper har en fast konstant størrelse, der aldrig vil blive ændret i fremtiden. Lad os ikke se på C ++ som i eksemplet. C ++ standart fortæller at:


"The fundamental storage unit in the C++ memory model is the byte. A byte is at 
least large enough to contain any member of the basic execution character set and 
is composed of a contiguous sequence of bits, the number of which is implementa-
tion-defined. The least significant bit is called the low-order bit; the most 
significant bit is called the high-order bit. The memory available to a C++ program
consists of one or more sequences of contiguous bytes. Every byte has a unique 
address."


Så vi kan se overraskende oplysninger - i C + + selv byte haven ikke nogen konstant størrelse. Så selvom vi vant til at tænke har størrelse - 8 bit, kan C + + ikke kun 8 men også 9, 10, 11, 12 osv. . bit i størrelse og måske endda 7 bit.


"There are five signed integer types: “signed char”, “short int”, “int”, and 
“long int”., and “long long int”. In this list, each type provides at least as 
much storage as those preceding it in the list. Plain ints have the natural size
suggested by the architecture of the execution environment; the other signed 
integer types are provided to meet special needs."


Denne citat beskriver to hovedkrav:


1) sizeof (char) <== sizeof (short) <=sizeof (int) <=sizeof (long) <=sizeof (long long)


2) Almindelig ints har den naturlige størrelse, der foreslås af arkitekturen i eksekveringsmiljøet. Det betyder, at int skal have maskinordstørrelsen af ​​målprocessorarkitekturen.


Du kan gennemgå alle C + + standard tekst, men du vil ikke finde noget som 'størrelsen af ​​int er 4 bytes' eller 'længden af ​​længden er 64 bit'. Størrelsen af ​​bestemte heltal C + + typer kan ændres ved at flytte fra en processor arkitektur til en anden, og med at flytte fra en compiler til en anden. Men selv når du skriver programmet i c ++, vil du med jævne mellemrum blive konfronteret med requirenment til at bruge datatyper med velkendt konstant størrelse.


Mindst tidligere kompilatorudviklere fulgte disse standardkrav. Men nu kan vi se, at folkens konservatisme kommer ind i spillet endnu en gang. Folk plejede at tro at int er 32-bit og kan gemme værdier fra intervallet fra -2.147.483.648 til 2.147.483.647. Tidligere da industrien kom gennem grænsen mellem 16-bit og 32-bit arkitekturer. Det andet krav blev stramt håndhævet. Og da du brugte C ++-kompilatoren til at oprette et 16-bit program, brugte kompilatoren int med 16-bit størrelse, der er 'naturlig størrelse' til 16-bit-processorer, og i modsætning hertil, da du brugte en anden C ++-compiler til at oprette 32-bit program, men fra samme kildekode, kompilator bruges int med 32-bit størrelse, der er 'naturlig størrelse' til 32-bit processorer. I dag, hvis du f.eks. Vil se på Microsoft C ++-kompilatoren, vil du opdage, at den vil bruge 32-bit int, uanset målprocessorarkitekturen (32-bit eller 64-bit), bare fordi folk plejede at tro at int er 32-bit!


Som summury kan vi se, at der er to datatyper familier - dword-baserede og int-baserede. Motivation til den anden er indlysende - applikationsudvikling på tværs af platformen. Motivation for den fisrt ene er alle tilfælde, når inddragelsen i akkaunt størrelserne af variabler har mening. For eksempel kan vi nævne følgende tilfælde:


1) Du skal have en vis værdi i forudbestemt velkendt område, og du skal bruge det i klasse eller i en anden datastruktur, der vil fylde i et stort antal tilfælde i løbetid. I så fald, hvis du vil bruge int-baserede typer til at gemme den værdi, vil den have ulempen i stor hukommelsestildeling på nogle arkitekturer og potentielt kan ødelægge logikken på en anden. For eksempel skal du manipulere værdier i området fra 0 til 1000000. Hvis du vil bruge int til at gemme det, vil dit program fungere korrekt, hvis int vil være 32-bit, vil have 4-byte hukommelses-overhead pr. vil være 64-bit og vil ikke fungere korrekt, hvis int vil være 16-bit.


2) Data involveret i nextworking. For at have mulighed for korrekt at håndtere din netværksprotokol på forskellige pc'er skal du angive det i almindeligt formatbaseret format, der beskriver alle pakker og overskrift bit for bit. Din netværkskommunikation vil blive fuldstændig brudt, hvis du på en pc vil have en protokolhoved på 20 byte med 32-bit, og på en anden pc vil den være 28 byte længde med 64-bit int.


3) Dit program skal gemme værdi, der anvendes til nogle specielle processorinstruktioner, eller dit program vil kommunikere med moduler eller kodebrikker skrevet i assembler.


4) Du har brug for butiksværdier, der bruges til at kommunikere med enheder. Hver enhed har sin egen specifikation, der beskriver, hvilken type inputenhed der kræves som input, og i hvilken form den vil give output. Hvis enheden kræver 16-bit værdier som input, skal den modtage lige 16-bit værdi uanset int størrelse og endog uanset maskinordstørrelse, der bruges af processor på systemet, hvor enheden er installeret.


5) Din algoritme er afhængig af heltalens overløbslogik. For eksempel har du en række af 2 ^ 16 poster, og du vil have infenitely og sequentely går igennem det og opdatere indtastningsværdier. Hvis du vil bruge 16-bit int vil dit program fungere perfekt, men når du flytter til 32-bit int-brugen, vil du have uden for rækkevidde array indeks adgang.


På grund af dette bruger Microsoft begge datatyper. Int-baserede typer, hvis den faktiske datastørrelse ikke har stor betydning og DWORD-baseret i de tilfælde, den har. Og selv i så fald definerer Microsoft både som makroer, for at give evnen hurtigt og nemt nok at anvende det virtuelle type system, der anvendes af Microsoft til den bestemte processorarkitektur og/eller compiler ved at tildele den korrekt C ++ -ækvivalent.


Jeg håber, at jeg har dækket spørgsmålet om datatypernes oprindelse og deres forskelle ganske godt.


Så vi kan skifte til seqond spørgsmålet om hvorfor hexademisk ciffer bruges til at betegne DWORD-baserede datatyper værdier. Der er faktisk få grunde:


1) Hvis vi bruger strengeformede binære datatyper, forventes det nok, at vi kan se på dem i binær form.


2) Det er meget nemt at forstå bitmasker værdier, når de kodes i binær form. Enig, at det er meget nemmere at understang, hvad der er angivet, og hvilken bit er nulstillet, hvis værdien i den næste formular


1100010001011001


Så hvis den bliver kodet i næste formular


50265


3) Data kodet i den binære form og beskrevet en DWORD-baseret værdi har konstant længde, når de samme data kodet i decimalformen vil have variabel længde. Bemærk, at selv når det lille nummer er kodet i binær form, gives den fulde værdi beskrivelse


0x00000100


i stedet for


0x100


Denne egenskab ved den binære kodning er meget attraktiv i tilfælde, hvor analysen af ​​den enorme mængde binære data er påkrævet. For eksempel hex-editor eller analyse af den almindelige hukommelse, der bruges af dit program i debugger, når dit breakpoint blev ramt. Enig, at det er meget mere komfortabelt at se på de pæne kolonner af værdier, der til bunken af ​​svagt tilpassede variable størrelsesværdier.


Så vi besluttede at bruge binær kodning. Vi har tre valg: Brug almindelig binær kodning, brug oktal kodning og brug hexadecimal kodning. Peple foretrækker at bruge hexademisk kodning, fordi den er kortest fra sæt af tilgængelige kodninger. Bare sammenlign


10010001101000101011001111000


og


0x1234568


Kan du hurtigt finde antallet af bits, der er angivet i den næste værdi?


00000000100000000000000000000


og i næste?


0x00100000


I det andet tilfælde kan du hurtigt opdele nummeret i fire adskilte byte


0x00 0x10 0x00 0x00
   3    2    1    0


i hvert af hvilke den første ciffer betegner 4 mest signifikante bits, og den anden angiver yderligere 4 mindst signifikante bits. Når du har brugt lidt tid på at arbejde med hex-værdier, vil du huske den enkle bitanalog af hvert hexadecimalt tal og vil erstatte en til en anden i sindet uden problemer:


0 - 0000  4 - 0100  8 - 1000  C - 1100
1 - 0001  5 - 0101  9 - 1001  D - 1101
2 - 0010  6 - 0110  A - 1010  E - 1110
3 - 0011  7 - 0111  B - 1011  F - 1111


Så, vi har kun brug for anden eller to at finde ud af, at vi har bit nummer 20 er indstillet!


Folk bruger hex, fordi det er mest kort, behageligt at undestand og bruger form for binær datakodning.