Пишу свой собственный C++ компилятор.. застрял на переменных
В настоящее время я работаю над компилятором C++ для моего процессора Logisim в JS, и теперь у меня проблема с переменными:
Я определил пространство в оперативной памяти для хранения данных / значений, и я определил пространство для хранения адресов в пространстве данных. У меня есть регистр nx с указателем на последнюю переменную и регистр mx с указателем на последнюю оперативную память для хранения данных. Но я не знаю, как получить к ним доступ, например, здесь:
модифицированный код C++:
int *pointer_test;
int test;
test = 123;
pointer_test = &test;
*pointer_test = 25;
Pre-сборщик
//Allocate new variable <--- int *pointer_test;
add nx, 1
//Set the pointer pointing to zero
sram nx, 0
//Allocate another variable <--- int test;
add nx, 1
//Allocate new storage for the variable
add mx, 1
//Let the variable point to the data <--- test = 123;
sram nx, mx
sram mx, 123
Как мне реализовать сейчас:
pointer_test = &test;
У меня есть только значение &test, сохраненное в nx, потому что это последняя объявленная переменная, но не адрес переменной / указателя "pointer_test" ...
1 ответ
Возможно, вы захотите написать сборку на основе стека, как и любой другой компилятор C за последние 20 лет. Это означает, что в ОЗУ имеется область данных, называемая стеком, представляющая собой очередь FIFO, которая расширяется. Стеки также всегда включают хотя бы один регистр: указатель стека. Указатель стека указывает на текущее место в стеке, куда пойдет следующая вещь. Итак, чтобы добавить что-то в стек, вы помещаете его туда, куда указывает указатель стека, а затем вычитаете размер этого элемента из указателя стека.
Другой регистр, который чаще всего используется в ассемблере C, это базовый указатель. Базовый указатель указывает на начало текущего кадра. Кадр можно приблизительно сравнить с областью действия в C. Итак, если у меня есть этот код:
int a;
{
int b;
}
И верхний стек равен 0x9999, затем a
будет в 0x9995 (при условии 4 байта int), указатель стека теперь указывает на 0x9991, а базовый указатель все еще в 0x9999. Когда вводится новая область, базовый указатель перемещается в указатель стека, а затем B устанавливается в 0x9991. Затем, когда выходит из области действия, указатель стека устанавливается на базовый указатель, эффективно стирая переменные в нижней области действия.
Я никогда не слышал об архитектуре, для которой вы программируете, но просто знаю, что подойдут любые два регистра, но некоторые архитектуры, такие как x86, имеют специальные регистры stak (ebp
, esp
на 32 бит и reb
а также rsp
на 64 бит).
Но чтобы ответить на этот вопрос немного подробнее, задача компилятора состоит в том, чтобы узнать, какое смещение в стеке имеет каждая переменная, поэтому он может выполнять такие действия, как (псевдокод):
base_pointer - 5 (Offset for pointer_test) = base_pointer - 4 (offset for test)