5

これが私が取り組んでいるプログラムからのテスト手順です。スタックを介していくつかのparmを渡します。そのうちの1つはポインターです。逆参照されたポインターの値を変更しようとすると、変数が更新されません。

_testProc proc
    push bp                             ;Save base pointer to stack
    mov bp, sp                          ;Set new base pointer
    sub sp, 4                           ;Allocate stack space for locals
    pusha                               ;Save registers to stack

    mov di, [bp + 08]                   ;Parm 3 - ptr to variable

    mov word ptr [di], 10   ; <---- Doesn't work. di contains an address, 
                            ;       but what it points at doesn't get updated

    popa                                ;Restore registers from stack
    mov sp, bp                          ;Remove local vars by restoring sp
    pop bp                              ;Restore base pointer from stack
    ret 6                               ;Return and also clean up parms on stack
_testProc endp
4

2 に答える 2

3

8086は、セグメントレジスタとインデックスレジスタの内容を組み合わせて生成し、アドレス指定します。それを[SR、IR]として示します。

レジスタdiを介した更新は、[DS、DI]で定義された場所を更新しています。特別なプレフィックスのないmov命令は、デフォルトでDSレジスタを使用します。他のセグメント(ES?SS?)のオフセットとしてアドレスDIを取得した場合、実際には間違ったレジスタを組み合わせて、目的のアドレスにヒットしています。

あなたの間違いは、あなたのルーチンに「ポインタ」を渡すための規則が何であるかについて明確になっていないことです。定義したものは、DSからの相対オフセットを想定しています。

于 2012-12-02T07:27:46.483 に答える
2

あなたができる最善のことは、できるだけ早く16ビットのセグメント化されたコードを放棄することです!:)

それができない場合は、それを指す「遠いデータ」と「遠いポインタ」があります。あなたの「proc」はそれが近いか遠いかを言いません-私は近いと思います(またはParm3はおそらくあなたがスタック上にあると思う場所ではありません...遠いリターンアドレスは4バイトなので)。変更しようとしている変数がスタック上にある場合は、さらに複雑になります。mov word ptr ss:[di], 10少なくとも。ローカル変数または静的変数のいずれかを処理する必要がある場合は、それを見つけるためにfarポインター(4バイト、セグメント、およびオフセット)が必要になると思います。

最初に頭に浮かんだのは、逆参照されたポインターの値を変更しようとしていると言っているのですが、(私が理解しているように)間接参照していないということです。mov di, [di]スタックから値を取得してから試してください。とにかく、試すのは簡単です。:)

他のすべてが失敗した場合は、呼び出し元のコードを表示してください。(そして、できるだけ早く32ビットコードに取り掛かってください!)

于 2012-12-02T11:29:25.610 に答える