- ベストアンサー
x64プログラムでアドレスが32bitになる理由
- x64プログラムにおいて、アドレスが32bitになる理由について説明します。
- 64bitOSで4GBを超えるメモリを使いたい場合やWin32APIにポインタを渡したい場合の技術についても考えています。
- しかし、具体的な理解ができないため、詳しい方に教えていただきたいと思っています。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
lea や call のアドレス指定において 33ビット目の 1 が落ちているのは, おそらく 冗長な情報だから だと思います. 命令フォーマットの都合上, ここの 4000B000h は 14000B000h しかありえません.
その他の回答 (4)
- chie65536(@chie65535)
- ベストアンサー率44% (8755/19865)
>調べてみたところ、HWNDは構造体へのポインタらしいのですが >その構造体の実体をOSが管理しているのならば、メモリのどこかにまとめられているから大丈夫なのかもしれませんね。 64ビットの動作環境に対応したコンパイラなら、ポインタに near * far * など「アドレスが何ビットのポインタなのか?」を修飾する、オプションの修飾子がある筈です。 たぶん、HWNDは「32ビットアドレスのポインタ」として定義されていると思われます。 もちろん、通常のポインタ(オプションの修飾子が無いポインタ)は、64ビットのポインタになると思います。
お礼
ご指摘ありがとうございます!勉強不足でした。 行き違いで回答を締めきってしまいましたが、あとは専門書探して勉強してみようと思います。 ありがとうございまいsた。
- chie65536(@chie65535)
- ベストアンサー率44% (8755/19865)
>1つ疑問がありますが、r9dはr9の下位32bitのことですね?NULLで下位32bitのみをゼロにしても大丈夫でしょうか? NULLに指定しているパラメータはHWND型だから、多分「OS管理のウィンドゥハンドルは下位32ビットのみ有効で、上位32ビットは無視される」っていう仕様になっているんじゃないかな? 詳しく調べてないから判らないけど、ウィンドゥハンドルの実体って、常にOSが管理するメモリの上に居るから、そこを指すポインタって、常に上位32ビットが固定になると思います。上位32ビットが固定なら「上位32ビットは要らない」ですよね?
お礼
調べてみたところ、HWNDは構造体へのポインタらしいのですが その構造体の実体をOSが管理しているのならば、メモリのどこかにまとめられているから大丈夫なのかもしれませんね。 先ほどのLEA33ビット目以降についてIntel資料のLEA項目に以下の記述がありました。 (Operand Size 32、Address Size 64の場合) >64-bit effective address is calculated (default address size) and the lower 32 bits of the >address are stored in the requested 32-bit register destination. 今回の結果も考慮すると、64bitの実効アドレスが計算された後、下位32bitが埋められるかもしれません。 解決しました!皆様ありがとうございます。 これからさらに勉強していきます。
- chie65536(@chie65535)
- ベストアンサー率44% (8755/19865)
>このうち、最後から3行目のxor(NULLに該当するところ)がecxになっている理由が分かりません。rcxではないのでしょうか? NULLは、一番最初の xor r9d,r9d だよ。 xor ecx,ecx は「MB_OK」だよ。 MB_OKの引数は「UINT」だから、32ビットで0クリアすれば問題無し。 >エントリーポイントも140000000のはずなのに、leaの[4000B008h]では33bit目の1が抜けています。 命令のオペランドを良く見て下さい。 lea r8,4000B000h ではなくて lea r8,[4000B000h] だよね? lea r8,[4000B000h] は「4000B000番地に格納されている64bitアドレスのアドレスをr8に入れろ」です。 この時に参照される4000B000番地は、セグメントレジスタにより64bit拡張されます。 4000B000~4000B007の8バイトに、64ビットのアドレスが入っているから、その次の命令は lea rdx,[4000B008h] のように「8バイト先」になってます。 >戻り値もeaxなのが気になります。 MessageBoxの戻り値は「int」です。 「64ビット環境でも、intの大きさが32ビットなら、戻り値も32ビット」ですよ。 戻り値が32ビットなら、eaxで問題ありません。 sizeof(int)ってやったら、4になりますよね?8ではなく。 だから、NULLはちゃんと64ビットでNULLになってるし、他の文字列も64ビットで渡されてる。何も問題無し。
補足
分かりやすい説明、ありがとうございます! 引数の順番について、STDCALLに慣れすぎてまた混合してしまいました。すみません。 1つ疑問がありますが、r9dはr9の下位32bitのことですね?NULLで下位32bitのみをゼロにしても大丈夫でしょうか?
- lupin-333333
- ベストアンサー率31% (294/933)
これって http://msdn.microsoft.com/ja-jp/library/ms173505(v=vs.90).aspx をしたと言う事ですか? それともデータ形で64bit の指定という話ですか? http://msdn.microsoft.com/ja-jp/library/7kcdt6fy(v=vs.90).aspx にその説明があるようですが・・
補足
混乱してしまったようで申し訳ないです。 下のURIの「イメージ形式」によると >実行可能イメージの形式は、PE32+ です。 >実行可能イメージ (DLL、EXE の両方) は、最大 2 GB までに制限されるため、静的イメージ データをアドレス指定するには 32 ビットの変位による相対アドレス指定を使用できます。 >このデータには、インポート アドレス テーブル、文字列定数、静的なグローバル データなどが含まれます。 とのことですが、 ・最大 2 GBというのは実行可能イメージのファイルとしての物理的なサイズで、確保できる物理メモリのサイズとは関係ない →当然仮想メモリは物理メモリ以上の量を予約できる →仮想メモリはファイルサイズに関係なく 2 GBや 4 GBを超える量を自由に予約できるのでは? →ということはRVAが 32 bitを超えることも有り得るのでは? →そのことを考慮すると、RCXではなくECXを渡すのは問題あるのでは?leaについても同様 と考えましたら分からなくなったのです。この考えのどこかに間違いがあるのでは。 もし 2 GBがヒープ領域を除く仮想メモリの最大サイズだとしても、mallocなどで返される64ビットポインタを関数に渡すときに問題が起こるのでは?と。 コマンドラインには、以下を入力しました。cl.exe、dumpbin.exeは、amd64フォルダのものを使用しました。 user32.libはWindows Kits内のものです。 cl test64.c /link /defaultlib:user32.lib dumpbin test64.exe /disasm
補足
確かにcaptionが7文字なのでNULLのことを考えると先ほど説明を頂きました8バイトと一致しましたので、 MessageBox (NULL, "Message", "Caption Title", MB_OK); としてコンパイルすると、本当に以下のように変わりました。 0000000140001007: 4C 8D 05 F2 9F 00 lea r8,[4000B000h] 00 000000014000100E: 48 8D 15 FB 9F 00 lea rdx,[4000B010h] 00 冗長な情報というのは、leaニモニックにおいて、33~64ビット目が一致している領域間でのやり取りには 32ビットオペランドを指定することで、これを省略することができるということでしょうか? 先ほどNo.2の補足に書いたNULLはxorですが、これについてはどうなるのでしょうか? 追伸:エントリーポイントは140001000でしたm(__)m 140000000はイメージベースでした