C ++ Builder — Понимание поведения старого кода C ++

Я переношу некоторые части старого кода C ++, изначально скомпилированного с CodeGear C ++ Builder® 2009 версии 12.0.3170.16989

Следующий код — минимальная версия большей части — выводит -34 с любым современным компилятором. Хотя, в оригинальной платформе это выводит 84:

char Key[4];
Key[0] = 0x1F;
Key[1] = 0x01;
Key[2] = 0x8B;
Key[3] = 0x55;

for(int i = 0; i < 2; i++) {
Key[i] = Key[2*i] ^ Key[2*i + 1];
}

std::cout << (int) Key[1] << std::endl;

введите описание изображения здесь
Следующий код выводит -34 со старыми и новыми компиляторами:

for(int i = 0; i < 2; i++) {
char a = Key[2*i];
char b = Key[2*i + 1];
char c = a ^ b;
Key[i] = c;
}

Кроме того, похоже, что ручное развертывание цикла работает с обоими компиляторами:

Key[0] = Key[0] ^ Key[1];
Key[1] = Key[2] ^ Key[3];

Важно, чтобы я соответствовал поведению старого кода. Кто-нибудь может помочь мне понять, почему оригинальный компилятор дает такие результаты?

8

Решение

Это похоже на ошибку:

Линия

Key[i] = Key[2*i] ^ Key[2*i + 1];

генерирует следующий код:

00401184 8B55F8           mov edx,[ebp-$08]
00401187 8A4C55FD         mov cl,[ebp+edx*2-$03]
0040118B 8B5DF8           mov ebx,[ebp-$08]
0040118E 304C1DFC         xor [ebp+ebx-$04],cl

Это не имеет смысла. Это что-то вроде:

Key[i] ^= Key[i*2 + 1];

И это объясняет, как получился результат: 0x01 ^ 0x55 это действительно 0x54, или же 84,

Это должно быть что-то вроде:

mov edx,[ebp-$08]
mov cl,[ebp+edx*2-$04]
xor cl,[ebp+edx*2-$03]
mov [ebp+ebx-$04],cl

Так что это определенно ошибка генерации кода. Кажется, до сих пор, C ++ Builder 10.2 Tokyo, для «классического» (Borland) компилятора.

Но если я использую компилятор «new» (clang), он выдает 222, Полученный код:

File7.cpp.12: Key[i] = Key[2*i] ^ Key[2*i + 1];
004013F5 8B45EC           mov eax,[ebp-$14]
004013F8 C1E001           shl eax,$01
004013FB 0FB64405F0       movzx eax,[ebp+eax-$10]
00401400 8B4DEC           mov ecx,[ebp-$14]
00401403 C1E101           shl ecx,$01
00401406 0FB64C0DF1       movzx ecx,[ebp+ecx-$0f]
0040140B 31C8             xor eax,ecx
0040140D 88C2             mov dl,al
0040140F 8B45EC           mov eax,[ebp-$14]
00401412 885405F0         mov [ebp+eax-$10],dl

Это не выглядит оптимальным для меня (я использовал O2 и O3 с одинаковым результатом), но это дает правильный результат.

5

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]