サンク(Cの関数呼び出し)について その2
- Cの関数呼び出しは、アセンブリとして見るとどんなコードになっているのでしょうか?
- cb=(WNDPROC)VirtualAlloc(NULL,10+5 , MEM_COMMIT, PAGE_EXECUTE_READWRITE); char *b=(char*)cb; *b++= 0xC7; *b++= 0x05; *((int *)b)++=(int)(&callbackSelf); *((int *)b)++=(int)this; *b++= 0xE9; *((int *)b)= ((int)WndProcGate)-(4+(int)b); リンク先の79レス目のコードを一部抜粋致しました。 おそらくMOV命令からオブジェクトアドレス代入までが実行環境の切替か調整を行ってる部分と思うのですが、これらの値を入れる事で結果どういう作用があるのでしょうか?
- この疑問に関する内容の書籍なりサイトがございましたら、そちらも紹介して頂けるとありがたいです。
- ベストアンサー
サンク(Cの関数呼び出し)について その2
1. Cの関数呼び出しは、アセンブリとして見るとどんなコードになっているのでしょうか? 2. http://oshiete1.goo.ne.jp/qa5750174.html すみませんが、上記質問「サンク方式について」の続きとして質問させて頂きます。 http://mentai.2ch.net/prog/kako/957/957341074.html cb=(WNDPROC)VirtualAlloc(NULL,10+5 , MEM_COMMIT, PAGE_EXECUTE_READWRITE); char *b=(char*)cb; //コールバックゲートをこしらえる *b++= 0xC7; *b++= 0x05; //MOV [adr],xxxx *((int *)b)++=(int)(&callbackSelf); //メモリアドレス *((int *)b)++=(int)this; //オブジェクトアドレス *b++= 0xE9; //jump long xxxx *((int *)b)= ((int)WndProcGate)-(4+(int)b);//ジャンプ先 リンク先の79レス目のコードを一部抜粋致しました。 おそらくMOV命令からオブジェクトアドレス代入までが実行環境の切替か調整を行ってる部分と思うのですが、これらの値を入れる事で結果どういう作用があるのでしょうか? また、この疑問に関する内容の書籍なりサイトがございましたら、そちらも紹介して頂けるとありがたいです。
- sankaku197
- お礼率98% (84/85)
- C・C++・C#
- 回答数1
- ありがとう数2
- みんなの回答 (1)
- 専門家の回答
質問者が選んだベストアンサー
1. 適当なCのプログラムを逆アセンブルしてみるなり、Cコンパイラからアセンブリ言語のファイルを出力させたりして、ご自分で見てみればいいのでは? Windows用のVisualC++を使っている場合は > dumpbin /disasm FILENAME.obj とか > cl /FA /FaFILENAME.asm /c FILENAME.c とか。 2. そのcbから始まるアドレスに書き込まれたコードでやっていることは、 Win構造体のcallbackSelfメンバーに、thisオブジェクトのポインタを書き込む WndProcGate関数へジャンプする の2つです。 この状態でcbのアドレスを呼び出すと、WndProcGateを経由してWndProc関数が呼び出されます。 > これらの値を入れる事で結果どういう作用があるのでしょうか? makeClass()を呼んだときのthisによって、コールバックのときに実行されるWndProc()を切り替えられるようにしています。Winを継承してWndProc()をオーバーライドできるようにするための仕掛けのようです。 オブジェクト指向とかウィンドウプログラミングの知識がないと何のことだか分からないでしょう。
関連するQ&A
- VirtualAllocについて
このサイトでわからくなったので質問させていただきます。 http://mentai.2ch.net/prog/kako/957/957341074.html このサイトの79番目で void makeClass(char *WinClassName) { cb=(WNDPROC)VirtualAlloc(NULL,10+5 , MEM_COMMIT, PAGE_EXECUTE_READWRITE); char *b=(char*)cb; //コールバックゲートをこしらえる *b++= 0xC7; *b++= 0x05; //MOV [adr],xxxx *((int *)b)++=(int)(&callbackSelf); //メモリアドレス *((int *)b)++=(int)this; //オブジェクトアドレス *b++= 0xE9; //jump long xxxx *((int *)b)= ((int)WndProcGate)-(4+(int)b);//ジャンプ先 WNDCLASS wndclass= { 0/*CS_SAVEBITS*/ ,//UINT style; cb, //WNDPROC lpfnWndProc; 0,0, //int cbClsExtra,cbWndExtra; 0, //HANDLE hInstance; LoadIcon(NULL,IDI_APPLICATION),//HICON hIcon; LoadCursor(NULL,IDC_ARROW), //HCURSOR hCursor; (HBRUSH) GetStockObject(WHITE_BRUSH), //HBRUSH hbrBackground; NULL, //LPCTSTR lpszMenuName; WinClassName, }; //LPCTSTR lpszClassName; RegisterClass( &wndclass ); } の、 cb=(WNDPROC)VirtualAlloc(NULL,10+5 , MEM_COMMIT, PAGE_EXECUTE_READWRITE); char *b=(char*)cb; //コールバックゲートをこしらえる *b++= 0xC7; *b++= 0x05; //MOV [adr],xxxx *((int *)b)++=(int)(&callbackSelf); //メモリアドレス *((int *)b)++=(int)this; //オブジェクトアドレス *b++= 0xE9; //jump long xxxx *((int *)b)= ((int)WndProcGate)-(4+(int)b);//ジャンプ先 の処理がどういう処理を行っているのかわからないので1つ1つわかりやすくご教授ください。
- ベストアンサー
- C・C++・C#
- C++DLLからC#へのコールバックに文字列の配列を渡したい
教えてください! C++のアンマネージドDLLから、複数のファイル名(文字列)をC#に渡したいです。 ステップとしては、 C#から、C++のDLLの関数を最初に呼んで、コールバック関数を渡しています。 次に、DLLからコールバック関数を呼ぶ時に、複数のファイル名を渡したいです。 以下のコードを動かすと、、 C++からは2つ渡しているつもりなのに、 C#ではfilesがサイズ1のString配列として引数に入ってきます。 なぜでしょう? またどうすればC#から複数受け取れるでしょうか? 教えてください! C# public delegate int StringArrayCallback(String[] files); // C# -> C++ public static int start() { StringArrayCallback cb = new StringArrayCallback(onReceivedFiles); int ret = start(cb); return ret; } // C++ -> C# callback public static int onReceivedFiles(String[] files) { return 1; } C++コード typedef int (__stdcall *OnReceivedFilesProc )(char**); int start( OnReceivedFilesProc callback ) { std::string message1_ = "from C++1"; std::string message2_ = "from C++2"; char* messages_[2] = { (char*)message1_.c_str(), (char*)message2_.c_str() }; int ret_ = callback(messages_); std::cout << "[from c#]" << ret_; }
- ベストアンサー
- C・C++・C#
- strcpy関数で文字型変数へのポインタを指定するとエラーになる
(1)のコードは問題なく動作するのですが、(2)の方はバスエラーとなります。どちらもも引数としてアドレスを渡しているのに何が違うのでしょうか? (1) char ch[]="aaaa"; strcpy(ch, "bbbb"); printf("%s\n", ch); (2) char *chp="xxxx"; strcpy(chp, "yyyy"); printf("%s\n", chp);
- ベストアンサー
- C・C++・C#
- C言語で文字列をかえす正しい書き方が知りたいです?
C言語で次の警告が表示されます。 文字列を返したいのですが、正しい書き方はどのようにすれば良いのでしょうか? jci.h(20) : warning C4172; ローカル変数またはテンポラリのアドレスを返します。 char *test(char *a, int b) { char str[BUFSIZ]; return str; <------ }
- ベストアンサー
- C・C++・C#
- javaのhashtableに関する質問です
以前にも質問させていただいた者ですが、またどなたかよろしくお願いします。 javaのhashtableを使いたいのですが、ソースコードの中で int a[]= char b[]= Hashtable<int,char> hash=new Hashtable<int,char>(); ~ hash.put(int[a],char[b]); と、put(,)の中にint型とchar型の配列を格納することは可能でしょうか?どうしてもエラーが出てしまいます。 どうしたらいいのでしょうか?
- 締切済み
- Java
- 関数の戻り値なんですが...
VC++を使用し以下のような関数additionで文字列を返したいのですが アドレスしか返しません。配列はその先頭のポインタだということは しっているのですが.... additionは、二つの文字列(32や47などの数字のやつ)を引数とし、そ れを整数型に変換し、その加算を行い、その結果を文字列型に変換し 、その文字列をかえす関数です。 関数の定義などが間違っているのですか?? #include<iostream.h> #include<string.h> #include<string> char *addition(char *,char *); void main(){ using namespace std; char a[] = "1000"; char b[] = "456"; cout << addition(a,b) << '\n'; } char *addition(char *a,char *b){ int c = 0; c = atoi(a)+atoi(b); char p[20]; _itoa(c,p,10); cout << p <<'\n'; return (*p); }
- ベストアンサー
- C・C++・C#
- isalpha()関数について
isalpha()関数について ◆開発環境 OS:Linux(Ubuntu9.10) コンパイラ:gcc4.4 IDE:eclipse 言語:C 《質問内容》 現在、char型配列A[8](最大8桁の文字列が格納されるため)に英字から始まる文字列(英字・数字)を入力し、 2文字目の文字を英字かどうか判別し、if文で分岐させようとしているのですが、 この2文字目の文字をisalpha()にかけても、英字と判別せず、思い通りの処理ができない状態で 困っています。 現状、以下のソースですと、"D0"ならelse ifに入りますが、"SM0"と入れるとifに入らずに、else ifに入ってしまいます。(2文字目は英字なのに…) 以下に、参考ソースを添付します。 どなたか、お分かりの方いらっしゃいましたら、ご教授お願いします。 できれば、isalphaの使い方等も詳しく教えていただけたら幸いです。(webで調べるとisalpha(int c)と書いてあり、文字の判別にint?とかなり疑問です。一応、ソース上ではchar型にキャストしてますが。) 《ソース》 char A[9]=""; //最大8桁の文字列(英字・数字)が入る char B[3]=""; //A,B入れ替え用バッファ char C[7]=""; //最大6桁の文字列(数字)が入る char code[2]=""; //判別用バッファ int C_val; //Cの10進値格納変数(後で使う) fscanf(stdin,"%s",&A); strncpy(code,,A+1,1); //code[2]に"0"をコピー if( (unsigned char)isalpha(code) != 0){ //codeが英字なら先頭2文字は英字 strncpy(B,A,2); strncpy(C,A+2,strlen(A)-2); C_val=atoi(C); //Cの10進化 strcpy(A,""); //Aの初期化 strcpy(A,B); strcpy(B,""); //Bの初期化 } else if( (unsigned char)isalpha(code) == 0){ //codeが英字でないなら先頭1文字が英字 strncpy(B,A,1); strncpy(C,A+1,strlen(A)-1); C_val=atoi(C); //Cの10進化 strcpy(A,""); //Aの初期化 strcpy(A,B); strcpy(B,""); //Bの初期化 }
- ベストアンサー
- C・C++・C#
- アセンブラ、ファンクションコールの使い方
入力した一文字を改行して表示させるものを作ってます。 以下のものを書いてみまして、 一文字読み取って改行はしますが表示されません。 アドバイス頂けますでしょうか? 環境は MASM 32 です。 name double .model small .stack 100 .data prompt db 0ah,0dh,"? $" .code start: mov ax, @data mov ds, ax lea dx, prompt mov ah, 9 ;output string int 21h mov ah, 1 ;get keyboard input and store into al int 21h mov dl, 0ah mov ah, 2 int 21h mov dl, 0dh mov ah, 2 int 21h mov dl, al mov ah, 2 ;output char from dl int 21h mov ax, 4c00h ;exit int 21h end start
- ベストアンサー
- その他(プログラミング・開発)
- C言語で型汎用性のある関数を作成したい
C言語です。 下記のコードでは、期待した通りにメンバにアクセスできるのですが、 構造体のメンバが多くなったとき、構造体をネストしているときには、 挙動がおかしく(なにか別の値をとりだしてしまっている?)なります。 どのようにしたら型汎用のある関数を書くことができるでしょうか? (C++ならば、汎用(テンプレート)関数があるけれども。。。) #include <stdio.h> struct hanyo{ int i; }; struct aaa{ int i; long l; char str[100]; }; struct bbb{ int i; }; void hoge(hanyo *ph){ printf("%d\n", ph->i); return; } int main(){ aaa a; a.i = 1; bbb b; b.i = 2; hoge((hanyo *)&a); hoge((hanyo *)&b); return 0; } ----実行結果---- 1 2 続行するには何かキーを押してください . . .
- ベストアンサー
- C・C++・C#
- c言語の問題
以下のプログラムをコンパイルし、実行したところ、次のような画面が表示された。下記の関数定義部分を補いなさい。 gcc test.c ./a.out abc def answer = defabc 以下ソースコード #include<stdio.h> void stradd(char A[], char B[]); int main(){ char str1[100], str2[100]; scanf("%s", str1); scanf("%s", str2); stradd(str1, str2); printf("answer = %s\n", str2); } void stradd(char A[], char B[]){ } よろしくお願いします。
- ベストアンサー
- その他([技術者向] コンピューター)
お礼
ありがとうございます。 dumpbinとclの事は知らなかったのですが、これ本当に便利ですね。 おかげさまで疑問のほとんどがclだけで解決しました。 以下、参考にしたサイトを載せておきます。 [起動方法] http://d.hatena.ne.jp/uox/20080302/p2 [dumpbin] http://d.hatena.ne.jp/language_and_engineering/20081008/1223384382 http://www.xlsoft.com/jp/products/intel/cvf/docs/vf-html/pg/pg26_10_02.htm [cl] http://besky-works.spaces.live.com/Blog/cns!555CF2E2F9E31C71!499.entry http://msdn.microsoft.com/ja-jp/library/367y26c6(VS.80).aspx >makeClass()を呼んだときのthisによって、コールバックのときに実行されるWndProc()を切り替えられるようにしています。Winを継承してWndProc()をオーバーライドできるようにするための仕掛けのようです。 ところで、これってサンクを応用しなくても以下のコードで十分なような気がします。 makeClass()のような実装にするのは、何か意味があるのでしょうか? class A{ public: A(){ callback = this; } virtual void CallBack(){ cout << "A" << endl; } static void CallBackGate(){ callback->CallBack(); } static A* callback; }; A* A::callback;
補足
改めてsalsberryさん、回答ありがとうございました。 もう新しい回答もなさそうなので、自分なりの結論を書いて締めようと思います。 マシンコードを直接打ち込む方法は面白く大変勉強になりました。 でも使う分には、やっぱり私の書いたコードで十分ですね。多分。