汇编指令 call、ret、jump 的区别
call、ret、jump 指令介绍
call
用于调用子程序,在调用前会保存返回地址(x86 架构下,段内跳转时只保存 EIP;段间跳转还会保存 CS)。ret
会返回到call
指令的下一行,也就是跳转前已保存的返回地址。通常在函数调用时,call
和ret
都是成对出现的。jmp
会直接进行跳转,不会保存返回地址,jmp
之后的指令如果跟了ret
,那就直接退出到上一个call
指令对应的下一行。
call 和 ret 使用方法
call 和 ret 指令用来调用子程序和从子程序返回:
call 的使用方法:call 子程序入口处地址,该地址可以是标号,也可以存放在寄存器和内存中。
ret 的使用方法:直接在子程序中使用 ret 指令即可,可以没有参数,执行该指令会直接返回至调用子程序的位置处。
之前遇到的一个 bug
函数 A 调用函数 B,然后在函数 B 里进行协程切换,进入到协程上下文(此时还没有结束函数调用)。在新的协程上下文中,使用 ret $27
,gcc 编译能够跳转到 $27 指定的地址处,clang 编译则会忽略 $27 的值,clang 编译器规定 ret 指令编译成 ret $ra,从而导致报错。