lll*_*lll 23 c assembly calling-convention
基本上我试图在C中模拟汇编代码.
这是C代码:
int main()
{
test();
main_next:
printf("Hello, World!");
}
void test()
{
goto main_next;
}
Run Code Online (Sandbox Code Playgroud)
尝试编译此代码(Linux 32位,gcc 4.6.3),我收到此错误:
error: label ‘main_randomtag_next’ used but not defined
Run Code Online (Sandbox Code Playgroud)
有谁知道如何在C中进行这种程序间的转换?
谢谢!
Joh*_*ica 33
goto如果你考虑堆栈,函数之间没有任何意义.跳跃时会在堆叠中出现什么?源和目标函数可能具有不同的参数和不同的返回值.新功能将返回谁?它的返回值是否对调用者有意义?调用者调用源函数,而不是目标函数.
仔细考虑你的例子:
int main()
{
test();
main_next:
printf("hello, world);
}
void test()
{
goto main_next;
}
Run Code Online (Sandbox Code Playgroud)
goto执行时会发生什么?我认为你希望这会将堆栈跳回到调用main()函数.该goto会有效地相同的return,从改变调用堆栈:
main() main()
| to
+--> test()
Run Code Online (Sandbox Code Playgroud)
但是如果你想跳转到不在调用堆栈中的函数呢?然后怎样呢?
另一种解释是,用一个goto替换现有的test()呼叫main().调用堆栈将改为:
main() main()
| to |
+--> test() +--> main()
Run Code Online (Sandbox Code Playgroud)
现在main()是递归调用自己,并且较低的main()将返回到upper main()-who,顺便说一下,期望void返回值但是将接收到int.
你最接近的是setjmp/ longjmp.这些允许您保存和恢复非本地goto的堆栈上下文,允许您在函数调用之间跳转.
setjmp并longjmp解决我所描述的问题:(a)跳转时保存和恢复完整的堆栈上下文,以及(b)如果堆栈上下文不再有效则不允许跳转.我引用了手册页(强调我的):
setjmp()和longjmp(3)对于处理程序的低级子例程中遇到的错误和中断很有用.setjmp()将堆栈上下文/环境保存在env中,供以后使用longjmp(3).如果调用setjmp()的函数返回,则堆栈上下文将无效.
换句话说,longjmp基本上是C等同于抛出异常.低级函数可以展开调用堆栈并在更高级别的函数中恢复执行.
使用它也非常棘手,很少有好主意.再次,从手册页:
setjmp()和sigsetjmp()使程序难以理解和维护.如果可能,应使用替代方案.
GCC首先生成汇编文件,然后才汇编它,那么使用内联汇编创建标签呢?
void test()
{
__asm__ volatile (
"jmp main_next"
);
}
int main()
{
test();
__asm__ volatile (
"main_next:"
);
printf("hello, world");
}
Run Code Online (Sandbox Code Playgroud)
但是,这(显然)不应该在实际情况下使用,因为它根本不处理堆栈.