「caller-save」および「callee-save」レジスターについて聞いたことがありますか?
CPU には少数の限られた数のレジスタしかないため、通常、呼び出し元/呼び出された関数が常に異なるレジスタを使用することは不可能です。呼び出し元の関数と呼び出された関数の両方が同じレジスタを使用したい場合は、呼び出しの前後に呼び出し元の値を保存/復元する必要があることを意味します。
レジスタ値の保存/復元は、呼び出し元または呼び出し先のいずれかによって行うことができます。どちらがそうするかは慣習の問題です。「caller-save」レジスターの利点は、呼び出し後にレジスター XYZ の値が必要ないことを呼び出し元が知っている場合、保存/復元操作を省略できることです。「呼び出し先保存」レジスタの利点は、呼び出し先がレジスタ XYZ の値を変更しないことがわかっている場合、保存/復元操作を省略できることです。
あなたのコンパイラはRDIを呼び出し先保存レジスタとして扱いますが、コンパイラの最適化をオンにしない限り、不要な保存/復元操作を省略しないと思います。(誰かがこれが間違っていることを知っている場合は、別の回答を投稿してください!)
更新: x86 呼び出し規約に関する記事を見つけました: http://en.wikipedia.org/wiki/X86_calling_conventions
ほとんどの呼び出し規約では、RDI が呼び出し先保存になることが確認されているようです。これは、他のすべての呼び出し先保存レジスタをプッシュおよびポップしない理由を説明していません。たぶん、ここで何か他のことが起こっています。