我刚开始编写汇编(字面意思是我的第一天),我很好奇是否有任何副作用使用call
但从未使用ret
。
如果没有副作用,有时候只是退缩是不好的做法吗?
代码简单如下:
my_func:
call is_digit
call is_lowercase
jmp error
is_lowercase:
cmp al, 'a'
jb isfalse
cmp al, 'z'
ja isfalse
jmp lowercase
is_digit:
cmp al, '0'
jb isfalse
cmp al, '9'
ja isfalse
jmp digit
isfalse:
ret
error:
some stuff
在这种背景下有意义吗?
答案 0 :(得分:3)
如果AL既不是数字也不是小写,您的代码将正确跳转到错误。
如果它确实是一个数字,你跳转到数字但那里你应该从堆栈中删除返回地址。如果这是16位代码,请使用add sp,2
;如果是32位代码,请使用add sp,4
或者在执行jmp
之前插入此额外指令此处。
is_digit:
cmp al, '0'
jb isfalse
cmp al, '9'
ja isfalse
add sp,2 ;Don't return from "call is_digit"
jmp digit
之前的所有内容也适用于您使用小写的方式。
如果你有一个备用的注册表(比如DX),你可以将add sp,2
缩短为pop dx
。同样适用于add sp,4
到pop edx
。
答案 1 :(得分:1)
如果您以某种方式控制程序流程,则不会。例如,由于某种原因,您希望无限期挂起:
foo:
jmp foo
ret
添加ret
是没有意义的,因为无论如何都无法达到。
当然你不需要ret
。您也可以从堆栈中弹出返回地址并在之后跳转到它,这基本上会产生相同的结果,但这通常是一个好主意,因为ret
也标记了函数的结束。
实现函数调用的另一种方法可能是:将寄存器保存在寄存器中,然后在需要时跳转到寄存器。事实上,这将比正常ret
更快,因为它不使用慢速堆栈,但读取和理解起来要复杂得多。
当然,您可能会争论汇编是否实际上是可读的; - )