所以它用 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
我想知道问题是否是拇指模式。arm1176肯定有拇指模式,真的,我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 的东西。
如果您有办法在其中放置未定义的处理程序,或者您能够观察跟踪并看到 pc 下降到地址 0x0000000 附近的某个地方,这可能就是正在发生的事情。如果您使用我的小 thumb_test 东西构建并且它使用 ldr 而不是 bx 到达那里,那么它不应该工作或者它仍然应该崩溃......