在汇编中有条件地调用子例程

问题描述 投票:0回答:5

我正在学习 x86 汇编。我想知道你如何有条件地调用子例程。 据我了解,跳转到标签不起作用,因为返回地址未存储,因此它不知道返回哪里。

 cmp bx, 0
 jz zero ; how do I do this correctly ?
 ; do something else and exit

 zero:
 ; do something
 ret
assembly x86
5个回答
7
投票

干净的方法很简单:

    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

对于 if-else 情况我不知道有更好的方法。好的,如果两个分支之后都必须直接返回,你可以这样做:

    cmp bx,0
    jnz notzero
    ; handle case for zero here
    ret

notzero:
    ; handle case for not zero here
    ret

如果必须在 ret 之前进行某些处理(例如弹出之前推送的值),则应使用第一种方法。


6
投票

如果您不需要返回该地址,它就可以了。很多时候,您可以按照这种情况构建代码。

否则,您将不得不使用

Jxx
指令进行分支,这些指令会在调用站点之间跳转,或者以其他方式围绕此限制构建代码。在这种情况下,反转测试应该有效:

    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

编辑2016-04-25:正如@Peter Cordes 在评论中提到的,下面的代码可能会表现得很糟糕。参见例如这篇文章解释原因。

@Manny D 评论中的建议启发我写了以下内容。它可能不会更干净或更好,但这是另一种构建它的方式:

    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

它显式地将返回地址压入堆栈,以便如果我们不调用该函数(重新调整堆栈),

zero
函数可以从堆栈返回或弹出值(
add esp, 4
)。请注意,如果您希望它在 16 位或 64 位模式下工作,您需要做一些细微的调整。


1
投票

我相信正确的方法是使用

call
指令。这相当于高级编程语言中的函数调用。 PC 存储在堆栈中,因此
ret
子例程末尾的
zero:
会执行其预期的操作。


0
投票

代替“ret”标签只需使用“pop”到任何寄存器

示例

` cmp bx, 0 零零 xor ax ;这是为了稍后清理“ax”寄存器给我们 ;做点别的事然后退出

零: ;做一点事 流行斧头`


-1
投票

如果我理解正确,你正在寻找的是例如 如果 CMP 的结果为零,则进行 CALL 而不是 JMP。一种解决方法是使用临时子函数来调用预期函数

示例:在下面的#4 程序中,您执行 CMP,然后 Jz 到 (made_up) 标签,然后使用该 (made_up) 标签来调用您想要的实际函数。

    #1 instruction xxx,xxx
    #2 instruction xxx,xxx
    #3 instruction xxx,xxx
    #4 CMP XXX , XXX 
    #5 JZ Made_up
    #6 Made_up:
    #7  call your_function
    #8 next instruction address will be pushed to stack as your return address.


    cmp xxx, xxx
    jz Made_up

    Made_UP:
        call your_Function
    ;now you will have the return address saved onto the stack to return to.

希望这有帮助...

© www.soinside.com 2019 - 2024. All rights reserved.