不使用其他跳转的条件函数调用?
Conditional function call without using other jumps?
我想根据寄存器的内容调用一个过程。过程完成后,它应该 return 到调用地址,以便程序可以继续执行 call
操作码之后的代码,否则它应该忽略它并继续执行其余代码。
我试图避免使用 jcc
有条件地跳过 call
,就像 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
如何在不使用跳转的情况下实现这一点?
您想在汇编代码中实现一个 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 分支代码放在 if 分支之前以获得更符合逻辑的条件跳转(因为在第一个示例中我们测试相等性但如果不相等则跳转)。使用第二个选项,汇编代码将是
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
I want to call a procedure depending on the contents of a register. ...I'm trying to avoid using a jump here. Is it possible?
...
How would one implement this without using a jump?
遗憾的是,大多数 CPU 仅支持 jump/branch 条指令的条件执行。
ARM CPU 支持几乎所有指令的条件执行;历史悠久的 8080 和兼容机(8085、Z80)除了跳转之外还支持 CALL
和 RET
的条件执行。
然而,x86 CPU 和大多数 CPU 一样:只有跳转指令可以有条件地执行。
假设地,您或许可以在 RAM 中使用自修改代码来有条件地执行任何指令,而无需使用跳转指令。但是,这样做仅对某些可行性研究有用,对任何实际用例都没有用。
我想根据寄存器的内容调用一个过程。过程完成后,它应该 return 到调用地址,以便程序可以继续执行 call
操作码之后的代码,否则它应该忽略它并继续执行其余代码。
我试图避免使用 jcc
有条件地跳过 call
,就像 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
如何在不使用跳转的情况下实现这一点?
您想在汇编代码中实现一个 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 分支代码放在 if 分支之前以获得更符合逻辑的条件跳转(因为在第一个示例中我们测试相等性但如果不相等则跳转)。使用第二个选项,汇编代码将是
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
I want to call a procedure depending on the contents of a register. ...I'm trying to avoid using a jump here. Is it possible? ... How would one implement this without using a jump?
遗憾的是,大多数 CPU 仅支持 jump/branch 条指令的条件执行。
ARM CPU 支持几乎所有指令的条件执行;历史悠久的 8080 和兼容机(8085、Z80)除了跳转之外还支持 CALL
和 RET
的条件执行。
然而,x86 CPU 和大多数 CPU 一样:只有跳转指令可以有条件地执行。
假设地,您或许可以在 RAM 中使用自修改代码来有条件地执行任何指令,而无需使用跳转指令。但是,这样做仅对某些可行性研究有用,对任何实际用例都没有用。