x86のCPU命令"POPAD"が曲者だった話

気づいたら100日ブログ書いてませんでした
最近はXinu本読んでるほのかのです

そもそもなんで今更POPADが出てきたかと言いますと
最近読んでいるXinu本がx86想定であり、そこでPOPADが出てくるわけです
ましてや、コンテキストスイッチの部分なので、ちゃんとレジスタを保存しつつ特定の場所へジャンプしなければいけないわけです

というわけで覚書

POPADは7つのレジスタを保存します
もう一度言います
ESP以外の7つのレジスタを保存します
ESPはどうなるかというと、それらをpopした後POPADの前のESPに+32します
つまり8つ値をPOPした後のESPの結果と一緒です

因みにPUSHADはESPもpushしますので注意が必要です
ただしこっちのESPも少し特殊でPUSHADする前のESPをpushするみたいなので注意

応用
x64ではPUSHA、POPA(PUSHAD/POPADはDとつく通り32bit用なのです)は廃止されました
多分レジスタが増えたのと上のESP(x64ではRSP)の特殊な仕様のせいだと思いますが便利だったのでちょっとショックです
そんなわけでx64でPUSHAとPOPAを再現するとこうなります
(x64の全レジスタを保存する場合下の例だとr9が保存されないので何かしら工夫してね)

/* pusha */
movq %rsp,%r9 ; save rsp
pushq %rax
pushq %rcx
pushq %rdx
pushq %rbx
pushq %r9   ; push rsp
pushq %rbp
pushq %rsi
pushq %rdi

/* popq */
popq %rdi
popq %rsi
popq %rbp
popq %rax ; trash rsp
popq %rbx
popq %rdx
popq %rcx
popq %rax

ではでは(?)

[編集履歴]
・gasの文法にnasmのコメントが入ってたので直したよ
・pushaのサンプルにバグがあるのでそれに関して追記したよ