Исходные данные:
Keil, компилятор - древний кейловский CARM, оптимизаций нет.
процессор LPC2138
Есть такой код (вопросы по оптимальности использования LDRB/STRB, перебрасывания регистров туда-сюда - к авторам библиотек к CARM)
CODE
0x000388F4 E59FC000 LDR R12,[PC]
0x000388F8 E12FFF1C BX R12
0x000388FC 00038901 DD 0x00038901
strlen:
0x00038900 2100 MOV R1,#0x00
0x00038902 E000 B 0x00038906
0x00038904 3101 ADD R1,#0x01
0x00038906 1C02 ADD R2,R0,#0
0x00038908 3001 ADD R0,#0x01
0x0003890A 7812 LDRB R2,[R2,#0x00]
0x0003890C 2A00 CMP R2,#0x00
0x0003890E D1F9 BNE 0x00038904
0x00038910 1C08 ADD R0,R1,#0
0x00038912 4770 BX LR
0x00038914 E59FC000 LDR R12,[PC]
0x00038918 E12FFF1C BX R12
0x0003891C 00038921 DD 0x00038921
memcpy:
0x00038920 B430 PUSH {R4-R5}
0x00038922 1C03 ADD R3,R0,#0
0x00038924 1C18 ADD R0,R3,#0
0x00038926 E005 B 0x00038934
0x00038928 1C0C ADD R4,R1,#0
0x0003892A 7825 LDRB R5,[R4,#0x00]
0x0003892C 1C04 ADD R4,R0,#0
0x0003892E 7025 STRB R5,[R4,#0x00]
0x00038930 3101 ADD R1,#0x01
0x00038932 3001 ADD R0,#0x01
0x00038934 1C14 ADD R4,R2,#0
0x00038936 3A01 SUB R2,#0x01
0x00038938 2C00 CMP R4,#0x00
0x0003893A D1F5 BNE 0x00038928
0x0003893C 1C18 ADD R0,R3,#0
0x0003893E BC30 POP {R4-R5}
0x00038940 4770 BX LR
вызываем
memcpy (0x40002390, 0x00038910, 0x10)
... и попадаем в DataAbort.
Содержимое регистров:
R0 = 0x0000008A
R1 = 0x00038911
R2 = 0x0000000D
R3 = 0x40002390
R4 = 0x0000008A
R5 = 0x0000001C
R13 (SP) = 0x40002524
R14 (LR) = 0x00038936
R15 (PC) = 0x00000010
SPSR = 0x00000030
Какая-то мистика.
memcpy (0x40002390, 0x00038920, 0x10)
memcpy (0x40002390, 0x00038900, 0x10)
- всё проходит нормально.
Если выполнять этот код по шагам, всё также проходит нормально.
Запускаем в обычном режиме - получите переход на 0x10...
Экспериментально установлено, что если дошагать до
0x00038926 E005 B 0x00038934
дальше всё работает. Если запустить на выполнение до этой строки, получаем ошибку.
Сделал тестовую функцию - она тоже работает нормально!
Да, она действительно работает, оптимизатор до неё не добрался.
Адреса менял - пофигу...
CODE
void Test (void)
{
char buff[128];
int ptr = 0x038910; // этот адрес менял уже из-под отладчика
while (1)
{
memcpy (buff, ptr, 16);
}
}
Собственно, вопрос. Что это было?!
Нарисовал CopyMem, которая копирует по 4 байта за раз - она работает хорошо. Но хочется разобраться...