主語を大きく取りすぎている可能性がある(実際に確認したのは「Mac の i386/x86_64 をターゲットとする、Xcode に含まれている Clang のインラインアセンブラ」だけ)のですが、記事タイトル通りのことになります。

Linux の i386/x86_64 や Windows の x86/x64 をターゲットとする場合は GCC (GAS) でも Clang でも .align.balign の意味、つまり引数はバイト数を指定します。一方、Mac の場合は .p2align の意味、つまり2を指定した数で累乗したバイト数でアライメントされます。なので、64 バイトアライメントにするつもりで .align 64 とか書くと16エクサバイトアライメントと見なされてエラーになります。

例えば以下のプログラムを x86_64 向けにコンパイルするとします。

int main(void)
{
        int ret;
        asm volatile (
                ".align 4\n"
                "incl %%eax\n"
                ".align 4\n"
        : "=a"(ret));
        return ret;
}

Linux だと以下のようになり、4バイトアライメントされています。

[umezawa@devcent7:pts/0 ~]$ clang -o asmalign asmalign.c
[umezawa@devcent7:pts/0 ~]$ gdb asmalign
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-94.el7
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
...
Reading symbols from /home/umezawa/asmalign...(no debugging symbols found)...done.
(gdb) disassemble main
Dump of assembler code for function main:
   0x00000000004004f0 <+0>:     push   %rbp
   0x00000000004004f1 <+1>:     mov    %rsp,%rbp
   0x00000000004004f4 <+4>:     movl   $0x0,-0x4(%rbp)
   0x00000000004004fb <+11>:    nop
   0x00000000004004fc <+12>:    inc    %eax            # ここ
   0x00000000004004fe <+14>:    xchg   %ax,%ax
   0x0000000000400500 <+16>:    mov    %eax,-0x8(%rbp) # ここ
   0x0000000000400503 <+19>:    mov    -0x8(%rbp),%eax
   0x0000000000400506 <+22>:    pop    %rbp
   0x0000000000400507 <+23>:    retq
End of assembler dump.

Mac だと以下のようになり、16バイトアライメントされています。

[umezawa@metis:ttys000 ~]$ clang -o asmalign asmalign.c
[umezawa@metis:ttys000 ~]$ lldb asmalign
(lldb) target create "asmalign"
Current executable set to 'asmalign' (x86_64).
(lldb) disassemble --name main
asmalign`main:
asmalign[0x100000f90] <+0>:  pushq  %rbp
asmalign[0x100000f91] <+1>:  movq   %rsp, %rbp
asmalign[0x100000f94] <+4>:  movl   $0x0, -0x4(%rbp)
asmalign[0x100000f9b] <+11>: nopl   (%rax,%rax)
asmalign[0x100000fa0] <+16>: incl   %eax             # ここ
asmalign[0x100000fa2] <+18>: nopw   %cs:(%rax,%rax)
asmalign[0x100000fb0] <+32>: movl   %eax, -0x8(%rbp) # ここ
asmalign[0x100000fb3] <+35>: movl   -0x8(%rbp), %eax
asmalign[0x100000fb6] <+38>: popq   %rbp
asmalign[0x100000fb7] <+39>: retq

私はバイト数指定で慣れているので .balign に置き換えればそれで済むことなんですが、なんでこんなことになってるんでしょう。 PowerPC 時代からの伝統でしょうか。

Trackback

no comment untill now

Add your comment now