#assembly #memory #cpu #ram
#сборка #память #процессор #ОЗУ
Вопрос:
mov db[0x402000],10
может дать нам некоторое представление о том, как var: db 10
работает тогда, когда мы записываем mov bx,var
, адрес памяти переходит в bx. вопрос в том, как метка или переменная типа ‘var’ равна адресу памяти и как компьютер принимает их за равное значение? или простым способом, как компьютеры приравнивают переменную, подобную x, к числу, подобному 2, на низком уровне, чтобы мы могли использовать в нашем коде? где будут храниться эти данные?
Ответ №1:
Я думаю, вы хотели сказать mov byte[0x402000], 10
. На самом деле компьютеры не имеют дела с метками или переменными; с ними имеют дело ассемблеры и компоновщики. Они содержат смещения или ячейки памяти своих значений, чтобы абстрагировать данные памяти для пользователя. Если код собран как двоичный, они исчезают. Или же они могут храниться внутри таблицы символов для целей перемещения или отладки.
Ответ №2:
… как метка или переменная, такая как ‘var’, равна адресу памяти …
В некоторой полупроводниковой памяти (например, ОЗУ) все ячейки памяти (в случае x86: байты) имеют адрес. Адрес — это не что иное, как число, идентифицирующее эту ячейку памяти.
Поэтому, если центральный процессор хочет прочитать переменную var
, он должен отправить адрес (номер) ячейки, содержащей переменную var
, в микросхему ОЗУ, и ОЗУ отправит значение, сохраненное в этой ячейке, обратно в центральный процессор.
Запись в переменную аналогична: центральный процессор отправляет адрес и новое значение в чип.
… и как компьютер принимает их за равное значение?
Как уже было сказано в другом ответе, компьютер не знает об этой переменной.
Некоторый исполняемый файл (например .exe
под Windows) не содержит никаких «переменных». Если вы компилируете какую-либо программу на C или C , выполняются следующие шаги:
- Программа на C / C содержит переменную
char var;
- Компилятор создает некоторый файл сборки из программы на C / C .
Язык ассемблера не знает о «переменных»;var: db 10
не означает: «однобайтовая переменная с именемvar
со значением 10«, но это означает: «один байт оперативной памяти с именем,var
содержащим значение 10«.
Таким образом, файл сборки уже больше не содержит переменных, но он уже содержит информацию о байтах в оперативной памяти. - Ассемблер создает некоторый объектный файл из файла ассемблера.
Ассемблер обычно группирует несколько ячеек ОЗУ в так называемые «разделы»; поэтому, если исходный файл C содержал 100char
переменных, объектный файл не содержит 100 отдельных ячеек ОЗУ, но содержит один «раздел» длиной 100 байт.
В объектном файлеmov [var],al
становитсяmov [0],al
инструкция, и появляется некоторая информация о том, что[0]
изначально[var]
было в файле сборки. - Затем компоновщик создает исполняемый файл (
.exe
под Windows) из одного или нескольких объектных файлов.
Компоновщик назначит адреса памяти каждому «разделу», упомянутому в объектных файлах. В простейшем случае это начнется с некоторого адреса (например, 0x402000) и разместит первый раздел одного объектного файла по этому адресу. Если этот раздел имеет длину 0x234 байта, он поместит следующий раздел по адресу 0x402000 0x234 = 0x402234 и так далее…
Объектный файл содержит некоторую информацию о том, где находится ячейка памятиvar
. Допустим, в информации говорится, что ячейка памятиvar
является 10-м байтом второго раздела. Это означает, что ячейка памяти расположена по адресу 0x402234 9 = 0x40223D. Используя информацию, которая[0]
была[var]
в файле сборки, компоновщик заменяет значение0
(вmov [0],al
) на0x40223D
.
В результате этого 3-шагового процесса (компилятор, ассемблер, компоновщик) в программе не остается переменных или имен, а только числовые адреса.