2016-11-21 5 views
0

チューリングマシンのシミュレーションのようなこのコード。私はこのコードを検出していると私はそれは大丈夫だが、私はCALLと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 

答えて

2

RETがスタックに書き込みをしないで、スタックの内容を変更する方法を理解していない変更のひとつひとつのステップについてのテーブルを作りましたSPを変更します。 CALLはスタックにリターンアドレスを書き込み、SPを変更します。

スタックに書き込むことができる唯一の値は、CALLの後の命令のIPなので、とちょうど CALL命令とRET命令では大したことはできないと思います。

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

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) 

は、しかし、オフセットプッシュは、コードセグメントcs内にあるとして、これは、32bのモードでより多くの利用可能性が非常に高いです16bリアルモードでは、単一のセグメントにすべてを持つコードとcs = dsでのみうまく動作します(便利です)。たとえば、ほとんどの ".com"実行可能ファイルはこの記述に適合します。

あなたのコードがより多くのセグメントを使用している場合、その印刷ルーチンは、あまり一般的ではないcs:によってその文字列をアドレス指定する方法で書かれなければなりません。

関連する問題