【问题标题】:SPARC assembly jmp \bootSPARC 程序集 jmp \boot
【发布时间】:2018-03-28 13:05:23
【问题描述】:

我会简单地解释一下这个问题。我有一块 Leon3 板(gr-ut-g99)。使用 GRMON2,我可以将可执行文件加载到板上所需的地址。

我有两个程序。让我们称它们为 A 和 B。我尝试将它们加载到内存中并单独它们工作。

我现在想做的是让A程序调用B程序。

这两个程序都是使用 gcc 编译器的变体(Gaisler Sparc GCC)用 C 语言编写的。

为了进行跳转,我在程序 A 中编写了一个小型内联汇编函数,该函数跳转到我加载程序 B 的内存地址。

在程序 A 的 sn-p 之下

 unsigned int return_address;
 unsigned int * const RAM_pointer = (unsigned int *) RAM_ADDRESS;
 printf("RAM pointer set to: 0x%08x \n",(unsigned int)RAM_pointer);
 printf("jumping...\n");

 __asm__(" nop;" //clean the pipeline
         "jmp %1;" // jmp to programB
       :"=r" (return_address)
       :"r" (RAM_pointer)
     );

RAM_ADDRESS 是一个#define

#define RAM_ADDRESS 0x60000000

程序 B 是一个简单的 hello world。程序 B 在 0x60000000 地址加载。如果我尝试运行它,它会起作用!

int main()
{
  printf ("HELLO! I'M BOOTED! \n");
  fflush(stdout);

  return 0;
}

当我运行 ProgramA 时,我期望在控制台上看到“正在跳跃...”消息,然后看到“您好!我已启动!”来自程序B

会发生什么,而不是 IU 异常。 下面我发布了 grmon2 监视器显示的消息。我还报告了“inst”报告,该报告应显示异常之前执行的最后操作。

  grmon2> run

  IU exception (tt = 0x07, mem address not aligned)

  0x60004824: 9fc04000  call  %g1


grmon2> inst
  TIME     ADDRESS   INSTRUCTION                   RESULT      SYMBOL

   407085  600047FC  mov  %i3, %o2                 [600063B8]  -

   407086  60004800  cmp  %i4                      [00000013]  -

   407089  60004804  be  0x60004970                [00000000]  -

   407090  60004808  mov  %i0, %o0                 [6000646C]  -

   407091  6000480C  mov  %i4, %o3                 [00000013]  -

   407092  60004810  cmp  %i4, %l0                 [80000413]  -

   407108  60004814  bleu  0x60004820              [00000000]  -

   407144  60004818  ld  [%i1 + 0x20], %o1         [FFFFFFFF]  -

   407179  60004820  ld  [%i1 + 0x28], %g1         [FFFFFFFF]  -

   407186  60004824  call  %g1                     [  TRAP  ]  -

我还尝试将“jmp”替换为“jmpl”或“c​​all”,但没有成功。 我很困惑。 我不知道如何很好地处理这个问题,因此我不知道还需要提供哪些其他信息。

我可以说,programB 在 0x60000000 加载,entry_point 当然是 0x60000000。从该入口点直接运行程序 B 效果很好!

提前感谢您的帮助!

【问题讨论】:

  • ld [%i1 + 0x28], %g1 [FFFFFFFF]: 看起来结果是FFFFFFFF,似乎你正试图跳转到 FFFFFFFF (通过“地址未对齐”错误以某种方式确认(PC 需要在偶数地址)
  • 顺便说一下,如果你不需要跳转,你可以使用普通的C语言和函数指针。
  • 小丑是对的。使用带参数的内联汇编并不是最简单的事情。如果你可以在纯 C 中做到这一点,那就去做吧。
  • 显示的反汇编不是程序A的反汇编。另外,GCC官方不支持asm将控制权转移到任意地址。我建议完全在汇编中编写第一阶段引导程序。
  • @zwol 地址暗示这是程序B的痕迹。现在的问题是程序B是如何链接的。特别是在地址 60004824 处调用的内容。地图文件应该会有所帮助。

标签: c assembly elf inline-assembly sparc


【解决方案1】:

在我看来,您确实执行了跳转,并且它到达了程序 B,正如跟踪缓冲区中指令的地址所证明的那样。但是你崩溃的地方是在 stdio 中试图打印东西。 Stdio大量使用了函数指针,序列清晰地显示了调用指令,目标地址在寄存器中,说明使用了函数指针。

我建议在跳转之前将 fflush(stdout) 放在程序 A 中,这样您就可以在跳转之前看到消息。然后,在程序 B 中,不使用 printf,而是将一些已知值放入内存中,稍后您可以通过监视器检查以验证它是否到达那里。

我的猜测是 stdio 库有一些数据或参数需要在程序开始时设置,并且没有完成或没有正确完成。不确定您正在运行的平台,但您是否具有某种调试或单步执行能力,例如在调试器中?如果是这样,只需单步执行跳转并按照程序执行的操作即可。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多