3

この方法で main() 関数のアドレスを取得しようとしています:

int main(int argc, char *argv[])
{
   void *pMainAddress=(void *)&main;
   printf("Address of main() 0x%08X \n", pMainAddress);

リリース構成を使用してプロジェクトをビルドすると、結果は次のようになります:
main() のアドレス:0x00401000

これはデバッガの下にあります:

00401000  /$  68 00104000  PUSH GetMain.00401000    ;  Entry address
00401005  |.  68 50A14000  PUSH GetMain.0040A150    ;  ASCII "0x%p \n"
0040100A  |.  E8 8B000000  CALL GetMain.0040109A

ただし、 /Ziオプションを指定してコンパイルするか、デバッグビルドを使用すると、アドレスがリダイレクトされます:
main() のアドレス: 0x0041178A。このアドレスは無条件ジャンプを実行することによって取得され、実際のアドレスは0x00412530

これはデバッガの下にあります:

00412530  /> \55                      PUSH EBP
...
00412539  |.  C745 FC 8A174100        MOV [LOCAL.1],GetMain.0041178A  ;  Entry address
00412540  |.  8B45 FC                 MOV EAX,[LOCAL.1]
00412543  |.  50                      PUSH EAX                                                         
00412544  |.  68 5CEC4200             PUSH GetMain.0042EC5C           ;  ASCII "0x%p \n"

なぜこれが起こるのですか?コードがデバッグ ビルドでコンパイルされている場合
、main() 関数 (上記の例) の実際のアドレスを取得する方法は?0x00412530

編集:
なぜこれが起こるのですか?ここですでに回答されています:関数呼び出しの間接的なレベルがおかしい

以下の関数は、私の 2 番目の質問を解決します

void *GetMainAddress(void)
{
    void *pMainAddress=(void*)&main;/* address in main() function */
    unsigned long calculateJump=0;
    unsigned char *ptrJump;   
    printf("Address of main() : 0x%08X\n",  pMainAddress);


    ptrJump=(unsigned char*)pMainAddress;/* get pointer to main address */
    if(*(unsigned char*)ptrJump == 0xE9)/* address point to jmp opcode ? */
    {
        calculateJump = ( *(unsigned long *)(ptrJump+1) ); /* get address after 0xe9 */
        pMainAddress =  ptrJump + calculateJump + 5; /* calculate real address */
        printf("Unconditional jump is performed\n");
        printf("Actual sddress of main() is: 0x%08X \n", pMainAddress);
    }
    else
    {
        printf("Unconditional jump is not performed\n");
    }
    return   pMainAddress;
}  
4

2 に答える 2

3

関数アドレスを取得する必要がある場合は、括弧を省略してください。

例えば:

int main(){
    printf("main is at %p\n", main);
    return 0;
}
于 2013-07-10T23:36:21.933 に答える
1

これは、 Visual Studio のプロジェクト構成でデバッグ情報の形式が に設定されているmain()場合に、関数の実際のアドレスを取得する方法です。 ここに私の機能があります: /ZI

void *GetMainAddress(void)
{
    void* pMainAddress = (void*)&main;
    unsigned long calculateJump = 0;
    unsigned char* ptrJump;

    ptrJump = (unsigned char*)pMainAddress;
    if(*(unsigned char*)ptrJump == 0xE9)
    {
        calculateJump = (*(unsigned long*)(ptrJump + 1));
        pMainAddress = (ptrJump + calculateJump + 5);
        printf("Unconditional jump is performed\n");
        printf("Address of main() : %#x \n", pMainAddress);
    }
    else
    {
        printf("Unconditional jump is not performed\n");
        printf("Address of main() : %#x \n", pMainAddress);     
    }
    return   pMainAddress;
}

テストするには、Visual Studio を使用してコンソール アプリケーションを作成し、ソリューション構成からDebugまたはを選択します。 を に配置し、ソリューションを構築します。Release
GetAddressOfMain()int main()

関数は 64 ビット プロジェクト構成でも機能しますが、アドレスを正しく出力するには、適切な形式指定子を使用する必要があります。

于 2013-08-07T01:25:43.527 に答える