今回は戻り値の型でアセンブラがどう変わるか確認します。
まずは戻り値がchar型の場合。
takk@deb9:~/tmp$ cat -n t.c 1 char func1(void) 2 { 3 return 100; 4 } 5 6 int main() 7 { 8 char ret; 9 ret = func1(); 10 } takk@deb9:~/tmp$
func1の戻り値はEAXに格納されるようです。char型の戻り値であっても、32bitのレジスタが使用されるんですね。
0000000000000660 <func1>: 660: 55 push %rbp 661: 48 89 e5 mov %rsp,%rbp 664: b8 64 00 00 00 mov $0x64,%eax 669: 5d pop %rbp 66a: c3 retq 000000000000066b <main>: 66b: 55 push %rbp 66c: 48 89 e5 mov %rsp,%rbp 66f: 48 83 ec 10 sub $0x10,%rsp 673: e8 e8 ff ff ff callq 660 <func1> 678: 88 45 ff mov %al,-0x1(%rbp) 67b: b8 00 00 00 00 mov $0x0,%eax 680: c9 leaveq 681: c3 retq 682: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 689: 00 00 00 68c: 0f 1f 40 00 nopl 0x0(%rax)
main側で、ALレジスタを使用することで、32bitのEAXレジスタから効率的に8bitを取得してるんですね。
便利なレジスタですね。
ということは、16bitの戻り値になっても同じかと思います。
takk@deb9:~/tmp$ cat -n t.c 1 short func1(void) 2 { 3 return 100; 4 } 5 6 int main() 7 { 8 short ret; 9 ret = func1(); 10 } takk@deb9:~/tmp$
0000000000000660 <func1>: 660: 55 push %rbp 661: 48 89 e5 mov %rsp,%rbp 664: b8 64 00 00 00 mov $0x64,%eax 669: 5d pop %rbp 66a: c3 retq 000000000000066b <main>: 66b: 55 push %rbp 66c: 48 89 e5 mov %rsp,%rbp 66f: 48 83 ec 10 sub $0x10,%rsp 673: e8 e8 ff ff ff callq 660 <func1> 678: 66 89 45 fe mov %ax,-0x2(%rbp) 67c: b8 00 00 00 00 mov $0x0,%eax 681: c9 leaveq 682: c3 retq 683: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 68a: 00 00 00 68d: 0f 1f 00 nopl (%rax)
やはり32bitのEAXからAXで16bitの戻り値のみが使用されています。
最後に戻り値longの場合。
takk@deb9:~/tmp$ cat -n t.c 1 long func1(void) 2 { 3 return 100; 4 } 5 6 int main() 7 { 8 long ret; 9 ret = func1(); 10 } takk@deb9:~/tmp$
結局func1関数は、戻り値が8/16/32bitどの場合でも同じコードでした。
0000000000000660 <func1>: 660: 55 push %rbp 661: 48 89 e5 mov %rsp,%rbp 664: b8 64 00 00 00 mov $0x64,%eax 669: 5d pop %rbp 66a: c3 retq 000000000000066b <main>: 66b: 55 push %rbp 66c: 48 89 e5 mov %rsp,%rbp 66f: 48 83 ec 10 sub $0x10,%rsp 673: e8 e8 ff ff ff callq 660 <func1> 678: 48 89 45 f8 mov %rax,-0x8(%rbp) 67c: b8 00 00 00 00 mov $0x0,%eax 681: c9 leaveq 682: c3 retq 683: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 68a: 00 00 00 68d: 0f 1f 00 nopl (%rax)
main関数の呼び出しの方は、コードは変わりますが、コードサイズが変わってません。
戻り値の方は32bitや64bitにこだわる必要もなさそうです。
コメント