条件函数调用而不使用其他跳转?

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

我想根据寄存器的内容调用一个过程。在程序完成后,它应该返回到调用地址,以便程序可以继续执行call操作码之后的代码,否则它应该忽略它并继续执行其余的代码。

我试图避免只是有条件地用call跳过jcc,就像call subroutines conditionally in assembly描述的答案一样。

可能吗?像这样的东西:

    cmp al,41h      ;check if register has value 41h
    call setAsize   ;call procedure if it does, otherwise ignore and continue executing code
   //more code to execute here


setASize:
    mov al,4d   ;change register content
    ret         ;return to call address so that code following call opcode can continue being executed

如何在不使用跳跃的情况下实现此目的?

assembly x86 nasm micro-optimization
2个回答
3
投票

您希望在汇编代码中实现if-else结构,如以下C代码中所示

if (al == 0x41) { // we keep your example values
    // do something
    setASize();
} else {
    // do something else
    // not present in your code but there for the sake of completeness
}

在汇编中,您将通过以下方式编写此代码:

    cmp al, h41             ; this is the comparison, which sets flags 
    jne elseBranch          ; if the zero flag is *not* set (al != h41) jump to elseBranch
                        ; the jne instruction can be replaced with any other conditional
                        ; jump to adjust to the test condition
ifBranch:               ; useless label for clarity
    call setASize           ; this is the actual if-code (do-something)
    jmp endIf               ; now jump to the end of the if to avoid the else-branch
elseBranch:
                        ; nothing in your code, but this is where you put
                        ; your else instructions
endIf:
; now is the code after your if-else block, which will be executed in any case

这是在汇编中编写if-else块的两种经典方法之一(原因只是指令更改相同)。另一个选择是将else-branch代码放在if-branch之前,以获得更多逻辑条件跳转(因为在第一个示例中,我们测试相等性,但如果不相等则跳转)。使用第二个选项,汇编代码将是

    cmp al, h41             ; this is the comparison, which sets flags 
    je ifBranch             ; if the zero flag is *not* set (al != h41) jump to elseBranch
                        ; the jne instruction can be replaced with any other conditional
                        ; jump to adjust to the test condition
elseBranch:             ; useless label for clarity
                        ; nothing in your code, but this is where you put
                        ; your else instructions
    jmp endIf               ; now jump to the end of the if to avoid the else-branch
ifBranch:
    call setASize           ; this is the actual if-code (do-something)
endIf:
; now is the code after your if-else block, which will be executed in any case

在你的情况下,由于没有其他分支,首选选项(只需要一次跳转,因为你不需要跳转到elseBranch标签(并且不需要第二次endIf跳转)。


对于您的代码,最终的答案是:

    cmp al,41h
    jne endIf
    call setAsize
endIf:
                    ; more code here

setASize:
    mov al,4d
    ret

4
投票

我想根据寄存器的内容调用一个过程。 ......我试图避免在这里使用跳跃。可能吗? ......如何在不使用跳跃的情况下实现这一目标?

不幸的是,大多数CPU仅支持跳转/分支指令的条件执行。

ARM CPU支持几乎所有指令的条件执行;历史悠久的8080和兼容性(8085,Z80)支持CALLRET的条件执行以及跳跃。

但是,x86 CPU与大多数CPU类似:只有跳转指令才能有条件地执行。

假设您可以在RAM中使用自修改代码来有条件地执行任何指令而无需使用跳转指令。但是,这样做只对某些可行性研究有用,而不适用于任何实际用例。

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