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

时间:2011-04-13 20:34:48

标签: c++ windows visual-c++ hex dword

我试图理解为什么在MSDN上的十六进制中经常描述DWORD值。

我之所以分析这个是因为我试图从根本上理解为什么存在所有这些不同数量的数据类型。一位当地导师向我提到,DWORD和其他微软类型的创建与处理器的发展有关。这为我理解这些数据类型提供了意义和背景。我想要更多背景和背景。

无论哪种方式,我都可以使用一些解释或一些资源来记住DWORD,无符号整数,字节,位,WORD等之间的区别。

总之,我的问题是: 1)为什么DWORD以十六进制表示? 2)您能否就数值数据类型之间的差异及其创建原因提供资源?

5 个答案:

答案 0 :(得分:9)

计算机中的所有内容都是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位游戏”。这就是我们所说的。该系统是围绕Bytes构建的。

然后计算机变得有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位寄存器。您通常可以在这样的cpu上运行32位或64位操作系统。

包括Bit,Byte,Word,Dword。这些是原始类型,经常用于标志,位掩码等。如果你想保留一个实际数字,最好使用有符号/无符号整数,长整数等。

我没有涵盖浮点数,但希望这有助于一般的想法。

答案 1 :(得分:4)

当DWORD常量用作可以按位方式一起进行OR运算的标志时,它们通常以十六进制写入。这样可以更容易地看到它。这就是为什么你看到0x01,0x02,0x04,0x08,0x10,0x20等等。程序员只是将这些值识别为只有一个位设置的二进制表示。

当它是一个枚举时,你会看到0x01,0x02,0x03等。它们通常仍然用十六进制编写,因为程序员往往会习惯这些习惯!

答案 2 :(得分:1)

仅仅为了记录,16位无符号数据被命名为WORD,因为当时计算机有16位寄存器。

在计算机历史记录中,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)。十六进制是一种更紧凑的方式来使用二进制文件并仍保留其中的一些属性。

答案 3 :(得分:0)

详细说明Tim的回答,这是因为将Hex转换为二进制并返回非常容易 - 每个Hex数字都是4位二进制数字:

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

所以,0x2D = 0010 1101

答案 4 :(得分:0)

你有一个非常有趣和棘手的问题。

简而言之,有两个驱动因素导致竞争类型系列的存在 - 基于DWORD和基于int:

1)希望一方面具有crosspltformity,另一方面具有严格的尺寸类型。

2)人民保守主义。

无论如何要为你提供详尽的答案以及这个领域的足够好的背景,我们必须深入研究计算机的历史。从计算的早期开始我们的故事。

首先,有一个机器词这样的概念。机器字是一个严格大小的二进制数据块,在特定处理器中处理是很自然的。因此,机器字的大小几乎不依赖于处理器,并且通常等于基本内部处理器寄存器的大小。通常它可以细分为两个相等的部分,处理器也可以将它们作为独立的数据块访问。例如,在x86处理器上,机器字大小为32位。这意味着所有通用寄存器(eax,ebx,ecx,edx,esi,edi,ebp,esp和eip)具有相同的大小 - 32位。但其中许多可以作为注册表的一部分进行访问。例如,您可以将eax作为32位数据块,ax,16位数据块或甚至8位数据块访问。但不是物理上这是一个32位寄存器。我认为你可以在维基百科上找到非常好的背景知识(http://en.wikipedia.org/wiki/Word_(computer_architecture))。简而言之,机器字是多少位数据块可以用作单个指令的整数操作数。即使在今天,不同的处理器架构也有不同的机器字大小。

好的,我们对计算机一词有所了解。现在是回归计算历史的时候了。第一款受欢迎的Intel x86处理器具有16位字长。它于1978年进入市场。那时汇编程序非常受欢迎,如果不是主要的编程语言。如您所知,汇编程序只是本机处理器语言下的一个非常薄的包装器。因此,它完全取决于硬件。当英特尔将新的8086处理器推向市场时,他们获得成功所需的第一件事就是将新处理器的推广器推向市场。没有人想要一个没人知道如何编程的处理器。当英特尔为8086的汇编程序提供了不同数据类型的名称时,它们会明确地选择并将16位数据块命名为一个字,因为8086的机器字具有16位大小。机器字的一半称为字节(8位),用作一个操作数的两个字称为双字(32位)。 英特尔在处理器手册和汇编程序助记符中使用了这些术语(db,dw和dd用于字节,字和双字的静态分配)。

多年过去了,1985年,随着80386处理器的推出,英特尔从16位架构转向32位架构。但当时有大量习惯于这个词的开发人员是一个16位的值。除此之外,还有大量的软件写着真正的相信,这个词是16位。许多已经编写的代码依赖于字是16位的事实。由于这个原因,除了实际更改了机器字大小这一事实外,符号保持不变,除了新数据类型到达汇编程序的事实 - 四字(64位),因为依赖于两台机器的指令单词保持不变,但机器字扩展了。同样,双四字(128位)现在采用64位AMD64架构。结果我们有

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

请注意,该类型系列的主要内容是它是强大的类型系列。因为它来自并且它在汇编程序中大量使用,所以它需要具有恒定大小的数据类型。注意,多年过去了一年,但这个家族的数据类型继续具有相同的常数大小,除了它的名称已经没有其原始含义。

另一方面,在同一时间,高级语言越来越受欢迎。而且因为这种语言是在脑海中通过跨平台应用开发的,所以从绝对的其他观点来看其内部数据类型的大小。如果我正确理解,没有一种高级语言没有明确声称它的某些内部数据类型具有固定的常量大小,以后永远不会改变。让我们看一下示例中的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具有执行环境的体系结构所建议的自然大小。这意味着int必须具有目标处理器体系结构的机器字大小。

你可以浏览所有C ++标准文本,但是你将找不到类似&#34的东西; int的大小是4字节"或"长度为64位"。特定整数C ++类型的大小可以随着从一个处理器体系结构移动到另一个处理器体系结构而从一个编译器移动到另但即使你用c ++编写程序,你也会定期遇到要求使用众所周知的常量大小的数据类型。

至少早期的编译器开发人员遵循该标准声明。但现在我们可以看到人们的保守主义再次进入剧中。人们过去认为int是32位,可以存储从-2,147,483,648到2,147,483,647的值。当业界通过16位和32位架构之间的边界时,早些时候。第二项索赔得到严格执行。当你使用C ++编译器创建16位程序时,编译器使用了16位大小的int,这是"自然大小"对于16位处理器,相反,当您使用另一个C ++编译器来创建32位程序但是来自相同的源代码时,编译器使用32位大小的int,即自然大小"适用于32位处理器。如今,如果您将查看Microsoft C ++编译器,您会发现它将使用32位int而不管目标处理器体系结构(32位或64位),因为人们过去认为int是32位!

作为总结,我们可以看到,有两种数据类型系列 - 基于dword和基于int。第二个动机很明显 - 跨平台应用程序开发。 fisrt one的动机是所有情况,当考虑到变量的大小有意义时。例如,我们可以提到下一个案例:

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个条目的数组,并且你想要infenitely和顺序通过它并刷新条目值。如果你将使用16位int,你的程序将完美地运行,但是你会移动到32位的int用法,你将超出范围数组索引访问。

由于此Microsoft使用两种数据类型系列。在实际数据大小不重要的情况下基于Int的类型,并且在它具有的情况下基于DWORD。即使在这种情况下,Microsoft也将两者都定义为宏,通过为特定的处理器体系结构和/或编译器分配正确的C ++等价物,可以快速,轻松地提供使用虚拟类型系统的能力。

我希望我已经很好地讨论了数据类型的来源及其差异的问题。

因此,我们可以切换到关于为什么使用十六进制数字来表示基于DWORD的数据类型值的seqond问题。实际上没有什么理由:

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位!

人们使用十六进制,因为它最短,很容易解决并使用二进制数据编码形式。