指针增量差异b / w 32位和64位

时间:2010-11-25 13:04:31

标签: winapi 32bit-64bit wdk

我试图在64位win7(amd64)上运行一些编码为32位vista(x86)的驱动程序,但它没有运行。经过大量的调试和试用后,我让它在后者上工作,但我不知道它工作的原因。这就是我所做的:

在许多地方,缓冲区指针指向一个结构数组(在不同的地方不同),并且为了递增它们,在某些地方使用了这种类型的语句:

ptr = (PVOID)((PCHAR)ptr + offset);

在某些地方:

ptr = (PVOID)((ULONG)ptr + offset);

第二个回垃圾,所以我把它们全部改成了第一个。但是在第二个网络之后我在网上发现了许多样本驱动程序。我的问题:

  1. 这些宏在哪里? 定义(谷歌没有多大帮助)?
  2. 我理解所有P_宏都是 指针,为什么是一个指针铸造 到ULONG?这是如何工作的 32位?
  3. PCHAR明显改变了 宽度根据环境。你知道在哪里找到这方面的文件吗?

3 个答案:

答案 0 :(得分:3)

  1. 它们应该在WinNT.h中定义(它们在SDK中;没有DDK)
  2. ULONG签名长;在32位系统上,这是指针的大小。所以一个指针 可以在不丢失的情况下来回转换为ULONG - 但在64位系统上则不然 (在这里投射值将截断它)。人们转向ULONG以获得基于字节的指针 算术(即使这有未定义的行为,正如你所发现的那样)
  3. 指针算法始终以基础类型为单位工作,即在PCHAR的CHAR中;这相当于字节算术
  4. 任何C书都应该详细说明指针算术的精确语义。

答案 1 :(得分:3)

此代码在64位上失败的原因是它将指针转换为ULONG。 ULONG是32位值,而64位指针是64位值。因此,只要您使用ULONG演员,就会截断指针。

假设PCHAR被定义为char *,PCHAR强制转换是正常的,前提是要将指针递增一个明确的字节数。

两个宏具有相同的意图,但只有其中一个在指针大于32位的情况下有效。

指针算法就像这样工作。如果你有:

T *p;

你做了:

p + n;

(其中n是数字),那么p的值将改变n * sizeof(T)

举一个具体的例子,如果你有一个指向DWORD的指针:

DWORD *pdw = &some_dword_in_memory;

并添加一个:

pdw = pdw + 1;

然后你将指向下一个DWORD。 pdw指向的地址将增加sizeof(DWORD),即4个字节。

您提到的宏使用强制转换来使它们应用的地址偏移量乘以不同的数量。这通常只在低级代码中完成,该代码已经传递了BYTE(或char或void)缓冲区,但知道其中的数据实际上是其他类型。

答案 2 :(得分:1)

ULONG在Windows SDK的WinDef.h中定义,并且始终为32位,因此当您将64位指针强制转换为ULONG时,会将指针截断为32位。