Skip to content

C言語で定義した変数にアセンブリで値を代入したいが、リンク時にエラーがでる #15

Closed Answered by nuta
keisuke713 asked this question in Help
Discussion options

You must be logged in to vote

納得のいかないアセンブリをコンパイラが生成するときは、Compiler Explorer を使うと便利です。RISC-V rv32gc clang 系が32ビットRISC-V CPU用のclangです。

アセンブリを見てみると、la s2, %0が次の2命令に展開されていることがわかります。

        auipc   s2, %pcrel_hi(a0)
        addi    s2, s2, %pcrel_lo(.Lpcrel_hi0)

%pcrel_hi のドキュメント (リンク) を見ると、シンボルを受け取ることがわかります。つまり、ここで %0 の内容 (a0) がシンボルとして扱われています。=r (任意の汎用レジスタ) が制約として指定されているので、コンパイラが a0 レジスタを %0 として割り当てられ、そのレジスタ名が文字列として愚直に展開されています。

このようなメモリアクセスをする場合は、制約として m を使うとアドレス周りの扱いをコンパイラに任せることができます。

    __asm__ __volatile(
        "li s1, 10\n"    // s1レジスタに数値10を読み込む
        "sw s1, %0\n"    // s1の値を指定したメモリ領域に書き込む。
        : "=m" (result)
    );

int result をグローバル変数に移動すると、アドレスの取り方をコンパイラがきちんと合わせるのを観察すると面白いと思います。

Replies: 1 comment 2 replies

Comment options

You must be logged in to vote
2 replies
@nuta
Comment options

@keisuke713
Comment options

Answer selected by keisuke713
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
Help
Labels
None yet
2 participants