gccのインラインアセンブラ内からcのラベルにgotoでジャンプ

最近のgccインラインアセンブラ内からcのgotoラベルに飛べる仕組みがあるのでそれのメモです。

ドキュメントはUsing the GNU Compiler Collection (GCC): Extended AsmUsing the GNU Compiler Collection (GCC): Extended Asmです。たしかLKMLに送られてたpatchにもこれを使ったコードがあった気がします。

それはさておき、gotoを使う場合の書式は以下のようになっていて、asm gotoという形式です。

asm [volatile] goto ( AssemblerTemplate 
                      : 
                      : InputOperands
                      : Clobbers
                      : GotoLabels)

ドキュメントには-ansiオプションを付けてコンパイルする場合はasmではなくてasmを使うようにと書かれています。また、出力のオペランドは指定できないようです。そのため、計算の途中経過を保持したいときとかはClobbersのところでメモリに書き出すようにするみたいです。

以下が簡単なサンプルです。argcの数が3かどうか調べて3だったらsameラベルにジャンプしてます。

#include <stdio.h>

int main(int argc, char **argv)
{
    __asm__ goto("cmpl $0x3, %[argc]\n\t"
             "je %l[same]\n\t"
             :
             : [argc] "r"(argc)
             :
             :same);

    printf("argc is %d\n", argc);

    return 0;
same:
    printf("argc == 3\n");
    return 0;
}

機械語になるとこんな感じです。

0000000000400527 <main>:                                                                                                                                                                                           
  400527:       55                      push   %rbp                                                                                                                                                                
  400528:       48 89 e5                mov    %rsp,%rbp                                                                                                                                                           
  40052b:       48 83 ec 10             sub    $0x10,%rsp                                                                                                                                                          
  40052f:       89 7d fc                mov    %edi,-0x4(%rbp)                                                                                                                                                     
  400532:       48 89 75 f0             mov    %rsi,-0x10(%rbp)                                                                                                                                                    
  400536:       8b 45 fc                mov    -0x4(%rbp),%eax                                                                                                                                                     
  400539:       83 f8 03                cmp    $0x3,%eax                                                                                                                                                           
  40053c:       74 1b                   je     400559 <main+0x32>                                                                                                                                                  
  40053e:       8b 45 fc                mov    -0x4(%rbp),%eax                                                                                                                                                     
  400541:       89 c6                   mov    %eax,%esi                                                                                                                                                           
  400543:       bf 00 06 40 00          mov    $0x400600,%edi                                                                                                                                                      
  400548:       b8 00 00 00 00          mov    $0x0,%eax                                                                                                                                                           
  40054d:       e8 ee fe ff ff          callq  400440 <printf@plt>                                                                                                                                                 
  400552:       b8 00 00 00 00          mov    $0x0,%eax                                                                                                                                                           
  400557:       eb 0f                   jmp    400568 <main+0x41>                                                                                                                                                  
  400559:       bf 0c 06 40 00          mov    $0x40060c,%edi                                                                                                                                                      
  40055e:       e8 cd fe ff ff          callq  400430 <puts@plt>                                                                                                                                                   
  400563:       b8 00 00 00 00          mov    $0x0,%eax
  400568:       c9                      leaveq
  400569:       c3                      retq
  40056a:       66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)

低レベルプログラミング

低レベルプログラミング