<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Verständnisproblem bei Thunks...]]></title><description><![CDATA[<p>Wie manche Fortgeschrittene von euch bestimmt wissen, gibt es einen Programmier-Trick um CALLBACK-Funktionen in eine Klasse zu bringen. Ich bin dabei auf zwei Versionen dieses Tricks gestoßen:</p>
<p>Als Beispiel will ich eine WNDPROC Funktion in meine Klasse kapseln. Man kann den Thunk so setzen, dass er <strong>entweder</strong> den HWND Parameter auf dem Stack modifiziert und zu einer statischen Memberfunktion springt (in der dann der HWND Parameter zum this-Zeiger gecastet wird und schließlich die gewünschte Memberfunktion der Klasse aufgerufen werden kann), <strong>oder</strong> dass er den this-Zeiger zusätzlich auf den Stack legt und gleich zur gewünschten Memberfunktion springt.</p>
<p>Erstere Version (von Codeproject):</p>
<pre><code class="language-cpp">void Init(F2 proc, T1 * pClass) // ist ein template
    {
        //make sure that 'this' is in ecx pointer
        // otherwsie code does not work
#ifdef _DEBUG
        long  pthis;
        _asm  { mov         dword ptr [pthis],ecx }; 
        assert(pthis == (long) this);
#endif
        // put values
        thunk.m_movcx = 0xB9;  //B9
        thunk.m_pThis= (DWORD)pClass;
        thunk.m_jmp = 0xE9;
        thunk.m_relproc = *((int *) &amp;proc) - ((int)this+sizeof(_ProcThunk));

        // write block from data cache and 
        // flush from instruction cache
        FlushInstructionCache(GetCurrentProcess(), 
            &amp;thunk, sizeof(thunk));
    }
</code></pre>
<p>Letztere Version (<a href="http://staff.develop.com/onion/Articles/cpprep0399.htm" rel="nofollow">http://staff.develop.com/onion/Articles/cpprep0399.htm</a>):</p>
<pre><code class="language-cpp">void Init(WNDPROC proc, void* pThis)
	{
		thunk.m_mov       = 0x042444c7;     // mov dword ptr [esp+0x4], pThis
		thunk.m_this      = (DWORD)pThis;   //HWND durch pThis ersetzen
		thunk.m_jmp       = 0xe9;           // jmp WndProc
		thunk.m_relproc   = (int)proc - ((int)this+sizeof(_WndProcThunk));	// Relative jmp
	}
</code></pre>
<p>Ich hoffe, dass ich das Prinzip soweit verstanden habe (gegebenenfalls bitte ausbessern falls unrichtig). Nun möchte ich darum bitten, dass mir jemand die &quot;Formel&quot; für m_relproc erklärt. Die begreife ich nämlich nicht so ganz.</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/69165/verständnisproblem-bei-thunks</link><generator>RSS for Node</generator><lastBuildDate>Wed, 08 Apr 2026 20:31:08 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/69165.rss" rel="self" type="application/rss+xml"/><pubDate>Wed, 24 Mar 2004 21:32:51 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Verständnisproblem bei Thunks... on Wed, 24 Mar 2004 21:32:51 GMT]]></title><description><![CDATA[<p>Wie manche Fortgeschrittene von euch bestimmt wissen, gibt es einen Programmier-Trick um CALLBACK-Funktionen in eine Klasse zu bringen. Ich bin dabei auf zwei Versionen dieses Tricks gestoßen:</p>
<p>Als Beispiel will ich eine WNDPROC Funktion in meine Klasse kapseln. Man kann den Thunk so setzen, dass er <strong>entweder</strong> den HWND Parameter auf dem Stack modifiziert und zu einer statischen Memberfunktion springt (in der dann der HWND Parameter zum this-Zeiger gecastet wird und schließlich die gewünschte Memberfunktion der Klasse aufgerufen werden kann), <strong>oder</strong> dass er den this-Zeiger zusätzlich auf den Stack legt und gleich zur gewünschten Memberfunktion springt.</p>
<p>Erstere Version (von Codeproject):</p>
<pre><code class="language-cpp">void Init(F2 proc, T1 * pClass) // ist ein template
    {
        //make sure that 'this' is in ecx pointer
        // otherwsie code does not work
#ifdef _DEBUG
        long  pthis;
        _asm  { mov         dword ptr [pthis],ecx }; 
        assert(pthis == (long) this);
#endif
        // put values
        thunk.m_movcx = 0xB9;  //B9
        thunk.m_pThis= (DWORD)pClass;
        thunk.m_jmp = 0xE9;
        thunk.m_relproc = *((int *) &amp;proc) - ((int)this+sizeof(_ProcThunk));

        // write block from data cache and 
        // flush from instruction cache
        FlushInstructionCache(GetCurrentProcess(), 
            &amp;thunk, sizeof(thunk));
    }
</code></pre>
<p>Letztere Version (<a href="http://staff.develop.com/onion/Articles/cpprep0399.htm" rel="nofollow">http://staff.develop.com/onion/Articles/cpprep0399.htm</a>):</p>
<pre><code class="language-cpp">void Init(WNDPROC proc, void* pThis)
	{
		thunk.m_mov       = 0x042444c7;     // mov dword ptr [esp+0x4], pThis
		thunk.m_this      = (DWORD)pThis;   //HWND durch pThis ersetzen
		thunk.m_jmp       = 0xe9;           // jmp WndProc
		thunk.m_relproc   = (int)proc - ((int)this+sizeof(_WndProcThunk));	// Relative jmp
	}
</code></pre>
<p>Ich hoffe, dass ich das Prinzip soweit verstanden habe (gegebenenfalls bitte ausbessern falls unrichtig). Nun möchte ich darum bitten, dass mir jemand die &quot;Formel&quot; für m_relproc erklärt. Die begreife ich nämlich nicht so ganz.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/488180</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/488180</guid><dc:creator><![CDATA[Aziz]]></dc:creator><pubDate>Wed, 24 Mar 2004 21:32:51 GMT</pubDate></item><item><title><![CDATA[Reply to Verständnisproblem bei Thunks... on Wed, 24 Mar 2004 22:07:45 GMT]]></title><description><![CDATA[<p>relproc scheint ein Offset zwischen der Member-Funktion und Adresse des Objekts im Speicher zu sein.</p>
<p>Muss allerdings nicht stimmen <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/488203</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/488203</guid><dc:creator><![CDATA[Shlo]]></dc:creator><pubDate>Wed, 24 Mar 2004 22:07:45 GMT</pubDate></item><item><title><![CDATA[Reply to Verständnisproblem bei Thunks... on Wed, 24 Mar 2004 22:14:37 GMT]]></title><description><![CDATA[<p>Also ich habe das so verstanden, ich hoffe das ist richtig:</p>
<p>Bei einem relativen Sprung musst du ja nur einen Offset ermitteln den du von der aktuellen Position springst.</p>
<p>Mit ((int)this+sizeof(_WndProcThunk)) ermittelt man den Instruction Pointer. (der zeigt ja auf den Befehl der als nächstes ausgeführt wird)</p>
<p>Offset = Ziel - aktuelle Position</p>
<p>weil</p>
<p>Ziel = aktuelle Position + Offset</p>
<p>Ich habe mich für die zweite Möglichkeit entschieden, weil die erste IMHO nicht auf allen Windows-Compilern funktioniert. (hab ich nicht auf dem g++ zum Laufen bekommen, da er glaube ich den this pointer nicht in ecx speichert. Werde es aber heute nochmal für mich selbst ausprobieren)</p>
]]></description><link>https://www.c-plusplus.net/forum/post/488208</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/488208</guid><dc:creator><![CDATA[Matthias.]]></dc:creator><pubDate>Wed, 24 Mar 2004 22:14:37 GMT</pubDate></item><item><title><![CDATA[Reply to Verständnisproblem bei Thunks... on Wed, 24 Mar 2004 22:14:50 GMT]]></title><description><![CDATA[<p>Das ist eben das, was ich nicht verstehe. Wieso ein Offset? Wieso nicht einfach:</p>
<pre><code class="language-cpp">thunk.m_relproc = *((int *) &amp;proc);
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/488209</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/488209</guid><dc:creator><![CDATA[Aziz]]></dc:creator><pubDate>Wed, 24 Mar 2004 22:14:50 GMT</pubDate></item><item><title><![CDATA[Reply to Verständnisproblem bei Thunks... on Wed, 24 Mar 2004 22:18:19 GMT]]></title><description><![CDATA[<p>Matthias. schrieb:</p>
<blockquote>
<p>Also ich habe das so verstanden, ich hoffe das ist richtig:</p>
<p>Bei einem relativen Sprung musst du ja nur einen Offset ermitteln den du von der aktuellen Position springst.</p>
<p>Mit ((int)this+sizeof(_WndProcThunk)) ermittelt man den Instruction Pointer. (der zeigt ja auf den Befehl der als nächstes ausgeführt wird)</p>
<p>Offset = Ziel - aktuelle Position</p>
<p>weil</p>
<p>Ziel = aktuelle Position + Offset</p>
<p>Ich habe mich für die zweite Möglichkeit entschieden, weil die erste IMHO nicht auf allen Windows-Compilern funktioniert. (hab ich nicht auf dem g++ zum Laufen bekommen, da er glaube ich den this pointer nicht in ecx speichert. Werde es aber heute nochmal für mich selbst ausprobieren)</p>
</blockquote>
<p>Ja, es funktioniert leider nur auf bestimmten Compilern...Ich hab aber nicht vor, von Visual C++ 6.0 auf was anderes umzusteigen. Man kann es aber trotzdem ohne viel Aufwand umstellen, falls man es doch auf einem anderen Compiler kompilieren will.</p>
<p>Ich versuch jetzt mal deine Erklärung zu behirnen <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/488212</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/488212</guid><dc:creator><![CDATA[Aziz]]></dc:creator><pubDate>Wed, 24 Mar 2004 22:18:19 GMT</pubDate></item><item><title><![CDATA[Reply to Verständnisproblem bei Thunks... on Wed, 24 Mar 2004 22:24:58 GMT]]></title><description><![CDATA[<p>Aziz schrieb:</p>
<blockquote>
<p>Das ist eben das, was ich nicht verstehe. Wieso ein Offset? Wieso nicht einfach:</p>
<pre><code class="language-cpp">thunk.m_relproc = *((int *) &amp;proc);
</code></pre>
</blockquote>
<p>Das habe ich mich auch schon gefragt, warum kein direkter Sprung gemacht wird. Ich kenne mich aber leider auch nicht in Assembler aus - wird bestimmt seine Gründe haben. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f603.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--grinning_face_with_big_eyes"
      title=":D"
      alt="😃"
    /></p>
<p>Aber solange du einen relativen Jump ausführst (Opcode 0xE9) musst du natürlich den Offset berechnen, anstatt die Adresse direkt zu benutzen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/488216</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/488216</guid><dc:creator><![CDATA[Matthias.]]></dc:creator><pubDate>Wed, 24 Mar 2004 22:24:58 GMT</pubDate></item><item><title><![CDATA[Reply to Verständnisproblem bei Thunks... on Wed, 24 Mar 2004 22:33:13 GMT]]></title><description><![CDATA[<p>Ok, ich denke jetzt verstehe ich es. Danke vielmals!</p>
<p>Ich hätte nie gedacht, dass ich diese &quot;Thunk-Geschichte&quot; jemals verstehen werde. Als ich das erste mal im Web darüber gestolpert bin, bin ich sofort vor Schreck davongelaufen <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f603.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--grinning_face_with_big_eyes"
      title=":D"
      alt="😃"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/488219</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/488219</guid><dc:creator><![CDATA[Aziz]]></dc:creator><pubDate>Wed, 24 Mar 2004 22:33:13 GMT</pubDate></item></channel></rss>