2016-11-21 56 views
0

這個代碼就像模擬圖靈機一樣。我正在檢測這個代碼,我提出要改變它的確定,但我不明白如何改變堆棧內容與CALL和RET如何通過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) 

但是,這是極有可能更多的使用在32B模式下,按下的偏移是內部代碼段cs,所以在16b真實模式,這將工作得很好(方便)只有代碼,其中包含單個部分的所有內容和cs = ds。例如,大多數「.com」可執行文件都適合這種描述。

如果你的代碼使用了更多的段,那麼這個打印例程必須以通過cs:尋址該字符串的方式寫入,這種方式並不常見。