1

私はGCCのアセンブリ出力スイッチで遊んでいます:

gcc -S -c helloworld.c

helloworld.c

#include <stdio.h>

int main(void){
    printf("Hello World!\n");
    return 0;
}

helloworld.s

    .file   "helloworld.c"
    .section    .rodata
.LC0:
    .string "Hello World!"
    .text
    .globl  main
    .type   main, @function
main:
.LFB0:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    movl    $.LC0, %edi
    call    puts
    movl    $0, %eax
    popq    %rbp
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE0:
    .size   main, .-main
    .ident  "GCC: (Debian 4.7.2-5) 4.7.2"
    .section    .note.GNU-stack,"",@progbits

出力helloworld.sファイルで、「HelloWorld!」を出力するアセンブリコマンドに気づきました。テキストは単純です:

call puts

ただし、ファイルにはputsプロシージャアセンブリコードが含まれhelloworld.s1ていません。このアセンブリコードはどこで表示できますか?

4

3 に答える 3

7

編集:これは実際には元の質問に対する答えではありませんが、賛成されているので、情報は有用であるように思われるので...


これはGCCによる最適化です。文字列には書式設定文字が含まれておらず、改行で終わるため、GCCはputs、同じ出力を生成する呼び出しを置き換えますが、はるかに高速です(書式設定指定子の文字列をスキャンする必要がないため)。次のようなものを試してください:

int main(int argc, char *argv[]){
    printf("Hello World!\nargc=%d", argc);
    return 0;
}

printfそして、あなたはアセンブリであなたを見るでしょう。

于 2013-03-19T14:52:25.473 に答える
2

答え

gccフラグを使用し-fno-builtinます。

説明

パフォーマンスを向上させるために、GCC、Glibcは一緒に標準Cライブラリにいくつかの変更を加えます。GCCとGlibcは、ほとんどすべてのユーザースペースアプリケーションで連携して動作するため、組み込み関数はデフォルトでオンになっています。これにより、printf()関数呼び出しで1つのパラメーターのみを使用して関数呼び出しが変換されますputs()

のようなフラグを使用して、特定の組み込み関数呼び出しを変換しないようにGCCに指示することもできます-fno-builtin-printf。これは、GCCを停止して変換できる組み込み関数の完全なリストです

これが旗の詳細な説明です。

于 2013-03-20T06:47:36.657 に答える
2

ユーザーが言及したように:

これは、Cプログラムが標準のCランタイムライブラリにリンクされていることを期待しているputs()ためです。もちろん、必要に応じて、システム上のライブラリファイルを分解して掘り下げることもできます。

そこで、 objdumpを使用して逆アセンブルし、セクションlibc.aの下にアセンブリコードを見つけました。<puts>objdump -d /usr/lib/x86_64-linux-gnu/libc.a

于 2013-03-24T20:03:20.570 に答える