1

アセンブリ言語でプロシージャを呼び出す方法を学ぼうとしています。以下は、私の問題を示す簡単な例です。7スタックにプッシュし、プロシージャを呼び出します。手順がスタックからポップされると、値はプッシュしたものではありません。誰かが何が起こっているのか、そしてこれを機能させるために何ができるのかを理解するのを手伝ってもらえますか?

PUSH 7
CALL FOOBAR
MOV AH, 4CH
INT 21H

FOOBAR PROC
    POP AX ; Not 7
    RET
FOOBAR ENDP
4

2 に答える 2

4

命令はcallリターンアドレスをスタックに置くのでpop ax、プロシージャに入ると、プッシュした7ではなく、リターンアドレスを取得します。も機能しません(retそこに差出人住所が見つかることを期待しています!)次のようなものを試してください...

FOOBAR proc
push bp ; save caller's reg
mov bp, sp
mov ax, [bp + 4]
; do something with it
; leave - equivalent to:
mov sp, bp
pop bp

ret

ここに「落とし穴」の可能性があります。「far」プロシージャには、スタック上にセグメント(cs)とオフセットの両方があるため、リターンアドレス用に4バイト、push bpputs用に2バイトが最初のパラメータをに置きます[bp + 6]procわかりやすくするために、デフォルトはproc near-あなたはそれを言いたいかもしれません。必要な場合は、proc farおそらく32ビットコード(または64ビット)に移行する時期です。16ビットコードはそのようなPITAです-私たちはそれを忘れて本当にうれしいです!:)

于 2013-01-12T20:02:48.733 に答える
1

main からプロシージャを呼び出し、値がそれぞれ 1 と 2 の 2 つのパラメーターを渡すときのスタックの状態を次に示します。

              Address    : Value
              ----------------------
              0xbffff3b0 : 0x0011e030
              0xbffff3b4 : 0x08049ff4
      esp --> 0xbffff3b8 : 0xbffff3e8
              0xbffff3bc : 0x08048419
              0xbffff3c0 : 0x00284324
              0xbffff3c4 : 0x00000003
      ebp --> 0xbffff3c8 : 0xbffff3e8 <-- old ebp
              0xbffff3cc : 0x080483e5 <-- return address
ebp + 0x8 --> 0xbffff3d0 : 0x00000001 <-- first parameter
ebp + 0xc --> 0xbffff3d4 : 0x00000002 <-- second parameter
              0xbffff3d8 : 0x0804840b
              0xbffff3dc : 0x00283ff4

このコードは 32 ビット プログラムから取得したものであるため、レジスタは実際には bp と sp であり、相対オフセットは 0x4 と 0x6 です。

于 2013-01-12T19:20:50.133 に答える