2017-10-05 3 views
1

를 생성 ++ 코드 : GCCGCC가 잘못 정렬 된 "LDRD"명령

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가 인 것이 특히주의에 대해 다음 플래그

#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); 
    } 
} 

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} 

xt, 이것은 닌텐도 DS 게임의 ROM 해킹 조각입니다. 플레이어 구조는 4 바이트로 정렬되고 오프셋 0x5C에서 플레이어의 위치는 3 Fix12 구조입니다 (Fix12 <int>은 1 바이트의 정수입니다).

문제는 gcc가 "ldrd"명령어를 생성하여 8 바이트 정렬 주소에 액세스 할 수 없음을 나타냅니다 ("player"가 어디인지 알 수 없으며 0x5C는 8의 배수가 아닙니다). . 제가 살펴본 ARM 문서에서는 ARMv5의 경우 잘못 정렬 된 더블 워드로드가 정의되지 않은 동작이라고합니다. 그러나 $ gba 및 DeSmuME는 주소가 4 바이트 정렬 일 때 이러한 액세스가 여전히 해당 주소에서 8 바이트 값을로드한다고 가정하지 않습니다. ARM946E-S CPU에서 ARMv5TE에 대해 올바른 동작입니까? (플래시 카드가 없기 때문에 이것을 실제 DS에서 테스트하지 않았습니다.)

+0

8 바이트 정렬 요구 사항이 나중에 Arm 아키텍처에서 제외 된 것처럼 보이며 GCC는 이전 요구 사항을 따르지 않습니다. 가능한 해결 방법은 ARMv5T에 대해서만 컴파일하여 이러한 명령어를 비활성화하는 것입니다. – NickJH

답변

0

대부분의 경우 클래스 인스턴스는 특정 바이트 (예 : 64 바이트)에 정렬되어 있으며 헤더는 따라서 8 바이트의 배수이기 때문에 구성원 변수는 "정렬되지 않은"주소에서 시작하는 위치에 압축되어 0x5c와 같은 "정렬되지 않은"오프셋과 결합되므로 주소는 8 바이트로 정렬됩니다.

컴파일러는 완벽하지는 않지만, 그렇게 간단한 실수를 저 지르지는 못한다.

걱정하지 마십시오.

관련 문제