cmp bx,0
jnz notzero
; handle case for zero here
jmp after_notzero
notzero:
; handle case for not zero here
after_notzero:
; continue with rest of processing
cmp bx, 0
jnz not_zero
call zero
; fall through here, return or do what you want
not_zero:
; do something else and exit
; ...
ret
zero:
; do something
ret
push back_from_zero ; Push where we want to return after possibly branching to 'zero'
cmp bx, 0
jz zero ; branch if bx==0
add esp, 4 ; adjust stack in case we didn't branch
back_from_zero: ; returning from the zero branch here or continuing from above
; do something else and exit
zero:
; do something
ret
3条答案
按热度按时间pxiryf3j1#
简单的方法是:
对于if-else情况,我不知道更好的方法。好的,如果两个分支都必须在之后直接返回,可以执行以下操作:
如果某些处理必须在ret之前发生(例如弹出先前推送的值),则应使用第一种方法。
uqjltbpv2#
如果你不需要返回到那个地址,它是有效的。通常你可以这样构造你的代码。
否则,你就必须使用
Jxx
指令来执行分支,这些指令会在调用点周围跳转,或者用其他方式来构建代码来避开这个限制。2016年04月25日第二次世界大战正如@Peter Cordes在评论中提到的,下面的代码可能会表现得很糟糕。请参见this article以了解原因。*
@Manny Ds在评论中的建议启发了我写了下面的内容。它可能不会更干净或更好,但它是另一种结构方式:
它显式地将返回地址压入堆栈,这样
zero
函数就可以返回值(add esp, 4
),或者如果我们不调用该函数(重新调整到堆栈),就可以从堆栈中弹出值(add esp, 4
)。注意,如果你想让它在16位或64位模式下工作,你需要做一些细微的调整。dhxwm5r43#
我认为正确的方法是使用
call
指令,这相当于高级编程语言中的函数调用,PC存储在堆栈中,因此zero:
子例程末尾的ret
执行它应该执行的操作。