GAS のマクロ定義の中で、マクロ引数(パラメーター)の後ろに文字を結合したい場合、引数名と後ろの文字とがくっつかないように境界を明示するためには \() を使え、とマニュアルに書いてあります

単純なマクロ定義ならこれでいいんですが、ネストした定義だと外側の定義を展開する時に \() が解釈されて消滅するので、うまく働きません。

[umezawa@devubuntu:pts/0 ~]$ cat gas_nested_macro_expansion.cc
void foo()
{
        asm volatile (
        R"(
        nop
        .macro MACRO_OUTER x
        .macro MACRO_INNER y
        cmp %al, %r\x\()b
        cmp %al, %r\y\()b
        .endm
        MACRO_INNER 8
        .endm
        MACRO_OUTER 9
        nop
        )");
}
[umezawa@devubuntu:pts/0 ~]$ g++ -c gas_nested_macro_expansion.cc
gas_nested_macro_expansion.cc: Assembler messages:
gas_nested_macro_expansion.cc:12: Error: invalid character '\' in operand 2
[umezawa@devubuntu:pts/0 ~]$ clang++ -c gas_nested_macro_expansion.cc
:2:11: error: invalid register name
        cmp %al, %r\yb
                 ^
:5:2: note: while in macro instantiation
        MACRO_INNER 8
        ^
gas_nested_macro_expansion.cc:13:1: note: while in macro instantiation
        MACRO_OUTER 9
^
:10:2: note: instantiated into assembly here
        MACRO_OUTER 9
        ^
1 error generated.

数年前にこれに困ってたんですが、最近 \(\()) と書けば回避できることに気づきました。

[umezawa@devubuntu:pts/0 ~]$ !cat
void foo()
{
        asm volatile (
        R"(
        nop
        .macro MACRO_OUTER x
        .macro MACRO_INNER y
        cmp %al, %r\x\(\())b
        cmp %al, %r\y\(\())b
        .endm
        MACRO_INNER 8
        .endm
        MACRO_OUTER 9
        nop
        )");
}
[umezawa@devubuntu:pts/0 ~]$ g++ -c gas_nested_macro_expansion.cc
[umezawa@devubuntu:pts/0 ~]$ objdump -d gas_nested_macro_expansion.o

gas_nested_macro_expansion.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 <_Z3foov>:
   0:   f3 0f 1e fa             endbr64
   4:   55                      push   %rbp
   5:   48 89 e5                mov    %rsp,%rbp
   8:   90                      nop
   9:   41 38 c1                cmp    %al,%r9b
   c:   41 38 c0                cmp    %al,%r8b
   f:   90                      nop
  10:   90                      nop
  11:   5d                      pop    %rbp
  12:   c3                      ret

上では x の方でも \(\()) と書いていますが、x を展開するのは外側のマクロの展開時なので、\() と書いても期待通りの動作になります。

Trackback

no comment untill now

Add your comment now