はじめまして。
私は趣味でCPUや機械語の勉強をしているのですが、
非常に初歩的な部分でどうしても分からないことがあったので質問させて下さい。
WindowsのVisual C++ 64ビットコンパイラで
MessageBox(NULL, "message", "caption", MB_OK);
をコンパイルすると、以下のコードが出力されます。
0000000140001004: 45 33 C9 xor r9d,r9d
0000000140001007: 4C 8D 05 F2 9F 00 lea r8,[4000B000h]
00
000000014000100E: 48 8D 15 F3 9F 00 lea rdx,[4000B008h]
00
0000000140001015: 33 C9 xor ecx,ecx
0000000140001017: FF 15 F3 71 00 00 call qword ptr [40008210h]
000000014000101D: 33 C0 xor eax,eax
このうち、最後から3行目のxor(NULLに該当するところ)がecxになっている理由が分かりません。rcxではないのでしょうか?
戻り値もeaxなのが気になります。
他のパラメータも見ると、64bitのレジスタを使っているのはmessageとcaptionへのポインタのみで、それもleaに渡すRVAは32bitです。
エントリーポイントも140000000のはずなのに、leaの[4000B008h]では33bit目の1が抜けています。
64bitとは具体的にどこがどう64bitなのでしょうか?
それとも64bitOSになってもWin32APIはWin32APIのままなのでしょうか?
64bitOSで4GBを超えるメモリを使いたいときはどういう技術を使えばよいのでしょうか?Win32APIにそのポインタを渡したい時は?
実行ファイルのサイズは2GBまでということですが、全てのセクションが持てる仮想アドレス領域の合計も4GB以内に制限されているのでしょうか?
いろいろ調べ、考えてみましたが、納得の行く理解ができません。
浅学ですが、詳しい方がいましたら教えていただければ助かります。
よろしくお願い致します。
No.3ベストアンサー
- 回答日時:
lea や call のアドレス指定において 33ビット目の 1 が落ちているのは, おそらく
冗長な情報だから
だと思います.
命令フォーマットの都合上, ここの 4000B000h は 14000B000h しかありえません.
この回答への補足
確かに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はイメージベースでした
No.5
- 回答日時:
>調べてみたところ、HWNDは構造体へのポインタらしいのですが
>その構造体の実体をOSが管理しているのならば、メモリのどこかにまとめられているから大丈夫なのかもしれませんね。
64ビットの動作環境に対応したコンパイラなら、ポインタに
near *
far *
など「アドレスが何ビットのポインタなのか?」を修飾する、オプションの修飾子がある筈です。
たぶん、HWNDは「32ビットアドレスのポインタ」として定義されていると思われます。
もちろん、通常のポインタ(オプションの修飾子が無いポインタ)は、64ビットのポインタになると思います。
ご指摘ありがとうございます!勉強不足でした。
行き違いで回答を締めきってしまいましたが、あとは専門書探して勉強してみようと思います。
ありがとうございまいsた。
No.4
- 回答日時:
>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が埋められるかもしれません。
解決しました!皆様ありがとうございます。
これからさらに勉強していきます。
No.2
- 回答日時:
>このうち、最後から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のみをゼロにしても大丈夫でしょうか?
No.1
- 回答日時:
これって
http://msdn.microsoft.com/ja-jp/library/ms173505 …
をしたと言う事ですか? それともデータ形で64bit の指定という話ですか?
http://msdn.microsoft.com/ja-jp/library/7kcdt6fy …
にその説明があるようですが・・
この回答への補足
混乱してしまったようで申し訳ないです。
下の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
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Visual Basic(VBA) VBAでArrayListを使う為の「mscorlib.tlb」の参照設定について 3 2022/03/23 19:45
- その他(プログラミング・Web制作) Visual Studio Code 関数の使い方について 3 2023/05/31 13:15
- オンラインゲーム Valorantの最低・推奨スペックについて質問させてください。 2 2022/09/07 17:48
- Excel(エクセル) Excel 2019 32-bit版を64-bit版にするには? 8 2023/07/28 14:20
- C言語・C++・C# Cのオブジェクトファイルの逆アセンブル 5 2023/05/13 01:51
- TOEFL・TOEIC・英語検定 bitとlittleは両方ともに同じ 1 2022/08/10 13:03
- 英語 英文和訳についての質問です。 2 2023/06/23 06:38
- その他(プログラミング・Web制作) プログラムについて。 2 2022/04/07 18:48
- C言語・C++・C# 関数ポインタの高速化のメリット 7 2023/05/05 20:15
- 数学 「FFTの基本は、DFTはサンプル数Nが偶数なら 2つのDFTに分解できるということ。 分解するとD 3 2022/03/31 21:01
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
セグメントエラー
-
C言語のポインタに直接アドレス...
-
init関数の意味
-
fopne で失敗する原因
-
C言語でのconstを返す関数
-
c言語で任意のファイルから読み...
-
TCHAR文字列内の検索について
-
main(int argc,char **argv[])...
-
cv::Mat から vectorにコピー
-
構造体とfscanf
-
[C#] DeviceIoControlの変数の型
-
VB6でのgethostbyaddrの使用方...
-
bsearch関数の呼び出しで
-
ExcelVBAでのkernel32(64bit)
-
基本アルゴリズムの『返す』の...
-
ハンドルはポインタか
-
関数ポインタの利点
-
C++で関数ポインタから関数名を...
-
パスからファイル名を抽出
-
エラーの意味
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C言語のポインタに直接アドレス...
-
C言語の関数と配列に関する質問
-
戻り値で構造体を返すことは可...
-
fopne で失敗する原因
-
init関数の意味
-
Run-Time Check Failure #3とい...
-
LPSTR型の初期化について
-
セグメントエラー
-
アプリを32bitから64bit移行
-
コンストラクタでnewを失敗した...
-
ExcelVBAでのkernel32(64bit)
-
Cで作成したDLL関数をVBから呼...
-
ハンドルはポインタか
-
DLL<->VB間での受け渡し(文字...
-
C言語でのconstを返す関数
-
ポインタについて
-
参照型で受け取った引数をポイ...
-
TCHAR文字列内の検索について
-
デバイスハンドルとは?
-
基本アルゴリズムの『返す』の...
おすすめ情報