Как машинные инструкции хранятся в памяти компьютера?

Обновлено: 21.11.2024

Я знаю, что наиболее простым (и наименее абстрактным) кодом для программирования является машинный код (типичным машинным кодом является двоичный код из нулей и единиц).

Я также знаю, что компьютеры могут сохранять данные, даже если они выключены, с помощью различных типов компьютерной памяти (память устройства хранения данных, ОЗУ и другие системные устройства компьютера, которые могут "запоминать" некоторые данные) .

Все ли данные, хранящиеся на компьютерах ("все данные, хранящиеся в памяти данного компьютера"), хранятся в виде машинного кода?
Является ли то, что сохраняется в «памяти» компьютера (и становится действительно эффективным благодаря правильному распределению электрического тока в компьютерной системе), просто двоичным машинным кодом в том смысле, что если бы я мог читать и понимать эти данные напрямую без взаимодействия с операционной системой? это для меня должно появиться в моем сознании как машинный код, или, скорее, это что-то еще?

2 ответа 2

Я бы так не сказал. В памяти хранятся биты. Это просто данные в двоичной форме.

Люди могут тогда пометить некоторые из этих битов как "машинный код", потому что мы намерены или ожидаем, что он будет выполнен; или потому что он будет выполнен. Это вопрос интерпретации, которую мы применяем. Модуль памяти просто видит кучу бит. Он просто видит некоторые данные и не знает, каково будет значение или предполагаемая цель этих данных.

Память не ограничивается хранением исполняемого кода. Компьютеры также хранят в памяти другие данные. Например, на вашем компьютере может храниться копия электронного письма, фотография или фотография, которую вы сделали. Это не код, но их можно хранить в памяти.

Может быть полезно думать, что память может использоваться для хранения данных или для хранения кода, но в архитектуре компьютера нет ничего, что навязывало бы какое-либо различие между ними. С точки зрения модуля памяти это всего лишь биты.

$\begingroup$ Таким образом, все хранится в ЛЮБОЙ памяти компьютера в битах, которые могут представлять машинный код (поскольку для некоторых программ они таковыми являются), но не обязательно представляют его, так как они также могут представлять данные для какого-либо документа, фотографии и т. д. $\endgroup$

Иногда это рассматривается как раз наоборот. У нас есть хранилище для данных, все в первую очередь является данными. Машинный код — это данные, предназначенные для чтения в конвейере выполнения процессора. Таким образом, различие является семантическим.

В настоящее время это стало несколько двусмысленным, когда у нас есть такие вещи, как шрифты истинного типа, которые воспринимаются как данные, но, если присмотреться, образуют полную по Тьюрингу систему.
Точно так же можно определить данные, составляющие некоторые популярные форматы документов, как программы. PDF является хорошим примером. Но это не совсем машинный код; скорее это интерпретируемая часть программного обеспечения, несколько уровней абстракции от аппаратного обеспечения.

Предпосылка вашего вопроса в основном была бы верна для предшественника компьютеров, ткацкого станка. Там машинный код был закодирован как шаблон, который на самом деле физически представлял собой шаблон, который машина должна была сгенерировать из этих данных.

Говоря более практично, в ядрах реальных операционных систем есть механизмы, позволяющие очень четко различать данные и исполняемый код, в том числе из соображений безопасности. Во-первых, существует концепция сегментов в программных файлах, которые могут быть помечены кодом или данными, но не тем и другим одновременно. Безумные шаблоны программирования, такие как самомодифицирующийся код, в большинстве случаев больше невозможны в современных системах, потому что сегменты кода защищены от записи. Во-вторых, существуют такие концепции, как защита от выполнения данных (DEP), которые предотвращают случайные попытки направить указатели команд процессора на области памяти, которые по объявлению содержат данные.

Когда программное обеспечение устанавливается на компьютер (путем его загрузки из Интернета или установки с диска), программа и все связанные с ней файлы сохраняются во вторичной памяти. Код программы хранится в виде последовательности битов, представляющих машинные инструкции. Код остается там до тех пор, пока пользователь не решит выполнить рассматриваемую программу, после чего участки кода загружаются в память компьютера.

Чтобы действительно запустить код, процессору необходимо извлечь инструкции из памяти одну за другой, чтобы он мог их выполнить. Этот процесс состоит из трех этапов: получение инструкции, декодирование инструкции и выполнение инструкции — эти три этапа известны как машинный цикл. Процессор проводит все свое время в этом цикле, бесконечно извлекая следующую инструкцию, расшифровывая ее и выполняя ее.

В цикле выборки блок управления просматривает регистр счетчика программ (ПК), чтобы получить адрес памяти для следующей инструкции. Затем он запрашивает эту инструкцию из основной памяти и помещает ее в регистр инструкций (IR).

Здесь блок управления проверяет инструкцию, которая сейчас хранится в регистре инструкций (IR). Он смотрит на инструкцию, которая представляет собой просто последовательность нулей и единиц, и решает, что нужно сделать. В инструкции сказано добавить два числа? Говорит ли он загрузить значение из памяти? Где в памяти? Блок управления интерпретирует двоичную инструкцию, чтобы ответить на подобные вопросы.

Теперь блок управления отправляет сигналы, которые сообщают АЛУ, памяти и другим компонентам сигналы о том, что они должны выполнять правильную работу.

В приведенном ниже видеоролике демонстрируется простая программа, работающая на компьютере. Показанный воображаемый компьютер использует специальные регистры для хранения адреса памяти (MAR) и данных, которые только что поступили из памяти (MBR). Он также использует регистры AL и BL для временного хранения значений. Не беспокойтесь о деталях этих других регистров, сосредоточьтесь на цикле выборки/декодирования/выполнения и на том, как используются ПК и ИК.

Компьютер представляет собой сложную систему, состоящую из множества различных компонентов. Но в сердце — или, если хотите, в мозгу — компьютера находится единственный компонент, который выполняет фактические вычисления. Это центральный процессор или центральный процессор. В современном настольном компьютере ЦП представляет собой один «чип» размером порядка одного квадратного дюйма. Работа процессора заключается в выполнении программ.

Программа – это просто список недвусмысленных инструкций, которым компьютер должен следовать автоматически. Компьютер создан для выполнения инструкций, написанных на очень простом языке, называемом машинным языком. Каждый тип компьютера имеет свой собственный машинный язык, и компьютер может напрямую выполнять программу только в том случае, если программа написана на этом языке. (Он может выполнять программы, написанные на других языках, если они сначала переведены на машинный язык.)

Когда ЦП выполняет программу, эта программа сохраняется в основной памяти компьютера (также называемой ОЗУ или оперативной памятью). В дополнение к программе в памяти также могут храниться данные, которые используются или обрабатываются программой. Основная память состоит из последовательности ячеек. Эти местоположения пронумерованы, а порядковый номер местоположения называется его адресом. Адрес обеспечивает способ выбора одной конкретной части информации из миллионов, хранящихся в памяти. Когда ЦП необходимо получить доступ к программной инструкции или данным в определенном месте, он отправляет адрес этой информации в качестве сигнала в память; память отвечает, отправляя обратно данные, содержащиеся в указанном месте. ЦП также может хранить информацию в памяти, указав информацию, которая должна быть сохранена, и адрес места, где она должна быть сохранена.

На уровне машинного языка работа ЦП довольно проста (хотя и очень сложна в деталях). ЦП выполняет программу, которая хранится в основной памяти в виде последовательности инструкций машинного языка. Он делает это, многократно считывая или извлекая инструкцию из памяти, а затем выполняя или выполняя эту инструкцию. Этот процесс — выборка инструкции, ее выполнение, выборка другой инструкции, ее выполнение и так далее до бесконечности — называется циклом выборки-и-исполнения. За одним исключением, которое будет рассмотрено в следующем разделе, это все, что когда-либо делает ЦП.

Подробности цикла выборки и выполнения не очень важны, но есть несколько основных моментов, которые вам следует знать. ЦП содержит несколько внутренних регистров, которые представляют собой небольшие блоки памяти, способные хранить одно число или инструкцию машинного языка. ЦП использует один из этих регистров — программный счетчик или ПК — для отслеживания того, где он находится в выполняемой программе. ПК сохраняет адрес следующей инструкции, которую должен выполнить ЦП. В начале каждого цикла выборки и выполнения ЦП проверяет ПК, чтобы узнать, какую инструкцию он должен получить. В ходе цикла выборки и выполнения число в ПК обновляется, чтобы указать инструкцию, которая должна быть выполнена в следующем цикле. (Обычно, но не всегда, это просто инструкция, которая последовательно следует за текущей инструкцией в программе.)

Компьютер выполняет программы на машинном языке механически, то есть не понимая их и не думая о них, просто из-за того, как он физически устроен. Это не простая концепция. Компьютер представляет собой машину, состоящую из миллионов крошечных переключателей, называемых транзисторами, которые обладают тем свойством, что их можно соединять вместе таким образом, что выходной сигнал одного переключателя может включать или выключать другой переключатель. Когда компьютер выполняет вычисления, эти переключатели включают или выключают друг друга по шаблону, определяемому как способом их соединения, так и программой, которую выполняет компьютер.

Инструкции машинного языка выражаются в виде двоичных чисел. Двоичное число состоит всего из двух возможных цифр, нуля и единицы.Итак, инструкция машинного языка — это просто последовательность нулей и единиц. Каждая конкретная последовательность кодирует определенную инструкцию. Данные, которыми манипулирует компьютер, также кодируются в виде двоичных чисел. Компьютер может работать напрямую с двоичными числами, потому что переключатели могут легко представлять такие числа: включите переключатель, чтобы представить единицу; выключите его, чтобы представить ноль. Инструкции на машинном языке хранятся в памяти в виде комбинаций включенных и выключенных переключателей. Когда инструкция на машинном языке загружается в ЦП, все, что происходит, это то, что определенные переключатели включаются или выключаются в шаблоне, кодирующем эту конкретную инструкцию. ЦП устроен так, чтобы реагировать на этот шаблон, выполняя закодированную им инструкцию; он делает это просто из-за того, что все остальные переключатели в ЦП соединены вместе.

Итак, вы должны понимать, как работают компьютеры: основная память содержит программы и данные на машинном языке. Они кодируются как двоичные числа. ЦП извлекает инструкции машинного языка из памяти одну за другой и выполняет их. Он делает это механически, не задумываясь и не понимая, что он делает, и поэтому исполняемая им программа должна быть совершенной, завершенной во всех деталях и однозначной, потому что центральный процессор не может ничего сделать, кроме как выполнить ее точно так, как она написана. Вот схематическое изображение этого первого этапа понимания компьютера:

Насколько я знаю, всякий раз, когда мы запускаем любую программу, машинные инструкции программы загружаются в оперативную память. Опять же, есть две области памяти: стек и куча.

Мой вопрос: в какой области памяти хранится машинная инструкция? стек или куча?

Я узнал, что следующая программа выдает ошибку времени выполнения, хотя внутри функции не объявлена ​​переменная. Причиной этого является переполнение стека. Тогда я должен предположить, что машинные инструкции функции хранятся в стеке?

Ваш новый вопрос не имеет абсолютно никакого отношения к первому. Причина сбоя в том, что параметры вызова функции, такие как адрес возврата, хранятся в стеке. Сам машинный код — нет.

@MuktadirRahman: Что ж, эта ошибка времени выполнения/переполнение стека — это проблема, с которой вы сталкиваетесь, когда смотрите на рекурсию, которая не завершается. ;-)

7 ответов 7

Ни то, ни другое, так как он не распределяется динамически так, как стек и куча.

Загрузчик исполняемого файла загружает исполняемый файл (.text) и любые содержащиеся в нем статические данные, например начальные значения глобальных переменных (.data / .rodata), в неиспользуемую область ОЗУ. Затем он устанавливает любую память с нулевой инициализацией, которую запросил исполняемый файл (.bss).

Только тогда стек настраивается для main() . Память стека выделяется в стеке, если вы входите в другую функцию, содержащую адрес возврата, аргументы функции и любые локально объявленные переменные, а также любую память, выделенную с помощью alloca() . [1] Память освобождается, когда вы возвращаетесь из функции.

Память кучи выделяется функциями malloc(), calloc() или realloc(). Он освобождается, когда вы освобождаете() или перераспределяете().

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

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

Что касается вашего отредактированного вопроса, нет. (Плохой стиль, редактировать вопрос, чтобы придать ему совершенно новый угол.)

Исполняемый код остается там, где он был загружен. Вызов функции не помещает машинные инструкции в стек. Единственное, что ваша функция func() (функция без аргументов) помещает в стек, — это адрес возврата, указатель, указывающий, где выполнение должно быть продолжено после возврата текущей функции.

Поскольку ни один из вызовов никогда не возвращается, ваша программа продолжает добавлять адреса возврата в стек до тех пор, пока он не перестанет храниться. Это вообще не имеет ничего общего с инструкциями машинного кода.

[1]: обратите внимание, что ничто из этого на самом деле не является неотъемлемой частью стандарта языка C, а определяется реализацией и может отличаться — я представил упрощенную версию дела. Например, параметры функции могут передаваться в регистрах ЦП, а не в стеке.

Читайте также: