esaulenka 7 22 июля, 2009 Опубликовано 22 июля, 2009 · Жалоба Наткнулся на непонятную проблему... Исходные данные: Keil, компилятор - древний кейловский CARM, оптимизаций нет. процессор LPC2138 Есть такой код (вопросы по оптимальности использования LDRB/STRB, перебрасывания регистров туда-сюда - к авторам библиотек к CARM) 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 дальше всё работает. Если запустить на выполнение до этой строки, получаем ошибку. Сделал тестовую функцию - она тоже работает нормально! Да, она действительно работает, оптимизатор до неё не добрался. Адреса менял - пофигу... void Test (void) { char buff[128]; int ptr = 0x038910; // этот адрес менял уже из-под отладчика while (1) { memcpy (buff, ptr, 16); } } Собственно, вопрос. Что это было?! Нарисовал CopyMem, которая копирует по 4 байта за раз - она работает хорошо. Но хочется разобраться... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 22 июля, 2009 Опубликовано 22 июля, 2009 · Жалоба Можно сказать только, что кто-то у Вас портит R0, и это не memcpy. Прерывания выключать пробовали? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
esaulenka 7 23 июля, 2009 Опубликовано 23 июля, 2009 · Жалоба Угу, портится R0 и STRB вполне законно вылетает. Только вот всё остальное-то работает! В частности, в том же самом месте эта memcpy нормально вызывается 0x3890 раз (собственно, считываем прошивку целиком кусочками по 16 байт в один и тот же буфер). И дальше нормально выполняется, если указатель руками переставить... Прерывания выключать не пробовал, т.к. всё развалится. Хотя вот Test() вызывал до разрешения прерываний, оно работает. Освобожусь чуток, постараюсь разобраться... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться