0

このコードは、チューリング マシンのシミュレーションのようなものです。私はこのコードを検出しており、変更のすべてのステップについて表を作成しましたが、それは問題ありませんが、CALL AND RETでスタックの内容を変更する方法がわかりません

.model small
.data
bant db 0,0,0,0,0,0,0,0,0

.code
.startup

mov si,4
call stateA
.exit

stateA proc near
cmp bant[si],0
je AB
jmp AC

AB:
mov bant[si],1
inc si
call stateB
jmp RTA

AC:
mov bant[si],1
dec si
call stateC

RTA: ret
stateA endp

stateB proc near
cmp bant[si],0
je BA
jmp BB

BA:
mov bant[si],1
dec si
call stateA
jmp RTB

BB:
mov bant[si],1
inc si
call stateB

RTB: ret
stateB endp
stateC proc near
cmp bant[si],0
je CB
jmp CHLT

CB:
mov bant[si],1
dec si
call stateB
jmp RTC

CHLT:
mov bant[si],1
inc si

RTC: ret
stateC endp

end
4

2 に答える 2

3

RET はスタックに書き込みませんが、SP を変更します。 CALLは、リターン アドレスをスタックに書き込み、SP を変更します。

スタックに書き込める値はCALL後の命令のIPだけなので、CALL命令とRET命令だけではたいしたことはできないと思います。

おそらく、MOV 命令やその他の命令を使用して通常の方法で行う必要があります。通常[BP]、スタック フレームを作成した後、 に相対的なアドレッシング モードを使用します。

于 2016-11-21T08:33:20.657 に答える
1

スタックの一番上にある値のオフセットをロードする方法があります。

    call print_message   ; address of string is pushed on top of stack
    db "some text message to print",0  ; defined inside code
print_message:
    call some_print_function ; which want single argument on stack as "ptr to string"
    ; restore stack as needed (but don't do "ret", it would execute string)

しかし、プッシュされたオフセットはコード セグメント内にあるため、これは 32b モードでより多く使用される可能性が非常に高いcsため、16b リアル モードでは、すべてが単一セグメントおよびcs = ds. たとえば、ほとんどの「.com」実行可能ファイルは、この説明に適合します。

コードがより多くのセグメントを使用している場合、その印刷ルーチンは、 を介してその文字列をアドレス指定する方法で作成する必要がありますがcs:、これはあまり一般的ではありません。

于 2016-11-21T13:26:03.617 に答える