@ledsun blog

無味の味は佳境に入らざればすなわち知れず

gccとclangが生成するアセンブリファイルを比較してみる

もっとCPUの気持ちが知りたいですか? - @ledsun blog で、本の環境と自信の環境で生成されるアセンブリファイルの命令が異なることに気がつきました。

X86アセンブラ/GASでの文法 - Wikibooks によると

GNU ASで使用されているAT&Tアセンブリ構文

というものがあるそうです。

オペレーションサフィックス 「pushl」とか「movl」とか、プッシュ命令やムーブ命令のうしろにエル「l」がサフィックスです。

データサイズなどを指定するためにサフィックスを指定する必要がある。

GASのアセンブリ命令では、一般にオペランドがどのサイズのデータを扱うか指定するために、b、s、w、l、q、tのいずれかの文字をオペランドの最後に付ける。これをサフィックスという。

ということは、もしかしてCPUアーキテクチャの違いではなく、コンパイラの違いなのでしょうか? clangで試してみます。

sudo apt install clangしてclangをインストールします。 つぎにclang -S calc1.cを実行して、アセンブリファイルを作成します。

        .text
        .file   "calc1.c"
        .globl  main                            # -- Begin function main
        .p2align        4, 0x90
        .type   main,@function
main:                                   # @main
        .cfi_startproc
# %bb.0:
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset %rbp, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register %rbp
        subq    $32, %rsp
        movl    $0, -4(%rbp)
        movl    %edi, -8(%rbp)
        movq    %rsi, -16(%rbp)
        movl    $1, -20(%rbp)
        movl    $2, -24(%rbp)
        movl    -20(%rbp), %eax
        addl    -24(%rbp), %eax
        movl    %eax, -28(%rbp)
        movl    -28(%rbp), %esi
        leaq    .L.str(%rip), %rdi
        movb    $0, %al
        callq   printf@PLT
        xorl    %eax, %eax
        addq    $32, %rsp
        popq    %rbp
        .cfi_def_cfa %rsp, 8
        retq
.Lfunc_end0:
        .size   main, .Lfunc_end0-main
        .cfi_endproc
                                        # -- End function
        .type   .L.str,@object                  # @.str
        .section        .rodata.str1.1,"aMS",@progbits,1
.L.str:
        .asciz  "c = %d\n"
        .size   .L.str, 8

        .ident  "Ubuntu clang version 14.0.0-1ubuntu1"
        .section        ".note.GNU-stack","",@progbits
        .addrsig
        .addrsig_sym printf

movlやmovqが出てきます。 セクション名や行の順番がちがうけど、mainの中身は一緒でしょうか? diffを見てみます。

1,5d0
<       .file   "calc1.c"
<       .text
<       .section        .rodata
< .LC0:
<       .string "c = %d\n"
7,10c2,6
<       .globl  main
<       .type   main, @function
< main:
< .LFB0:
---
>       .file   "calc1.c"
>       .globl  main                            # -- Begin function main
>       .p2align        4, 0x90
>       .type   main,@function
> main:                                   # @main
12c8
<       endbr64
---
> # %bb.0:
15c11
<       .cfi_offset 6, -16
---
>       .cfi_offset %rbp, -16
17c13
<       .cfi_def_cfa_register 6
---
>       .cfi_def_cfa_register %rbp
19,36c15,33
<       movl    %edi, -20(%rbp)
<       movq    %rsi, -32(%rbp)
<       movl    $1, -12(%rbp)
<       movl    $2, -8(%rbp)
<       movl    -12(%rbp), %edx
<       movl    -8(%rbp), %eax
<       addl    %edx, %eax
<       movl    %eax, -4(%rbp)
<       movl    -4(%rbp), %eax
<       movl    %eax, %esi
<       leaq    .LC0(%rip), %rax
<       movq    %rax, %rdi
<       movl    $0, %eax
<       call    printf@PLT
<       movl    $0, %eax
<       leave
<       .cfi_def_cfa 7, 8
<       ret
---
>       movl    $0, -4(%rbp)
>       movl    %edi, -8(%rbp)
>       movq    %rsi, -16(%rbp)
>       movl    $1, -20(%rbp)
>       movl    $2, -24(%rbp)
>       movl    -20(%rbp), %eax
>       addl    -24(%rbp), %eax
>       movl    %eax, -28(%rbp)
>       movl    -28(%rbp), %esi
>       leaq    .L.str(%rip), %rdi
>       movb    $0, %al
>       callq   printf@PLT
>       xorl    %eax, %eax
>       addq    $32, %rsp
>       popq    %rbp
>       .cfi_def_cfa %rsp, 8
>       retq
> .Lfunc_end0:
>       .size   main, .Lfunc_end0-main
38,57c35,45
< .LFE0:
<       .size   main, .-main
<       .ident  "GCC: (Ubuntu 11.3.0-1ubuntu1~22.04) 11.3.0"
<       .section        .note.GNU-stack,"",@progbits
<       .section        .note.gnu.property,"a"
<       .align 8
<       .long   1f - 0f
<       .long   4f - 1f
<       .long   5
< 0:
<       .string "GNU"
< 1:
<       .align 8
<       .long   0xc0000002
<       .long   3f - 2f
< 2:
<       .long   0x3
< 3:
<       .align 8
< 4:
---
>                                         # -- End function
>       .type   .L.str,@object                  # @.str
>       .section        .rodata.str1.1,"aMS",@progbits,1
> .L.str:
>       .asciz  "c = %d\n"
>       .size   .L.str, 8
>
>       .ident  "Ubuntu clang version 14.0.0-1ubuntu1"
>       .section        ".note.GNU-stack","",@progbits
>       .addrsig
>       .addrsig_sym printf

ああ、パラメーターとかも微妙に違うんですね。