我将简要说明问题。我有一个Leon3开发板(gr-ut-g99)。使用GRMON2,我可以在板上的所需地址加载可执行文件。
我有两个程序。我们称它们为A和B。我试图将它们加载到内存中,并且它们分别工作。
我现在想做的是使A程序称为B程序。
这两个程序都是使用gcc编译器(Gaisler Sparc GCC)的变体用C编写的。
为了进行跳转,我在程序A中编写了一个微型内联汇编函数,该函数跳转到加载程序B的内存地址。
在程序A的摘要下方
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世界。程序B加载在0x60000000地址。如果我尝试运行它,它将起作用!
int main()
{
printf ("HELLO! I'M BOOTED! \n");
fflush(stdout);
return 0;
}
当我运行ProgramA时,我期望在控制台上看到“正在跳跃...”消息,然后看到“ HELLO!I BOOTED!”从程序B
会发生什么,而不是IU异常。
我在下面发布了grmon2 Monitor显示的消息。我还报告了“ 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 ] -
我还尝试用“ jmpl”或“ call”代替“ jmp”,但是它不起作用。
我很困惑
我不知道如何很好地解决该问题,因此我不知道还需要提供什么其他信息。
我可以说,programB在0x60000000处加载,而entry_point当然是0x60000000。从该入口点直接运行程序B效果很好!
在此先感谢您的帮助!
最佳答案
在我看来,您确实执行了跳转,并且跳转到了程序B,这由跟踪缓冲区中的指令地址证明。但是您崩溃的地方是在stdio中尝试打印内容。 Stdio大量使用了函数指针,该序列清楚地显示了一个调用指令,其中目标地址位于寄存器中,指示了函数指针的使用。
我建议将fflush(stdout)放在跳转之前的程序A中,这将允许您在执行跳转之前查看消息。然后,在程序B中,不使用printf,而是将一些已知值放入内存中,然后可以通过监视器检查该值,以确认它是否在那里。
我的猜测是stdio库具有一些需要在程序开始时设置的数据或参数,而这些数据或参数未完成或未正确完成。不确定正在运行的平台,但是您是否具有某种调试功能或单步执行功能,例如在调试器中?如果是这样,只需单步执行跳转,然后跟踪程序的运行位置即可。
关于c - SPARC汇编jmp\boot,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49535410/