Может ли программа вернуться с основного?Почему регистр ссылок имеет то же значение, что и счетчик программ? - PullRequest
0 голосов
/ 14 февраля 2019

Он находится в 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]

1 Ответ

0 голосов
/ 15 февраля 2019

Поскольку вы показываете только несколько скриншотов, а не полный код, я могу только строить догадки ...

Снимок экрана 1: Точка входа

Кроме Windowsили Linux, программа микроконтроллера не должна возвращаться из main () .Никуда некуда деться.Чтобы защитить от дальнейшего повреждения, LR указывает на бесконечный цикл.Вот куда пойдет процесс, если вы случайно вернетесь из main () .

Снимок экрана 2: IntAINTCInit ()

Без вопросов.

Снимок экрана 3: ПК = LR

LR содержит адрес возврата при вводе функции.Если функция вызывает дополнительные функции, она должна сохранить LR (обычно в стеке) и присвоить ей новое значение.На снимке экрана показано состояние после оператора:

char name_utf8[40] = {0};

Если вы посмотрите на код сборки, вы увидите, что memset был вызван для инициализации 40 байтов в 0. Так что, действительно, еще одинбыла вызвана функция, и на скриншоте показано состояние сразу после возврата из memset .И каждый раз, когда функция только что вернулась, PC должно равняться LR , потому что так работает возврат.Так что все в порядке.

Снимок экрана 4: DNMManager_GetName

На снимке экрана показано состояние справа при вводе DNMManager_GetName () .Вызов этой функции был сделан с помощью оператора:

805AFECC    bl  DNMManager_GetName

Оператор после вызова (к которому необходимо вернуться) имеет значение 0x805AFED0, то есть то, что LR содержит на снимке экрана.

Обратите внимание, что одна строка в коде C приводит к двум вызовам функций, один для DNMManager_GetName () и один для memcpy .0x805AFEE4 будет адресом возврата второго вызова функции.Но на скриншоте 4 показано состояние первого вызова функции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...