我面临一个奇怪的问题,有点类似于this。我有一个 Windows Phone 8 本机 DLL 项目,主要是 C++,但其中包含 ARM 程序集源。源处于 ARM 模式(即不是 Thumb)。C++ 编译为 Thumb。
当 C++ 尝试调用汇编例程时,应用程序崩溃。反汇编中的调用命令是带有立即偏移量的 BLX - 它应该无条件地将模式切换回 ARM,但不知何故它没有。
我有异常的详细信息。异常代码为0xc000001d(无效操作),crash context struct中PC的值为0x696d5985。这在任何一种模式下都是不可能的——它没有对齐,零位是一。BLX 指令运行1b f0 0c eb
- 如果您破译,那是一个由两部分组成的 Thumb 式 BLX 好吧,具有 4 对齐位移。崩溃上下文中的 T 标志为 SET (CPSR=0x60000010)。
我没有设备,但来自 beta 测试人员的崩溃日志非常有说服力。在调用程序集之前我有一个调试日志记录。然后是崩溃。
编辑:相关。然而,他们声称汇编程序本身 ( armasm
) 将 ARM 转换为 Thumb。对我来说不是这样——至少不是静态的。DLL 包含正确的 ARM 代码,如汇编源代码 ( CODE32
) 中所指定。
编辑:尝试使用稍微不同的跳转顺序:
ldr r12, target
and r12, r12, #0xfffffffe ; To be sure
bx r12 ;BX to a register with a cleared 0th bit. Doesn't get any more explicit than that.
结果相同。看起来商店中某处发生了一些奇怪的代码变形,或者操作系统本身捕获了模式切换并阻止了它们。
代码变形可以通过将可执行文件的一部分连同其余的崩溃数据一起转储到崩溃日志中来检测。但是,除了将整个代码库转换为 Thumb 之外,我还能如何处理操作系统干扰?它不只是重新编译。
为 dwelch 编辑:编译的 C 代码中的调用序列如下所示:
.text:1000A35E MOV R2, #g_Host ;Three parameters
.text:1000A366 MOV R1, R5
.text:1000A368 MOV R0, R6
.text:1000A36A BLX Func ; Code bytes 1B F0 0C EB
BLX 到立即地址有切换模式。这不是有条件的,例如bx register
. 调用目标是一个 thunk:
.text:10025984 B Func_Impl
崩溃地址是这个 thunk 加一:5985。
这是已编译 DLL 的反汇编,但我不能保证这正是设备上正在执行的内容。链接的 MSDN 线程中的用户声称他们查看了调试器中的反汇编并看到了 ARM 应该在的地方。微软, IIRC,拥有修改从发布者到设备的应用程序代码的专利;这可能是原因。