0

個別に割り当てられたスタックで関数を実行しようとしています。

後でスタックを保持したいので、スタックを復元して機能を再開できます。

次のコードはコンパイルおよび実行されますが、画面には何も表示されません。

#include <cstdlib>
#include <csetjmp>
#include <iostream>
using namespace std;

unsigned char stack[65535];
unsigned char *base_ptr = stack + 65535 - 1;

unsigned char *old_stack;
unsigned char *old_base;

void function()
{
    cout << "hello world" << endl;
}

int main()
{
    __asm
    {
        mov old_base, ebp
        mov old_stack, esp

        mov ebp, base_ptr
        mov esp, base_ptr

        call function

        mov ebp, old_base
        mov esp, old_stack
    }
}

vs2012/win8/intel Q9650 を使用

4

3 に答える 3

2

C++ と名前マングリングへようこそ。C++ の関数名は、コンパイラによってマングルされます (gcc 関数を使用すると、私にとっては _Z8functionv になります)。これは、関数のオーバーロードを容易にするためです。コンパイラは、バックグラウンドでさまざまな関数に付けた実際の名前を追跡するため、ユーザーにはわかりません。これは、C++ と対話しようとする他の言語の問題です。

このコードは私のコンピューターではリンクしません。

解決策: 1) g++ でコンパイルし、-S フラグを渡します (つまり、g++ -S test.cpp)。次に、アセンブリの出力 (cat test.s) を見て、関数の名前を確認します。次に、「call function」の名前を「call _Z8functionv」に変更します(私にとっては、簡単に異なる場合があります)。2) C を使用: cout << を printf ステートメントに変更すると、上記が機能するはずです。

ただし、gccを使用していないと思います(アセンブラはガスのために前に戻っているため、アセンブラのすべてのオペランドを切り替える必要がありました)。

于 2012-08-03T06:46:33.260 に答える
1

実際、コードに問題はありません。そのまま取得したサンプルは、期待どおりにコンパイル、リンク、実行されます。

おそらく、コンソール設定、またはグローバルSTL/CRT初期化などの問題です。functionとにかく、あなたはあなたがそこに着いていることを確実にするためにあなたの中にブレークポイントを置くかもしれません。

于 2012-08-03T07:17:53.470 に答える
1

Intel の x86 に関するドキュメントMOV、ページ 3-403 によると、新しい値SSをロードする直前にレジスタをロードする必要があります。これにより、割り当てられるESPまで割り込みの実行がブロックされます。ESP

于 2012-08-03T06:18:38.303 に答える