Как C ссылается на автоматические переменные. - PullRequest
0 голосов
/ 08 октября 2018

Я пытаюсь понять, как компилятор ссылается на автоматические переменные.Моя точка зрения - это микроконтроллер PIC32MZ с компилятором XC32.

Пока я понимаю, как работают глобальные и статические переменные.Компилятор размещает их в памяти, а затем жестко кодирует адрес и размер непосредственно в код.Инструкции будут содержать адреса.Таким образом, операция, подобная c = a + b, если бы все они были глобальными, выглядела бы примерно так.(сборка sudo)

Переместить адрес a в рабочий регистр.Переместить адрес b в другой рабочий регистр.Добавьте два рабочих регистра.Переместить результат по адресу c.

Как это работает с автоматическими переменными?

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

С динамической памятью идея имеет смысл.Возвращение malloc является указателем на местоположение новой переменной, и этот указатель сохраняется в уже существующей переменной.

1 Ответ

0 голосов
/ 17 октября 2018

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

Вот небольшой фрагмент начала функции и конца.

Начало функции

0x9D005640: ADDIU SP, SP, -56
0x9D005644: SW RA, 52(SP)
0x9D005648: SW S7, 48(SP)
0x9D00564C: SW S6, 44(SP)
0x9D005650: SW S5, 40(SP)
0x9D005654: SW S4, 36(SP)
0x9D005658: SW S3, 32(SP)
0x9D00565C: SW S2, 28(SP)
0x9D005660: SW S1, 24(SP)
0x9D005664: SW S0, 20(SP)

Конец функции

0x9D0057CC: LW RA, 52(SP)
0x9D0057D0: LW S7, 48(SP)
0x9D0057D4: LW S6, 44(SP)
0x9D0057D8: LW S5, 40(SP)
0x9D0057DC: LW S4, 36(SP)
0x9D0057E0: LW S3, 32(SP)
0x9D0057E4: LW S2, 28(SP)
0x9D0057E8: LW S1, 24(SP)
0x9D0057EC: LW S0, 20(SP)
0x9D0057F0: JR RA
0x9D0057F4: ADDIU SP, SP, 56

В начале указатель стека (SP) увеличивается, чтобы освободить место в стеке.Поскольку стек начинается с верхних адресов и идет вниз, имеет смысл вычесть 56 из указателя стека для его перемещения.Это делается с помощью команды ADDIU и путем добавления отрицательного значения.

Затем наступает удивительная часть.Команда SW перемещает данные из рабочих регистров в память.Как можно видеть, S0-S7 копируется.Из того, что говорится в документации MIPS, рабочие регистры S необходимо очистить перед их использованием.Это поведение затем согласовывается с документацией.

Команда SW перемещает данные из рабочего регистра в адрес памяти.Это где мой вопрос ответил.Указанный адрес, например, 20 (SP).Это означает SP + 20. Этот механизм затем позволяет адресовать данные относительно SP.При добавлении к SP это перемещает адрес данных в стек относительно указателя стека.Подпрограмма 20 (SP) подобна подкоманде, потому что ядро ​​вычисляет SP + 20 перед выполнением SW.

Затем, когда функция выполняет свои операции, она использует теперь свободные рабочие резисторы.

Наконец, когда операции завершены, данные, находящиеся в стеке, возвращаются в рабочие регистры с помощью команды LW.Аналогично команде SW адресация из стека осуществляется с относительными смещениями.Чтобы завершить, функция 56 добавляется обратно к указателю стека, чтобы освободить используемую память.

...