質問: 細々とした質問なので、複数質問することをお許しください。 アセンブリ言語で読めない箇所があります。 以前の質問で、以下のような例を示してもらいました(ありがとうございます。) ``` .section .rodata xx: .quad subr .text subr: inc %rax # ++rax ret .global aFunc aFunc: mov $0, %rax call subr call (subr) call *(xx) # 1 call *xx # 2 mov $subr, %rdx # 3 call *%rdx # lea subr(%rip), %rdx call *%rdx lea xx(%rip), %rdx call *(%rdx) ret ``` ですが、私の環境ではうまく行きませんでした。 1、2、3番と出来なかった所には番号が振ってあります。 (私にとってはこの3つができない方が納得いきます。) 1、**call *subrとできない。** subrは絶対アドレスです。 なぜでしょうか? 1番,2番が仮にも出来る環境なら、call *subr これはできないとおかしいのではないでしょうか? 2,call subr 及び call (subr) の結果が変わらないのは、ラベルに対して括弧を付けても意味が無いということですよね? (付けても付けなくてもおk) 3,$subr は$は即値に付ける構文ですよね? ラベルにも付けれるんですか? (私の環境ではできませんでした。) 4,以上を見ていただければ、わかりますが・・・ アスタリスクは、絶対アドレスが入っているレジスタに対する構文ではないでしょうか? ラベルに[*]を付ける方が納得がいかないんですが・・・・ (レジスタ以外に対するアスタリスクはすべてダメでした。) 5,もう1つ気になる事があります。 ``` movq -8(%rbp), %rax movabsq $7812735413947559801, %rdx movq %rdx, (%rax) movabsq $7308533390257515808, %rcx movq %rcx, 8(%rax) ``` calloc関数を使って、ヒープを確保しその領域にstrcpy()で文字列を代入します。 しかしこれは**オーバーフローではないでしょうか??** 代入している即値が「8Byte」を完全に超えています。 64bitのレジスタに対してはオーバーフローです。 しかし、正常に動作しています・・・なぜでしょうか? 6, mov $1, %rax 最後に、qやl と言った文字をニーモニックにつけますが、 これは即値によって決めるものですか?それともレジスタの容量によって決めるものですか? あ、言い方が悪かったです。ソースとデステネイションのどちらによって決めるものですか? 7,lea xx(%rip), %rdx | call *(%rdx) これを1つにして、call *xx(%rip) と記述できます。(正常に実行できます。) これも変です。 xx(%rip) の中身はアドレスです。 そのアドレスが指す領域内のアドレスが関数のポインタです。 なら、イメージ的には、call *(xx(&rip))こんな感じになります。 実際には文法エラーですが、call *xx(%rip)の記述はおかしいような気がするんですが・・・ これでは、%rip + xx のアドレスを絶対アドレスとしてcallしてしまっているように見えるのですが・・・・ わざわざ、オフセット付きの括弧となしの括弧の使い方を区別しているのに、これでは意味が無くなってしまいます。 [環境] 64bit Linux Debian系 intel CPU です。
回答: > > 3,$subr は$は即値に付ける構文ですよね? > > > Yes. > > ラベルにも付けれるんですか? > > > `mov $subr, %rdx`は、シンボル"subr"の値を%rdxにロードするのです。できて当たり前でしょう。念の為に言うと、シンボル値が決定するのはリンク時である。 おまけ:ら抜き言葉は止めよう。軽薄に聴こえるw ×付けれる ○付けられる > > 私の環境ではできませんでした > > > ひとつ見てみたいのは、君の手元で、アセンブルリストを出して、`mov $subr, %rdx`の部分がどうなってるか、(エラーにならない、と言うなら)何バイト命令としてアセンブルされるか。 もうひとつは、`movq $subr, %rdx`としたら、何か変化があるか。。。 > > 5. 代入している即値が「8Byte」を完全に超えています > > > って movabsq $7812735413947559801, %rdx movabsq $7308533390257515808, %rcx のことであれば、strike君の名誉のために、さっさと質問を取り下げるのが 良いと思う。 > > 6, mov $1, %rax > > 最後に、qやl と言った文字をニーモニックにつけますが、 > > これは即値によって決めるものですか?それともレジスタの容量によって決めるものですか? > > > 0x01も、0x0001も、0x00000001も、0x00000000000000001 も、値は全て1ですが、デスティネーションとして %rax が指定されてるのだから、その1は64ビットの1である(LSBitのみ1で、それ以外の63bitは0である)と判断できます。 一般的な言い方をすれば「デスティネーションとして指定されたレジスタのビット数(「容量」でも構わないよ、普通そういう言い方しないと思うが)によって決まる」と、容易に想像がつく話だけどねえ。