ポインター増分差B/W 32ビットおよび64ビット
-
28-09-2019 - |
質問
64ビットWin7(AMD64)で32ビットビスタ(x86)をコードしたドライバーを実行しようとしていましたが、実行されていませんでした。多くのデバッグとヒットとトライアルの後、私は後者で作業するようにしましたが、それが機能している理由はわかりません。これが私がしたことです:
多くの場所で、バッファポインターは一連の構造(異なる場所で異なる)を指し、それらを増やすために、このタイプのステートメントが使用されました。
ptr = (PVOID)((PCHAR)ptr + offset);
そしていくつかの場所で:
ptr = (PVOID)((ULONG)ptr + offset);
2番目のものはゴミを返していたので、私はそれらをすべて1番目に変更しました。しかし、2番目のドライバーに続いてネット上の多くのサンプルドライバーを見つけました。私の質問:
- これらのマクロはどこで定義されていますか(Googleはあまり役に立ちませんでした)?
- 私はすべてのP_マクロがポインターであることを理解しています、なぜポインターがウルングに投げ込まれたのですか?これは32ビットでどのように機能しますか?
- PCHEは明らかに環境に応じて幅を変化させます。このためのドキュメントを見つける場所を知っていますか?
解決
- それらはwinnt.hで定義する必要があります(彼らはSDKにあります; DDKを手元に持っていない)
- ウルングは長く署名されていません。 32ビットシステムでは、これがポインターのサイズです。したがって、ポインターは、損失なく前後にulongに変換できますが、64ビットシステム(値をキャストすると切り捨てられる場合)ではそうではありません。バイトベースのポインター算術を得るためにウルングに投げかけました(これは未定義の動作がありますが、あなたが知ったように)
- ポインター算術は常に基礎となるタイプの単位で機能します。これは、バイト算術に相当します
- すべてのCブックは、ポインター算術の正確なセマンティクスについて詳しく説明する必要があります。
他のヒント
このコードが64ビットで失敗した理由は、ulongへのポインターをキャストしているためです。 Ulongは32ビット値であり、64ビットのポインターは64ビット値です。したがって、Ulongキャストを使用するたびにポインターを切り捨てることになります。
PCHARが定義されていると仮定して、PCHARキャスト char *
明示的な数のバイト数でポインターを増分することを意図している場合は、問題ありません。
どちらのマクロも同じ意図を持っていますが、ポインターが32ビットより大きい場合、そのうちの1つだけが有効です。
ポインター算術はこのように機能します。あなたが持っている場合:
T *p;
そしてあなたはする:
p + n;
(ここでnは数字です)、pの値は n * sizeof(T)
.
具体的な例を与えるには、DWORDへのポインターがある場合は次のとおりです。
DWORD *pdw = &some_dword_in_memory;
そして、あなたはそれにそれを追加します:
pdw = pdw + 1;
次に、次のDWORDを指しています。アドレスPDWポイントが増加します sizeof(DWORD)
, 、つまり4バイト。
あなたが言及したマクロは、キャストを使用して、適用されるアドレスオフセットに異なる量を掛けていることです。これは通常、バイト(またはcharまたはvoid)バッファに渡された低レベルのコードでのみ行われますが、その内部のデータが実際に他のタイプであることを知っています。
ULONG
Windef.hでWindows SDKで定義されており、常に32ビットなので、64ビットのポインターをキャストするとき ULONG
ポインターを32ビットに切り捨てます。