アセンブリにおけるC言語の配列とポインタの扱い方の違い

C言語において配列とポインタは同等のものとして扱うことができる。

アセンブリにおいてこの二者の扱い方の違いはあるのだろうか。MIPSアセンブリにおいて、C言語の配列とポインタの扱い方にどのような違いがあるのか挙動を確認してみる。

test.cというプログラムを用意し、それをコンパイルしたtest.sというMIPSアセンブリプログラムを読みこれを確認していく。

char * string_ptr   = "String of pointer";
char   string_ary[] = "String of Array";

まず注目すべきは領域の確保の仕方である。

asciizで文字列を格納しているところは同じであるが、ポインタの方は$LC0というラベルを使用し、_string_ptr:において.wordを使ってさきほどのラベルを指定して文字列を格納している。

    20 $LC0:
     21   .asciiz "String of pointer"
     22   .data
     23   .align  0
     24   .align  2
     25 _string_ptr:
     26   .word $LC0
     27   .align  2

一方_string_aryに関しては、そのままそのラベル部分で領域を確保して文字列を格納している。

     28 _string_ary:
     29   .asciiz "String of Array"
     30   .rdata
     31   .align  0
     32   .align  2

この違いは、いったい何を生むのだろうか。

ポインタでは、_string_ptrの示すアドレス(文字列の先頭番地のなるのか)を変えることで、容易に他のデータを指し示すよう変更を加えることができる。文字列ではそのラベル自体が文字列をさしているのでそのような変更を行うことはできない。これは間接的にデータを指し示すポインタを用いるひとつの利点になり得るだろう。

C言語のレベルに落とし込むとさらに疑問は生まれる。

C言語内でもstring_ptrの値を直接アドレスで上書きすれば他のデータの先頭を指し示すよう変更を加えることができることは容易に想像できる。

だが同様にC言語ソース中でstring_aryはデータの先頭を指し示すアドレスであるはずなのでこれを書き換えればstring_ary[]内のデータも変更されるような気がする。だがそのような操作を行う場合、アセンブリプログラムでは、もう一度ラベルの中のデータを塗り替えてしまうぐらいしか方法が思いつかない。ということは、C言語でこのような操作を行うことはできないのだろうか。

謎は深まる