如果你打电话但从未退回会怎么样?

时间:2015-10-02 17:29:10

标签: assembly nasm

我刚开始编写汇编(字面意思是我的第一天),我很好奇是否有任何副作用使用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

在这种背景下有意义吗?

2 个答案:

答案 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,4pop edx

答案 1 :(得分:1)

如果您以某种方式控制程序流程,则不会。例如,由于某种原因,您希望无限期挂起:

foo:
    jmp foo
    ret

添加ret是没有意义的,因为无论如何都无法达到。

当然你不需要ret。您也可以从堆栈中弹出返回地址并在之后跳转到它,这基本上会产生相同的结果,但这通常是一个好主意,因为ret也标记了函数的结束。

实现函数调用的另一种方法可能是:将寄存器保存在寄存器中,然后在需要时跳转到寄存器。事实上,这将比正常ret更快,因为它不使用慢速堆栈,但读取和理解起来要复杂得多。

当然,您可能会争论汇编是否实际上是可读的; - )