为什么DWORD值通常用十六进制表示?

问题描述

| 我试图理解为什么在MSDN上的十六进制中经常描述DWORD值。 我之所以进行分析,是因为我试图从根本上理解为什么所有这些不同的数字数据类型都存在。一位本地导师向我暗示,DWORD和其他Microsoft类型的创建与处理器的发展有关。这为我对这些数据类型的理解提供了意义和上下文。我想要更多的背景信息。 无论哪种方式,我都可以使用一些解释或一些资源来记住DWORD,无符号整数,字节,位,WORD等之间的区别。 总而言之,我的问题是: 1)为什么用十六进制表示DWORD? 2)您能否提供有关数值数据类型之间的差异以及为什么创建它们的资源?     

解决方法

计算机中的所有内容都是一堆0和1。但是用二进制代码编写整个DWORD非常繁琐:
00000000 11111111 00000000 11111111
为了节省空间并提高可读性,我们喜欢用较短的形式编写它。十进制是我们最熟悉的,但是不能很好地映射到二进制。八进制和十六进制映射非常方便,与二进制位完全对齐:
// 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
由于十六进制与8位字节非常好地对齐(2个十六进制数字构成一个字节),因此符号被卡住了,而这正是使用最多的方式。当与位掩码混淆时,它更易于阅读,更易于理解,更易于排队。 标识正在使用哪个碱基的通常速记:
  1234543 = decimal
 01234543 = octal (leading zero)
0x1234543 = hexadecimal (starts with 0x)
至于您关于BYTE,WORD,DWORD等的问题... 电脑从一点开始。只有1或0。他在原始Tron中有一个客串。 字节长8位(好一次,曾经有7位字节,但是我们可以忽略那些字节)。这样一来,您可以使用0-255之间的数字,也可以使用-128至127之间的带符号的数字。比1/0更好,但仍然受到限制。您可能已经听说过有关“ 8位游戏”的信息。这就是我们所指的。该系统是围绕字节构建的。 然后计算机发展为具有16位寄存器。这是2个字节,被称为WORD(不,我不知道为什么)。现在,数字可能是0-65535或-32768到32767。 我们继续希望获得更多功能,并且计算机已扩展到32位寄存器。 4字节2字,也称为DWORD(双字)。到目前为止,您可以在\“ C:\\ Windows \”中查找\“ system \”(旧的16位元)和\“ system32 \”(新的32位元)的目录。 然后是QWORD(四字)。 4个字,8个字节,64位。听说过Nintendo-64吗?这就是名字的来历。现在是现代建筑。 cpu的内部包含64位寄存器。通常,您可以在此类cpus上运行32位或64位操作系统。 涵盖了位,字节,字,双字。这些是原始类型,通常用于标志,位掩码等。如果要保留实际数字,最好使用有符号/无符号整数,长整数等。 我没有介绍浮点数,但是希望这对总体思路有所帮助。     ,当DWORD常量用作可以按位或运算符的标志时,通常以十六进制形式编写。这样更容易看出来。这就是为什么您看到0x01、0x02、0x04、0x08、0x10、0x20等的原因。程序员只是将这些值识别为仅具有单个位的二进制表示形式。 当它是枚举时,您会看到0x01、0x02、0x03等。由于程序员倾向于养成这些习惯,因此它们仍经常用十六进制编写!     ,仅出于记录目的,由于当时计算机具有16位寄存器,因此将16位无符号数据命名为WORD。 在计算机历史记录中,8位数据是您可以在寄存器中存储的最大数据。由于它可以存储一个ASCII字符,因此通常称为CHAR。 但是16位计算机问世了,CHAR不适合命名16位数据。 因此16位数据通常被称为WORD,因为它是您可以存储在一个寄存器中的最大数据单元,并且可以很好地延续为CHAR创建的数据。 因此,在某些计算机上,使用不同的CPU WORD通常指寄存器的大小。在Saturn CPU上,使用64位寄存器时,WORD为64位。 当32位x86处理器问世时,出于兼容性原因,WORD保留为16位,并且创建了DWORD以将其扩展为32位。 QWORD和64位也是如此。 至于为什么十六进制通常用于描述一个WORD,它必须与绑定到其寄存器来源的WORD定义的性质有关。在汇编程序中,您使用十六进制来描述数据,因为处理器仅知道binray整数(0和1)。十六进制是使用二进制文件并保留其某些属性的更紧凑的方法。     ,为了详细说明Tim的答案,这是因为将十六进制转换为二进制然后返回很容易-每个十六进制数字都是4个二进制数字:
0x1 = 0001
0x2 = 0010
...
0xD = 1101
0xE = 1110
0xF = 1111
因此,
0x2D
=
0010 1101
    ,您有一个非常有趣且棘手的问题。 简而言之,有两种驱动因素导致了竞争类型家族的存在-基于DWORD和基于int的: 1)一方面要具有交叉性,另一方面要有醒目的尺寸类型。 2)人民的保守主义。 无论如何要为您的问题提供充分的详细解答以及该领域足够好的背景知识,我们必须深入研究计算机的历史。并从计算的早期开始我们的故事。 首先,有一个像机器字这样的概念。机器字是大小庞大的二进制数据块,在特定处理器中自然可以处理。因此,机器字的大小几乎与处理器无关,并且通常等于通用内部处理器寄存器的大小。通常,它可以细分为两个相等的部分,处理器也可以将其作为独立的数据块进行访问。例如,在x86处理器上,机器字大小为32位。这意味着所有通用寄存器(eax,ebx,ecx,edx,esi,edi,ebp,esp和eip)都具有相同的大小-32位。但是其中许多可以作为寄存器的一部分进行访问。例如,您可以将eax作为32位数据块,ax作为16位数据块甚至8位数据块进行访问。但实际上并不是全部都是一个32位寄存器。我认为您可以在Wikipedia(http://en.wikipedia.org/wiki/Word_(computer_architecture))上找到该领域的很好背景。简而言之,机器字就是可以将多少位数据块用作单个指令的整数操作数。即使在今天,不同的处理器体系结构也具有不同的机器字大小。 好的,我们对计算机单词有所了解。现在是重新回到计算历史的时候了。第一个流行的Intel x86处理器具有16位字长。它于1978年问世。那时,汇编器(如果不是主要的编程语言)非常受欢迎。如您所知,汇编程序只是本机处理器语言下的一个非常薄的包装器。因此,它在很大程度上取决于硬件。当英特尔将新的8086处理器推向市场时,取得成功的第一件事就是将新处理器的组装者也推向市场。没有人想要一个没人会编程的处理器。当英特尔在8086的汇编器中为不同的数据类型提供名称时,它们会很明显地将chois命名为16位数据块,因为8086的机器字大小为16位。机器字的一半称为字节(8位),而用作一个操作数的两个字称为双字(32位)。 英特尔在处理器手册和汇编助记符中使用了这些术语(db,dw和dd dd用于字节,字和双字的静态分配)。 多年过去了,1985年,随着80386处理器的推出,英特尔从16位架构转变为32位架构。但是在那时,有大量的开发人员习惯了这个词是16位的值。字是16位的,除了真实的笔迹之外,还有大量的软件。许多已经编写的代码都依赖于单词为16位这一事实。因此,除了实际更改机器字长的事实外,符号保持不变,除了新数据类型到达汇编程序的事实-四字(64位),因为依赖于两台机器的指令单词保持不变,但是机器单词被扩展了。现在,采用64位AMD64架构的双四字(128位)以同样的方式出现。结果我们有
byte    =   8 bit
word    =  16 bit
dword   =  32 bit
qword   =  64 bit
dqword  = 128 bit
请注意,该类型族的主要之处在于它是大小较大的类型族。因为它来自并且在汇编程序中大量使用,所以需要具有恒定大小的数据类型。请注意,岁月流逝,但是这个族的数据类型继续具有相同的恒定大小,此外,其名称已经没有其原始含义。 另一方面,在逐年同一时间,高级语言变得越来越流行。而且由于该语言是在头脑中使用跨平台应用程序开发的,因此thay从绝对其他角度来看其内部数据类型的大小。如果我正确理解任何一种高级语言,都不会明确声称其某些内部数据类型具有固定的常量大小,以后再也不会更改。让我们不像示例那样看C ++。 C ++标准表明:
\"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.\"
因此,我们可以看到令人惊讶的信息-在C ++中,即使字节没有任何恒定大小。因此,即使我们习惯认为大小为8位,根据C ++,大小也可以是8位,也可以是9、10、11、12等位。甚至7位。
\"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.\"
该引用描述了两个主要主张: 1)sizeof(char)<= sizeof(short)<= sizeof(int)<= sizeof(long)<= sizeof(long long) 2)普通整数具有执行环境的体系结构建议的自然大小。这意味着int必须具有目标处理器体系结构的机器字大小。 您可以遍历所有C ++标准文本,但找不到诸如“ int的大小为4个字节”或“ long的长度为64位”之类的内容。特定整数C ++类型的大小可以随着从一种处理器体系结构转移到另一种处理器体系结构,以及从一种编译器转移到另一种编译器而改变。但是,即使当您使用C ++编写程序时,您也会定期面临使用众所周知的常量大小的数据类型的需求。 至少早期的编译器开发人员遵循该标准声明。但是现在我们可以看到人们的保守主义再一次出现了。人们以前认为int是32位的,并且可以存储从–2,147,483,648到2,647范围内的值。早些时候,行业经历了16位和32位体系结构之间的边界。第二项要求得到严格执行。而且,当您使用C ++编译器创建16位程序时,编译器使用16位大小的int(对于16位处理器为“自然大小”),相反,当您使用另一个C ++编译器创建32位时程序,但使用相同的源代码,编译器使用的int的32位大小为32位处理器的“自然大小”。如今,例如,如果您看一下Microsoft C ++编译器,您会发现它将使用32位int,而与目标处理器体系结构(32位或64位)无关,仅仅是因为人们曾经认为int是32位! 总而言之,我们可以看到thare是两种数据类型族-基于dword和基于int的。第二个方面的动机很明显-跨平台应用程序开发。首先考虑的动机是,在考虑变量大小的情况下才有意义。例如,我们可以提及以下几种情况: 1)您需要在预先定义的众所周知的范围内具有一定的价值,并且需要在类或其他数据结构中使用该值,这些数据结构将在运行时填充到大量实例中。在那种情况下,如果您将使用基于int的类型来存储该值,那么它将在某些体系结构上具有巨大的内存开销,并且可能会破坏另一种体系结构的逻辑。例如,您需要处理0到1000000之间的值。如果使用int来存储它,则如果int为32位,则程序将正确运行,如果int为每个值实例,则每个实例将有4字节的内存开销将为64位,如果int为16位,则将无法正常工作。 2)涉及下一个工作的数据。为了能够在不同PC上正确处理网络协议,您需要以基于大小的格式以纯格式指定它,该格式将逐位描述所有数据包和标头。如果一台PC上协议标头的长度为20字节(32位),而另一台PC上协议标头的长度为28字节(64位int),则网络通信将完全中断。 3)您的程序需要存储用于某些特殊处理器指令的值,否则您的程序将与用汇编器编写的模块或代码块进行通信。 4)您需要用于与设备通信的存储值。每个设备都有自己的规范,该规范描述了哪种输入设备需要作为输入,以及它将以哪种形式提供输出。如果设备要求16位值作为输入,则无论int大小,甚至与安装该设备的系统上的处理器使用的机器字大小无关,它都必须接收相等的16位值。 5)您的算法依赖于整数溢出逻辑。例如,您有2 ^ 16个条目的数组,并且想要连续地依次遍历并刷新条目值。如果您将使用16位int,则您的程序将可以完美运行,但是如果您直接使用32位int,则将无法使用数组索引。 因此,Microsoft使用这两种数据类型系列。在实际数据大小不太重要的情况下,基于Int的类型;在实际情况下,则基于DWORD。甚至在那种情况下,Microsoft都将它们定义为宏,以通过为其分配正确的C ++对等体来快速,轻松地为特定的处理器体系结构和/或编译器提供采用Microsoft使用的虚拟类型系统的能力。 我希望我已经很好地涵盖了有关数据类型的起源及其差异的问题。 因此,我们可以转到以下问题,即为什么使用十六进制数字来表示基于DWORD的数据类型值。实际上有几个原因: 1)如果我们使用大小惊人的二进制数据类型,则可以期望以二进制形式查看它们。 2)以二进制形式编码的位掩码值很容易理解。同意如果下一种形式的值加上下划线,则更容易划清设置的位和重置的位
1100010001011001
那么如果将其编码为下一种形式
50265
3)以二进制形式编码并描述了一个基于DWORD的值的数据具有恒定的长度,而以十进制形式编码的相同数据将具有可变的长度。请注意,即使小数以二进制形式编码,也会提供完整的值描述
0x00000100
代替
0x100
在需要分析大量二进制数据的情况下,二进制编码的此属性非常有吸引力。例如,当遇到断点时,十六进制编辑器或对调试器中程序所使用的普通内存的分析。同意在整洁的值列上查找比未对齐的可变大小值堆更舒服的方法。 因此,我们决定要使用二进制编码。我们有三个选择:使用纯二进制编码,使用八进制编码和使用十六进制编码。 Peple更喜欢使用十六进制编码,因为它比可用编码集最短。只是比较
10010001101000101011001111000
0x1234568
您能否快速找到下一个值中设置的位数?
00000000100000000000000000000
接下来呢?
0x00100000
在第二种情况下,您可以将数字快速分成四个独立的字节
0x00 0x10 0x00 0x00
   3    2    1    0
其中第一个数字表示4个最高有效位,第二个数字表示另外4个最低有效位。在花了一些时间处理十六进制值之后,您将记住每个十六进制数字的普通位模拟,并且在头脑中将彼此替换而没有任何问题:
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
因此,我们只需要一两秒钟就可以找到已设置的位数20! 人们使用十六进制是因为它最短,很容易理解和使用二进制数据编码形式。