32 位和 64 位的指针增量黑白差异

发布于 2024-10-04 13:24:28 字数 522 浏览 9 评论 0原文

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

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

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

在某些地方:

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

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

  1. 这些宏在哪里 定义(谷歌没有多大帮助)?
  2. 我明白所有的 P_ 宏都是 指针,为什么要强制转换指针 去乌龙?这是如何运作的 32 位?
  3. PCHAR 显然改变了 宽度根据环境而定。您知道在哪里可以找到这方面的文档吗?

I was trying to run some drivers coded for 32-bit vista (x86) on 64-bit win7 (amd64) and it was not running. After a lot of debugging, and hit-and-trial, I made it to work on the latter, but I don't know the reason why it's working. This is what I did:

At many places, buffer pointers pointed to an array of structures(different at different places), and to increment them, at some places this type of statement was used:

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

And at some places:

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

The 2nd one was returning garbage, so I changed them all to 1st one. But I found many sample drivers on the net following the second one. My questions:

  1. Where are these macros
    defined(google didn't help much)?
  2. I understand all the P_ macros are
    pointers, why was a pointer casted
    to ULONG? How does this work on
    32-bit?
  3. PCHAR obviously changes the
    width according to the environment. Do you know any place to find documentation for this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

逆光飞翔i 2024-10-11 13:24:28
  1. 它们应该在 WinNT.h 中定义(它们在 SDK 中;手头没有 DDK)
  2. ULONG 是 unsigned long;在 32 位系统上,这是指针的大小。所以一个指针
    可以无损地来回转换为 ULONG - 但在 64 位系统上则不然
    (其中转换值将截断它)。人们强制转换为 ULONG 来获取字节基指针
    算术(即使这有未定义的行为,正如您所发现的)
  3. 指针算术始终以基础类型为单位工作,即在 PCHAR 的 CHAR 中;这相当于字节算术
  4. 任何 C 书籍都应该详细说明指针算术的精确语义。
  1. they should be defined in WinNT.h (they are in the SDK; don't have the DDK at hand)
  2. ULONG is unsigned long; on a 32-bit system, this is the size of a pointer. So a pointer
    can be converted back and forth to ULONG without loss - but not so on a 64-bit system
    (where casting the value will truncate it). People cast to ULONG to get byte-base pointer
    arithmetic (even though this has undefined behavior, as you found out)
  3. Pointer arithmetic always works in units of the underlying type, i.e. in CHARs for PCHAR; this equates to bytes arithmetic
  4. Any C book should elaborate on the precise semantics of pointer arithmetic.
少年亿悲伤 2024-10-11 13:24:28

此代码在 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;

,并向它添加 1:

pdw = pdw + 1;

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

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

The reason this code fails on 64-bit is that it is casting pointers to ULONG. ULONG is a 32-bit value while pointers on 64-bit are 64-bit values. So you will be truncating the pointer whenever you use the ULONG cast.

The PCHAR cast, assuming PCHAR is defined as char * is fine, provided the intention is to increment the pointer by an explicit number of bytes.

Both macros have the same intention but only one of them is valid where pointers are larger than 32-bits.

Pointer arithmetic works like this. If you have:

T *p;

and you do:

p + n;

(where n is a number), then the value of p will change by n * sizeof(T).

To give a concrete example, if you have a pointer to a DWORD:

DWORD *pdw = &some_dword_in_memory;

and you add one to it:

pdw = pdw + 1;

then you will be pointing to the next DWORD. The address pdw points to will have increased by sizeof(DWORD), i.e. 4 bytes.

The macros you mention are using casts to cause the address offsets they apply to be multiplied by different amounts. This is normally only done in low-level code which has been passed a BYTE (or char or void) buffer but knows the data inside it is really some other type.

单身情人 2024-10-11 13:24:28

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

ULONG is defined in WinDef.h in Windows SDK and is always 32-bit, so when you cast a 64-bit pointer into ULONG you truncate the pointer to 32 bits.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文