【发布时间】: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”或“call”,但没有成功。 我很困惑。 我不知道如何很好地处理这个问题,因此我不知道还需要提供哪些其他信息。
我可以说,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