Он находится в IDE Code Composer Studio для отладки операционной системы на базе микросхемы cortex-a8.
Снимок экрана 1
Я заметил, что до того, как программа входит в какую-либо функцию вОсновной цикл, регистр ссылки содержит адрес, который указывает на бесконечный цикл, в то время как (1).
Это привлекает мое внимание, потому что
регистр ссылки - это то место, куда ядро помещает возвратадреса всякий раз, когда он вызывает подпрограмму.
Хотя код запуска будет вызывать main, но у main нет способа вернуться назад, пока в нем не запущен оператор возврата или не запущена операционная система, не говоря уже об одномпрограмма входит в функцию, значение регистра связи изменяется.
Итак, зачем нужен этот бесконечный цикл?
Программа:
int main(void)
{ //program stops here. link register: 0x805dcda0
OS_ERR err = OS_ERR_NONE;
IntAINTCInit(); //once program enters this function,
//the value of link register is changed
OS_Init(); //initialize OS
OSStart(&err); //start OS
if (err != OS_ERR_NONE)
{
printf("OS fails");
}
/*no return statement*/
}
Разборка:
start_boot():
805dcd94: E92D4008 push {r3, lr}
138 CopyVectorTable();
805dcd98: EB000001 bl CopyVectorTable
141 main();
805dcd9c: EB00001D bl main
143 while(1);
$C$L1:
805dcda0: EAFFFFFE b $C$L1
Снимок экрана 2
Вот практический пример, показывающий, что значение регистра ссылки будет изменено после того, как программа войдет в функцию IntAINTCInit ().
Программа:
void IntAINTCInit(void)
{ //program stops here. link register: 0x805dce28
/*pseudo code*/
!!Reset the ARM interrupt controller
!!Wait for the reset to complete
!!Enable any interrupt generation by setting priority threshold
!!Register the default handler for all interrupts
}
Разборка:
44 OS_Init(); //initialize OS
805dce28: EBFF30EA bl CPU_Init
Скриншот 3 и 4
В некоторых точках программы я обнаружил, что значениепрограммный счетчик будет равен регистру связи.
Хотя я знаю,
программный счетчик содержит адрес следующей инструкции, которая будет извлечена процессором.
Однако это все еще сбивает меня с толку, потому что оба этих регистра используются для совершенно разных целей.
Возьмите один фрагмент примера из кода.Я перешагнул один за другим на уровне сборки, наблюдая за ним в режиме отладки, но все еще не могу понять это.
Как это происходит?В какой ситуации?
Программа:
DNM_s* p = DNMManager_Retrive(index);
if(NULL != p)
{
char name_unicode[40] = {0};
char name_utf8[40] = {0};
memcpy(&name_unicode[0], DNMManager_GetName(p), 40); //program stops here.
//link register : 0x805afec8
//program counter: 0x805afec8
enc_unicode_to_utf8(name_unicode, 20, name_utf8);
memcpy(&((UI_DNM_RealList_s*)structs)->Name[0], &name_utf8[0], 40);
}
Разборка:
366 char name_utf8[40] = {0};
805afeb8: E3A01000 mov r1, #0
805afebc: E28D004C add r0, sp, #0x40
805afec0: E3A02028 mov r2, #0x28
805afec4: EB00D1FD bl memset
367 memcpy(&name_unicode[0], DNMManager_GetName(p), 40);
805afec8: E59D0020 ldr r0, [sp, #0x14]
805afecc EB0076E4 bl DNMManager_GetName
805afed0: E28DC024 add r12, sp, #0x18
805afed4: E1A01000 mov r1, r0
805afed8: E3A02028 mov r2, #0x28
805afedc: E1A0000C mov r0, r12
805afee0: EB00C2EF bl memcpy
Программа:
char* DNMManager_GetName(DNM_s* element)
{ //program stops here.
//link register : 0x805afed0
//program counter: 0x805cda64
return &element->Name[0];
}
Разборка:
DNMManager_GetName():
805cda64: E24DD008 sub sp, sp, #8
805cda68: E58D0000 str r0, [sp]