上記のスニペットは、(IMO が壊れている) AT&T 構文の x86_32 アセンブリです。
AT&T 構文では、すべてのオペランドにサイズ サフィックスが付加されます。
movl
32 ビットオペランドを意味します。(長い場合は l)
movw
は 16 ビット オペランドを意味します (ワードは w)
movb
は 8 ビット オペランドを意味します (バイトは b)
オペランドの順序が逆になっているため、宛先が右側にあり、ソースが左側にあります。
これは、他のほぼすべてのプログラミング言語とは対照的です。
%
レジスタ名には、変数名と区別するために接頭辞 a が付きます。レジスタが括弧で囲まれている場合は()
、レジスタ自体の値ではなく、レジスタが指すメモリ アドレスが使用されることを意味します。
EBP はスタックフレームへのポインターとして使用されるため、これは理にかなっています。
スタックフレームは、関数内のパラメーターとローカル変数にアクセスするために使用されます。
書く代わりに: mov eax, dword ptr [ebp+8]
(Intel 構文)
AT&T 構文では次のようにリストされます: movl 8(%ebp), %eax
(gas 構文)
つまり、(ebp + 8) が指すメモリアドレスの内容を eax に入れます。
翻訳は次のとおりです。
.L13: <<-- label used as a jump target.
movl 8(%ebp), %eax <<-- p1, stored at ebp+8 goes into EAX
movl (%eax), %edx <<-- p1 is a pointer, EDX = p1->next
movl 12(%ebp), %ecx <<-- p2, stored at ebp+12 goes in ECX
movl (%ecx), %eax <<-- p2 is (again) a pointer, EAX = p2->next
movl 8(%ebp), %ecx <<-- ECX = p1
movl %eax, (%ecx) <<-- p2->next = p1->next
jmp .L19 <<-- jump to exit
...
.L19
movl %edx, %eax <<-- EAX is always the return value
<<-- return p1->data.
x86 の多くの呼び出し規則のすべてで、関数の戻り値は EAX レジスタに入れられます。(または INT64 の場合は EAX:EDX)
散文: p1 と p2 はデータへのポインターであり、このデータではポインターへのポインターです。
このコードは、連結リストを操作しているように見えます。
p2->next
に設定されていp1->next
ます。
それ以外は、スニペットは不完全に見えます。これは、最初にあったものはすべて処理されp2->next
ていないため、表示されていないコードがさらにある可能性があります。
紛らわしい AT&T 構文を除けば、これは非常に単純なコードです。
C では、コードは次のようになります。
(void *)p2->next = (void *)p1->next;
コードは非常に非効率的であり、まともなコンパイラ (または人間) がこのコードを生成しないことに注意してください。
次の等価物は、より理にかなっています。
mov eax,[ebp+8]
mov ecx,[ebp+12]
mov eax,[eax]
mov [ecx],eax
jmp done
AT&T と Intel の構文の違いについて詳しくは、http ://www.ibm.com/developerworks/linux/library/l-gas-nasm/index.html を参照してください。