Assembly 我可以在ARM组件中的程序(PROC/ENDP)之外进行分支吗?

Assembly 我可以在ARM组件中的程序(PROC/ENDP)之外进行分支吗?,assembly,arm,Assembly,Arm,文档对此没有提及。如果我像这样编写代码并调用条,会发生什么?有什么负面后果吗 foo PROC ... BX lr ENDP bar PROC B foo ENDP 更新 从技术上讲,这样做是完全合法的。代码编译并正常工作。正如一些人所注意到的,对象文件中的某些元信息需要PROC指令。我担心以这种方式使用它(如上面的示例中),我可能会“破坏”此信息,并产生未知的后果 该指令的描述中说: 当为ELF生成矮人调用帧信息时,汇编程序使用PROC

文档对此没有提及。如果我像这样编写代码并调用
,会发生什么?有什么负面后果吗

foo PROC
    ...
    BX    lr
    ENDP

bar PROC
    B     foo
    ENDP
更新

从技术上讲,这样做是完全合法的。代码编译并正常工作。正如一些人所注意到的,对象文件中的某些元信息需要
PROC
指令。我担心以这种方式使用它(如上面的示例中),我可能会“破坏”此信息,并产生未知的后果

该指令的描述中说:

当为ELF生成矮人调用帧信息时,汇编程序使用PROC来标识函数的开始。PROC将规范帧地址设置为R13(SP),帧状态堆栈设置为空


我不擅长调试器的工作方式,但如果我没有弄错的话,调用框架意味着与堆栈相关的东西。由于我没有在函数中使用堆栈,我可以得出结论,这些信息对我来说并不重要。我说得对吗?

PROC
这样的注释是为了工具的好处-例如,指示为该标签生成的ELF符号应标记为函数,而不是数据。链接、调试等需要所有对象文件元信息,但除了通知动态加载程序如何映射段以及在何处映射段外,它与执行中的实际代码和数据无关


换一种方式考虑:函数调用本身只是一个分支,因此,如果在指令集级别不允许它在“函数”之外分支,那么您实际上可以编写什么样的有用代码呢?;)

这是完全合法的。编译器有时也会生成如下代码:

int foo(int x)
{
    return x*x*4 + x*7 + 1;
}

int bar(int x)
{
    printf("Hello bar");
    return foo(x);
}

这段代码很可能是从bar内部跳转到foo,而不是调用并立即返回。

您使用的是什么芯片体系结构和汇编程序?有任何负面后果吗?如果你这样编程,你会陷入混乱。如果
bar
的C版本是
void bar(){foo();}
(即,
bar
以调用
foo
结束,因此您可以让
foo
负责返回到调用
bar
的人,而不是返回到
bar
,并让
bar
返回其调用者)。否则,不要这样做。我说的是这样一种情况,即你完全在汇编中实现某些东西,并控制推送和弹出的内容。你可以在汇编中做任何你想做的事情,甚至使计算机崩溃。Proc和end等严格用于工具,并帮助一些试图将汇编变成hi的人更高级的语言,如果你不想使用它们,你根本不需要使用它们,而且它们绝不会限制你做你想做的事情,你只需要知道它们对代码做了什么,如果有的话,并使用它们当为ELF生成矮人调用帧信息时,汇编程序使用PROC来标识函数的开始"。那么你对元信息的看法是对的。但是它对调试、链接和使用加载程序真的很关键吗?我不太擅长调试器的工作方式。假设你将
foo
构建为拇指代码-如果链接器不知道
是什么类型的符号,并用实际指令地址填充
blx foo
重定位,则ra除了为正确的交互设置底部位之外,您还将度过一段不愉快的时光。然后,当您尝试调试意外的崩溃时,调试器还尝试将其作为ARM指令进行反汇编,并显示乱码;)这是有意义的。如果编译器可以生成这样的跳转,我也可以!