GCC 生成了未对齐的"ldrd"指令
GCC Generated a Misaligned "ldrd" Instruction
编译此C 代码时:
#include "../SM64DS_2.h"
//@021026a0, hooks: 0x020bddb8, 0x020bde0c
void CancelPowerups(Player& player)
{
if(player.isFreezeFramePeach)
{
player.isFreezeFramePeach = false;
player.EndMusic(0x33);
}
if(player.isDashyToad)
{
player.isDashyToad = false;
player.EndMusic(0x33);
}
}
//hook: 0x020b98f8
void EnableFreezeFramePeach(Player& player)
{
//TODO: Show message on first use
player.isFreezeFramePeach = true;
player.flowerPowerTimer = 600;
player.SetMusic(0x33);
}
//hook: 0x020b9904
void EnableDashyToad(Player& player)
{
//TODO: Show message on first use
player.isDashyToad = true;
player.flowerPowerTimer = 600;
player.SetMusic(0x33);
}
//hook: 0x020e4f10
void WorkDashyToadPart1(Player& player)
{
//TODO: Deal with speed of walking animation
if(player.isDashyToad)
{
player.horzSpeed /= 2;
player.isSpeedHalfed = true;
if(player.walkOnWaterTimer == 61)
++player.walkOnWaterTimer;
}
}
//hook: 0x020e52e8
void WorkDashyToadPart2(Player& player)
{
if(player.isSpeedHalfed)
{
player.horzSpeed *= 2;
player.isSpeedHalfed = false;
player.dashyToadParticleSysID = Particle::System::New(player.dashyToadParticleSysID,
0x4a,
player.pos.x,
player.pos.y + Fix12i(72),
player.pos.z,
nullptr,
nullptr);
}
}
带有GCC
的以下标志arm-none-eabi-g++ -MMD -MP -MF /c/Users/Joshua/Documents/desmume-0.9.11-win64/SM64DSe/SM64DSe/ASMPatchTemplate/build/PeachToadAbilities.d -g -Wall -O2 -march=armv5te -mtune=arm946e-s -fomit-frame-pointer -ffast-math -iquote /c/Users/Joshua/Documents/desmume-0.9.11-win64/SM64DSe/SM64DSe/ASMPatchTemplate/include -I/c/devkitPro/libnds/include -I/c/devkitPro/devkitARM/include -I/c/devkitPro/devkitARM/arm-none-eabi/include -I/c/Users/Joshua/Documents/desmume-0.9.11-win64/SM64DSe/SM64DSe/ASMPatchTemplate/build -DARM9 -nodefaultlibs -I. -fno-builtin -c --std=c++14 -fno-rtti -fno-exceptions -Wa,-adl=PeachToadAbilities.lst -c /c/Users/Joshua/Documents/desmume-0.9.11-win64/SM64DSe/SM64DSe/ASMPatchTemplate/source/C_PeachToadAbilities/PeachToadAbilities.cpp -o PeachToadAbilities.o
(特别注意架构是ARMV5TE,CPU是ARM946E-S)最后一个功能生成以下ASM:
push {r4, lr}
mov r4, r0
mov r1, #0x0
ldrd r2, [r4, #0x5c]
ldr ip, [r0, #0x98]
ldr r0, [r0, #0x280]
lsl ip, ip, #0x1
str ip, [r4, #0x98]
ldr ip, [r4, #0x64]
sub sp, sp, #0x10
strb r1, [r4, #0x27d]
add r3, r3, #0x48000
str r1, [sp, #0x8]
str r1, [sp, #0x4]
str ip, [sp]
mov r1, #0x4a
bl _ZN8Particle6System3NewEjj5Fix12IiES2_S2_PK11Vector3_16fPNS_8CallbackE
str r0, [r4, #0x280]
add sp, sp, #0x10
pop {r4, pc}
对于上下文,这是Nintendo DS游戏的一部分。播放器结构为4字节对齐,在偏移率0x5c是玩家的位置,该位置是3 fix12< int> gt;(fix12< int>是1个4字节整数的结构。)。
问题是GCC生成了一个" LDRD"指令,该指令无法证明访问8个字节对齐的地址(它不应该知道" player"在哪里,此外,0x5C不是8个。)。我看过的ARM文档说,对于ARMV5,加载未定义的双字是未定义的行为。但是,没有$ GBA和DESMUME认为,当地址为4字节时,此类访问仍然从该地址加载8字节值。ARM946E-S CPU上ARMV5TE的正确行为是正确的吗?(我没有在实际DS上测试过,因为我没有闪存卡。)
我也看到了ARMV5TE和ARM946E-S和GCC 6(5中还可以)。就我而言,该代码正在加载两个数组的两个连续元素,但是编译器无法证明传递的数组指针是8字节对齐。我将尝试生成一个简单的示例并报告。您应该做同样的事情,希望它可以修复。
很可能类实例与某些字节对齐(例如64个字节),并且标题不是八个字节的倍数在"不协调"的地址上,结合了"未对准"偏移(例如0x5C),该地址保证为8个字节对齐。
编译器并不完美,但我无法想象他们会犯如此微不足道的错误。
所以不用担心。
相关文章:
- 使用C++库在Android项目中修改gradle中的cmake参数,用于插入指令的测试
- 无法编译 rtmidi 测试 cmidiin.cpp 文件, 非法指令
- C++:对不存在的命名空间使用命名空间指令
- 函数名是c中该函数的第一条指令的地址吗
- 错误:无效的预处理指令 #i 的意思是 #if?
- 组装指令中乘法的下部和上部是什么
- OpenMP 与有序和关键指令并行
- C++中的移动分配出现问题.非法指令: 4.
- 嵌套命名空间的"using"指令,但需要命名内部命名空间
- C++CMake编译指令与
- 使用宏扩展的泛型:为什么指令缓存使用不当?
- 如何在 c++ 中确定一条指令(以字节为单位)在哪里结束,另一条指令从哪里开始?
- AVX 指令中寄存器和指针之间的客观差异
- while 循环 c++ 中的非法指令
- 如何在编译时定义C++预处理器指令的值?
- 存储指令是否会阻止缓存未命中的后续指令?
- 保证编译器指令在C++中重新排序
- VS2008中的AVX-512指令库
- 令人困惑的定义指令在C ++项目中
- GCC 生成了未对齐的"ldrd"指令