自作エミュレータで学ぶx86アーキテクチャ 3.7 call_rel32,ret

 call-rel32とretはcall命令とret命令に対応した関数です。

(define (call-rel32 emu)
  (let1 diff (get-sign-code32 emu 1)
    (push32 emu (+ (ref emu 'eip) 5))
    (eip-add emu (+ diff 5))))

(define (ret emu)
  (set! (ref emu 'eip) (pop32 emu)))

 call-rel32はcallの次の命令の番地を基準にして前後32ビットの範囲でジャンプできる
命令です。
例えば、以下のようなプログラムだと

call hoge
mov eax,0x0000

「mov eax,0x0000」がある番地を基準にして前後32ビットの範囲でジャンプできます。

 call-rel32の以下の部分で

(eip-add emu (+ diff 5))))

5を足しているのは、call命令の全体が5バイトだからです。
例えば上の「call hoge」のある番地に5を足すと、基準になる「mov eax,0x0000」の
番地になります。

(push32 emu (+ (ref emu 'eip) 5))

 この部分はcall命令を実行した後に戻ってくる番地をプッシュしています。
ここで5を足しているのも上の理由とだいたい同じです。

 retでは、ここでプッシュした値をポップしてeipに設定しています。

(set! (ref emu 'eip) (pop32 emu)))

プログラムの全体はgithubに置いています。
https://github.com/mas454/x86emu