Assembly 如何使用call和ret更改堆栈内容?

Assembly 如何使用call和ret更改堆栈内容?,assembly,emu8086,Assembly,Emu8086,此代码类似于图灵机的模拟。我检测到了这段代码,我制作了一个关于更改的每一个步骤的表格。这没关系,但我不知道如何使用调用和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 RT

此代码类似于图灵机的模拟。我检测到了这段代码,我制作了一个关于更改的每一个步骤的表格。这没关系,但我不知道如何使用调用和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

RET不会写入堆栈,但会修改SP。它会将返回地址写入堆栈,并修改SP

您可以写入堆栈的唯一值是调用后指令的IP,因此我认为仅使用CALL和RET指令不太可能


您可能需要使用MOV指令和其他指令以正常方式进行操作。通常在制作堆栈帧后,使用相对于
[BP]
的寻址模式。

RET不会写入堆栈,但会修改SP。将返回地址写入堆栈,并修改SP

您可以写入堆栈的唯一值是调用后指令的IP,因此我认为仅使用CALL和RET指令不太可能


您可能需要使用MOV指令和其他指令以正常方式进行操作。通常在制作堆栈帧后,使用相对于
[BP]
的寻址模式。

有一个巧妙的技巧,如何在堆栈顶部加载某个值的偏移量:

    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:
,对该字符串进行寻址,这并不常见。

有一个巧妙的技巧,如何在堆栈顶部加载某个值的偏移量:

    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:
编写打印例程来处理该字符串,这并不常见