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 回答