裸机mod(%)挂在带有libgcc的ARMv6上



当我尝试在ARM裸机程序中的C代码中使用%时,它需要来自libgcc的包装器。没问题,我可以链接。当我这样做时,链接器停止抱怨,但程序在mod使用时挂起(如果我观察寄存器,它们实际上开始以莫名其妙的方式循环)。用%注释这条线会使程序不会以这种方式挂起,所以这肯定是问题所在。

我在https://gist.github.com/1724746

我使用运行测试

qemu-system-arm -M versatilepb -cpu arm1176 -nographic -kernel kernel.elf | xxd

然后^a-x退出它,%行被注释掉后,我得到了我期望输出的字节,但有了这行,我没有得到任何这样的输出。

知道这里发生了什么吗?

编辑:我使用的交叉编译器是Ubuntu上的默认编译器:https://launchpad.net/gcc-linaro

所以它用2加载r0和r1(好吧,它在当前任务+1 上做了加一的事情

10648:  e1a00003    mov r0, r3
1064c:  e51b1010    ldr r1, [fp, #-16]
10650:  eb00fd36    bl  4fb30 <____aeabi_uidivmod_veneer>

我猜他们用_veneer从手臂切换到拇指,这是一个蹦床来切换模式:

0004fb30 <____aeabi_uidivmod_veneer>:
   4fb30:   e51ff004    ldr pc, [pc, #-4]   ; 4fb34 <____aeabi_uidivmod_veneer+0x4>
   4fb34:   00010905    .word   0x00010905

这就是实际的模运算,这是拇指代码,拇指模式

00010904 <__aeabi_uidivmod>:
   10904:   2900        cmp r1, #0
   10906:   d0f8        beq.n   108fa <__aeabi_uidiv+0x252>
   10908:   e92d 4003   stmdb   sp!, {r0, r1, lr}
   1090c:   f7ff fecc   bl  106a8 <__aeabi_uidiv>
   10910:   e8bd 4006   ldmia.w sp!, {r1, r2, lr}
   10914:   fb02 f300   mul.w   r3, r2, r0
   10918:   eba1 0103   sub.w   r1, r1, r3
   1091c:   4770        bx  lr
   1091e:   bf00        nop

因此,它看起来像是做一个正常的除法,然后乘以结果并减去,例如

12345 % 100 = 12345 - ((12345/100)*100) = 12345 - (123*100) = 12345 - 12300 = 45

我想知道问题是否出在拇指模式上。手臂1176肯定有拇指模式,真正的模式,我qemu可以做拇指。

不过,你可以尝试一个实验来找出组装和链接:

.thumb
.thumb_func
.globl thumb_test
thumb_test:
   add r0,#1
   bx lr
arm-none-linux-gnueabi-as thumb_test.s -o thumb_test.o

或者不管你的工具链前缀是什么(如果有的话),并将.o文件与其他文件链接起来。

在C代码中声明为

unsigned int thumb_test ( unsigned int );

无论你通过什么,你都应该得到这个值加一回来。。。试试这个而不是模。

另一件需要尝试的事情是直接除法,看看除法是否有效,但不是模,也许问题是乘法指令?谁知道呢。

嗯,我想我看到了问题:

0004fb30 <____aeabi_uidivmod_veneer>:
   4fb30:   e51ff004    ldr pc, [pc, #-4]   ; 4fb34 <____aeabi_uidivmod_veneer+0x4>
   4fb34:   00010905    .word   0x00010905

你不能用ldr切换模式——它必须是bx或blx,当它试图在arm模式下执行拇指代码时,它可能会转到未定义的处理程序。

我有一些切换模式需要如何工作的例子,特别是为qemu编写的。现在这是一个低级别的例子,没有printf,例如,我确实有一个uart输出,可以查看uart上的内容。如果这是问题所在(切换到拇指模式),那么您需要检查如何编译和链接程序。如果您没有使用以前的代码源(现在由导师图形使用)工具链,您可能需要指定交互工作,或者可能需要了解工具链是如何构建的。这是假设您使用的是基于gnu/gcc的东西。

如果你有办法把一个未定义的处理程序放在那里,或者如果你能够观察跟踪并看到电脑掉到地址0x0000000附近,这可能就是正在发生的事情。如果你用我的小拇指测试构建,它使用ldr而不是bx来达到目的,那么这也不应该起作用,它仍然应该崩溃。。。

相关内容

  • 没有找到相关文章

最新更新