0

inject-bundle プロジェクトからコピーされた c ファイルの asm 関数は次のとおりです。

asm void mach_thread_trampoline(void)
{

    // Call _pthread_set_self with pthread_t arg already on stack
    pop     eax
    call    eax
    add     esp, 4

    // Call cthread_set_self with pthread_t arg already on stack
    pop     eax
    call    eax
    add     esp, 4

    // Call function with return address and arguments already on stack
    pop     eax
    jmp     eax

}

gcc の後 (私は mac os x lion 10.7.4 で作業を行います):

$gcc -m32 -fasm-blocks -oa ac -g

gdb をターゲットにして、gdb の mach_thread_trampoline の内容を確認します。

(gdb) x/17i mach_thread_trampoline

0x1f80 <mach_thread_trampoline>:    pop    %eax
0x1f81 <mach_thread_trampoline+1>:  call   *%eax
0x1f83 <mach_thread_trampoline+3>:  mov    %esp,%eax
0x1f85 <mach_thread_trampoline+5>:  mov    %eax,%esp
0x1f87 <mach_thread_trampoline+7>:  add    $0x4,%esp
0x1f8a <mach_thread_trampoline+10>: mov    %esp,%eax
0x1f8c <mach_thread_trampoline+12>: mov    %eax,-0x8(%ebp)

0x1f8f <mach_thread_trampoline+15>: pop    %eax
0x1f90 <mach_thread_trampoline+16>: call   *%eax
0x1f92 <mach_thread_trampoline+18>: mov    %esp,%eax
0x1f94 <mach_thread_trampoline+20>: mov    %eax,%esp
0x1f96 <mach_thread_trampoline+22>: add    $0x4,%esp
0x1f99 <mach_thread_trampoline+25>: mov    %esp,%eax
0x1f9b <mach_thread_trampoline+27>: mov    %eax,-0x8(%ebp)

0x1f9e <mach_thread_trampoline+30>: pop    %eax
0x1f9f <mach_thread_trampoline+31>: jmp    *%eax
0x1fa1 <mach_thread_trampoline+33>: ret     

ターゲットは、mach_thread_trampoline 関数のいくつかの命令を追加しました。

asm 関数を変更しないようにする方法はありますか?

4

2 に答える 2

1

自明ではないサイズのasm関数がある場合は、必要に応じて.S使用できる別のファイルに配置する.intel_syntax noprefixか、別の回答が示唆するようにNASMを使用する必要があります。

ただし、 GAS 構文で記述された小さな関数をorasm("");に貼り付けたい場合は、グローバルスコープでステートメントを使用して、コンパイルのバグ/奇妙さを回避できます。この回答の最後のセクションを参照してください。.c.cpp


asm関数型は Apple 拡張機能のように見えるため、(Linux) gcc または Godbolt コンパイラ エクスプローラーの clang ではサポートされていません。

それは同じ目的を果たしているようです__attribute__ ((naked))(メインストリーム (Apple だけでなく) の clang 3.3 以降、および最近の GCC によって x86 でサポートされています)。しかし、@MichaelPetch はgcc、OS X 10.7 では ( gcc version 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)) がをサポートしていない__attribute__ ((naked))と報告しています。

(新しい OS X はgccのエイリアスを作成しclangますが、古い OS X には GCC のカスタム バージョンがありました)。

asm void func(void) {使用しているコンパイラ バージョンの構文にコンパイラ バグがあるようです。フレームポイントの存在を想定して、 のようなものを挿入できるのは意味がありませんmov %eax,-0x8(%ebp)asmコンパイラがそれを許可している場合、その拡張機能がどのように役立つかわかりません。では発生しない-O3可能性があるため、最適化を有効にすることで回避できる場合があります。

ところで、通常の (Apple 以外の) GCC は MSVC スタイルの asm ブロックをサポートしていませんが、GNU C asm("instructions");asm ステートメントのみをサポートしています。しかし、LLVM を使用する Apple の gcc のバージョンは、LLVM をサポートしています。


__attribute__ ((naked))(OS X 10.7 gcc ではサポートされていません)

asm ブロックに余分な命令を導入するバグのあるコンパイラを使用している場合、これが違いを生む場合は IDK を使用してください。(サポートされていたとしても、OS X 10.7ではサポートされていませんgcc

この構文は、最新の clang で機能します。(まだサポートしていないため、gcc ではありません-fasm-blocks)

これは、clang 3.3を使用する Godboltで正しくコンパイルされます。「バイナリ」出力を使用して、オブジェクト ファイルに実際のマシン コードが表示されていることを確認したので、-nostdlibそれをリンクするために使用する必要がありました。-O0orでasm を歪めるのを回避します-O3が、私は非常に異なるコンパイラを使用していますが、この構文の変更はおそらく関係ありません。

__attribute__ ((naked)) void mach_thread_trampoline(void)
{
    // asm block *inside* a function
    asm { 
    // Call _pthread_set_self with pthread_t arg already on stack
    pop     eax
    call    eax
    add     esp, 4

    // Call cthread_set_self with pthread_t arg already on stack
    pop     eax
    call    eax
    add     esp, 4

    // Call function with return address and arguments already on stack
    pop     eax
    jmp     eax
    }
}

ポータブル GNU Casm("");

GNU C では、 Basic ASM ステートメントをグローバル スコープに置くことができます。

この構文は、おそらく OS X 10.7 のコンパイラ バグを回避します。これは、まったく使用-fasm-blocksしておらず、コンパイラが関数内にあると考える機会がないためです。.textセクションでこのコードをアセンブルするだけ

void mach_thread_trampoline(void);   // prototype

// definition: name mangling / leading underscore must be done manually
asm(".globl  _mach_thread_trampoline\n\t"
    "_mach_thread_trampoline:\n\t"
    "pop   %eax\n\t"
    "call  *%eax\n\t"
    ...
    "jmp    *%eax"
);

そのため、ネイキッド関数は、名前マングリングが重要な C++ で利点を持つ可能性があります。おそらくネイキッド関数は自動的に noinline になります。

本当に移植性が必要な場合は、次のような方言代替を使用jmp {*%eax|eax}して、コンパイルされている-masm=intelかどうかに関係なくコードが機能するようにすることができます。

.intel_syntax noprefixasm ブロック内で使用してから.att_syntax、残りのコンパイラ コードの最後で元に戻すことはお勧めしません。あなた (または Godbolt コンパイラ エクスプローラーのようなツール) でコンパイルすると壊れるハックです-masm=intel

于 2018-08-05T19:59:16.790 に答える