首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从内联程序集跳转到AVR32上的错误目标

从内联程序集跳转到AVR32上的错误目标
EN

Stack Overflow用户
提问于 2019-06-13 11:50:54
回答 1查看 334关注 0票数 0

我们正在使用AVR32 7.0.1645为Atmel AVR32/ UC3C0512C开发一个应用程序。在做一些基本的测试时,我注意到了一些非常奇怪的事情。

请考虑以下代码(我知道这是不好的风格和不常见的,但这不是重点):

代码语言:javascript
复制
float GetAtan2f(float p_f_y,
                float p_f_x)
{
  unsigned int l_ui_x,
               l_ui_y,
               l_ui_Sign_x,
               l_ui_Sign_y,
               l_ui_Result;

  float l_f_Add,
        l_f_Result;

  asm volatile(
    "RJMP GETATAN2_EXIT \n"
    :
    : /* 0 */ "m" (p_f_y),
      /* 1 */ "m" (p_f_x)
    : "cc", "memory", "r0", "r1", "r2", "r3", "r5"
  );

  GETATAN2_EXIT:
  return (l_f_Result);
}

在查看该代码的反汇编(编译/链接后)时,我发现如下:

代码语言:javascript
复制
Disassembly of section .text.GetAtan2f:

00078696 <GetAtan2f>:
   78696:   eb cd 40 af     pushm   r0-r3,r5,r7,lr
   7869a:   1a 97           mov r7,sp
   7869c:   20 9d           sub sp,36
   7869e:   ef 4c ff e0     st.w    r7[-32],r12
   786a2:   ef 4b ff dc     st.w    r7[-36],r11
   786a6:   e0 8f 00 00     bral    786a6 <GetAtan2f+0x10>
   786aa:   ee f8 ff fc     ld.w    r8,r7[-4]
   786ae:   10 9c           mov r12,r8
   786b0:   2f 7d           sub sp,-36
   786b2:   e3 cd 80 af     ldm sp++,r0-r3,r5,r7,pc

我们注意到,rjmp已经成为bral --完全可以接受,只是同一件事的另一个助记符。

但是,当查看该行中的分支目标时,我们还注意到这将产生一个无止境的循环,显然它不应该这样做,它应该分支到786aa (函数返回的开始),而不是786a6

如果我更改代码,使其读到

代码语言:javascript
复制
float GetAtan2f(float p_f_y,
                float p_f_x)
{
  unsigned int l_ui_x,
               l_ui_y,
               l_ui_Sign_x,
               l_ui_Sign_y,
               l_ui_Result;

  float l_f_Add,
        l_f_Result;

  asm volatile(
    "RJMP GETATAN2_EXIT \n"
    :
    : /* 0 */ "m" (p_f_y),
      /* 1 */ "m" (p_f_x)
    : "cc", "memory", "r0", "r1", "r2", "r3", "r5"
  );

  asm volatile(
    "GETATAN2_EXIT: \n"
    :
    :
    : "cc", "memory"
  );

  return (l_f_Result);
}

它按预期工作,即反汇编现在读取。

代码语言:javascript
复制
Disassembly of section .text.GetAtan2f:

00078696 <GETATAN2_EXIT-0x12>:
   78696:   eb cd 40 af     pushm   r0-r3,r5,r7,lr
   7869a:   1a 97           mov r7,sp
   7869c:   20 9d           sub sp,36
   7869e:   ef 4c ff e0     st.w    r7[-32],r12
   786a2:   ef 4b ff dc     st.w    r7[-36],r11
   786a6:   c0 18           rjmp    786a8 <GETATAN2_EXIT>

000786a8 <GETATAN2_EXIT>:
   786a8:   ee f8 ff fc     ld.w    r8,r7[-4]
   786ac:   10 9c           mov r12,r8
   786ae:   2f 7d           sub sp,-36
   786b0:   e3 cd 80 af     ldm sp++,r0-r3,r5,r7,pc

我们注意到现在的分支目标是正确的。

因此,内联汇编程序显然不知道C标签(即不在内联程序集中的标签),这本身是可以的。-经验教训。

但是,另外,当遇到未知(未定义)标签时,不会发出警告或抛出错误,而是在分支/跳转到这样的标签时只使用0的偏移量产生无穷无尽的循环。

我认为后者是一个灾难性的错误。这可能意味着(在没有任何警告的情况下),每当我在内联汇编代码中使用未定义的标签(例如,由于错误)时,我的软件中就会有一个没完没了的循环。

我能做些什么吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-06-13 13:28:08

如果您不告诉编译器您的asm语句的另一面可能不会执行,编译器就会假设是这样的。

所以这两个例子都是不安全的,幸运的是,第二个例子没有破坏任何东西,因为函数太简单了。

我不知道您的代码是如何编译的;C本地标签通常不会以同名asm标签的形式出现。如果编译器生成的代码使用它们,gcc就会使用像.L1这样的名称,就像它为if()for/while循环创建的分支目标一样。@Kampi用AtmelStudios 7.0.1931报告源代码的链接器错误。

实际上,您正在查看一个非链接的.o**,,其中分支目标只是一个由链接器**填充的占位符。(对未定义符号的引用是等待发生的链接器错误)。e0 8f 00 00的编码当然符合这一点:汇编程序没有在编译器给它的.s中找到分支目标标签,所以它将它作为外部符号来处理,并使用了一个具有更多移位字节的分支。显然,在AVR32上,相对分支位移相对于分支指令的开始,与许多ISAs不同,后者相对于分支的结束。(也就是说,当指令被解码/执行时,PC已经增加了。)

因此,这将解释为什么您缺少链接器错误(因为您从未运行链接器),并看到一个虚假的分支目标。更新:这个是正在链接,但被链接到一个库中。因此,库本身仍然有一个未解决的符号.

在另一个内联asm语句中定义的目标存在于编译器的asm输出中,因此汇编程序可以找到它并使用简短的rjmp

(一些汇编程序通过要求extern foo声明来帮助您捕捉这样的错误。GAS没有;它只是假定任何未定义的符号都是extern。GAS语法来自传统的Unix汇编程序,这些编译器设计用于汇编编译器输出,在这种情况下,一次只编译一个C函数(而不是整个文件优化)的古编译器不知道函数的定义是出现在这个.c文件中还是单独的.c文件中。因此,这个语法允许在没有足够内存的机器上对C进行一次编译,并为后面在asm输出中未定义的符号添加extern声明。)

GNU asm goto使此安全

GNU C内联asm确实有用于跳出内联-asm语句(到C标签)的语法。https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#GotoLabels。然后看一个关于SO的例子:GCC装配线上的标签。(使用x86指令,但asm模板的内容与如何使用asm goto语法无关。)

在没有条件代码/标志输出的GCC6语法的目标上,使用内联some_label: return true;中的条件分支跳转到some_label: return true;或切换到return false;是一种方便的方法。(使用条件标志作为GNU C内联asm输出)

但是根据提交消息的说法,Linux内核放弃AVR32支持的原因是,AVR32 gcc被困在gcc4.2。asm goto只出现在gcc4.5中。

除非编译器是(基于?)更近一点的gcc,你根本不能安全地做到这一点。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56579861

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档