У каждого из нас есть мечта программиста наверное, то есть стать Даниэлем, мы наверное погружаемся в разные рамки, эта рамка решает все, что прикладной уровень самый важный, вы не правы. В современной компьютерной индустрии будет применяться базовое качество, если вы понимаете принцип, позволяющий вам двигаться дальше в отрасли, а базовые компьютерные знания являются главным приоритетом. Теперь следуйте по моим стопам, рассказывая нам об основных компьютерных знаниях.
CPU
Не знаю процессор еще? Теперь возьмите вас, чтобы понять, что является процессором
Полное название процессораCentral Processing Unit, это самое硬核компоненты, не будет преувеличением сказать, что. Процессор — это то, что позволяет вашему компьютеру вызывать计算机Основной компонент компьютера, но он не может представлять ваш компьютер Отношения между процессором и компьютером эквивалентны отношениям между мозгом и человеком. Ядром ЦП является получение инструкций от программы или приложения и выполнение вычислений. Этот процесс можно разбить на три основных этапа:Извлечь, декодировать и выполнить. ЦП извлекает инструкцию из основной памяти системы, затем декодирует фактическое содержание инструкции перед выполнением инструкции соответствующей частью ЦП.
Внутренняя обработка ЦП
На следующем рисунке показан процесс выполнения общей программы (в качестве примера взят язык C) Можно сказать, что понимание процесса выполнения программы является основой и предпосылкой для овладения механизмом выполнения программы.
В этом процессе ЦП отвечает за интерпретацию и запуск контента, который в конечном итоге преобразуется в машинный язык.
Процессор в основном состоит из двух частей:控制单元и算术逻辑单元(ALU)
- Блок управления: выборка инструкций из памяти и выполнение декодирования
- Арифметико-логическое устройство (ALU): обрабатывает арифметические и логические операции.
Центральный процессор — это сердце и мозг компьютера, а память и память — электронные компоненты, состоящие из множества транзисторов. Он получает ввод данных, выполняет инструкции и обрабатывает информацию. Он взаимодействует с устройствами ввода/вывода (I/O), которые отправляют данные в ЦП и получают данные от него.
С функциональной точки зрения внутренняя часть ЦП состоит изРегистры, контроллеры, операторы и часыОн состоит из четырех частей, и части соединены электрическими сигналами.
-
寄存器Он является частью центрального процессора. Их можно использовать для временного хранения инструкций, данных и адресов. Думайте об этом как о типе памяти. В зависимости от типа ЦП будет иметь внутри от 20 до 100 регистров. -
控制器Отвечает за преобразование инструкций на память в регистр и контролирует компьютер в соответствии с результатами инструкции. -
运算器Отвечает за вычисление данных, считываемых в регистры из памяти. -
时钟Отвечает за выдачу тактового сигнала для ЦП, чтобы начать отсчет времени
ЦП — это набор регистров
Из четырех структур ЦП нашим программистам нужно понять только寄存器Все, остальным трем не нужно уделять слишком много внимания, почему вы так говорите? Потому что программы описывают регистры как объекты.
Разные типы ЦП имеют разные типы и количество внутренних регистров, а также диапазон значений, хранящихся в регистрах. Однако в зависимости от функции регистры можно разделить на следующие категории:
| тип | Функции |
|---|---|
| регистр накопления | Хранит данные запуска и расчетные данные. |
| регистр флагов | Он используется для отражения состояния процессора и некоторых особенностей результатов операций, а также для контроля выполнения инструкций. |
| счетчик команд | Счетчик программы - это адрес, где находится следующая инструкция, сохраняется. |
| базовый регистр | Начальное местоположение памяти, где хранятся данные |
| индексный регистр | Сохраняет относительный адрес базового регистра |
| регистр общего назначения | Хранить произвольные данные |
| регистр команд | Сохраняет выполняемую инструкцию, используемую внутри ЦП, и программист не может читать или записывать этот регистр. |
| стековый регистр | начало области стека |
вСчетчик программ, регистр накопления, регистр флагов, регистр команд и регистр стекаТолько один, есть другой более общий реестр.
Каждый регистр описан ниже
счетчик команд
程序计数器(Program Counter)- это адрес устройства, в котором хранится следующая инструкция.
При выполнении программы начальным значением ПК является адрес первой инструкции программы.При последовательном выполнении программы,控制器Сначала из памяти извлекается инструкция по адресу инструкции, указанному программным счетчиком, а затем инструкция анализируется и выполняется, а значение PC увеличивается на 1, чтобы указать на следующую команду, которая должна быть выполнена.
Рассмотрим подробно процесс выполнения счетчика программ на примере.
Это операция по добавлению, программа запускается, и после компиляции и разбора операционная система копирует программу с жесткого диска в память.Программа в примере складывает 123 и 456, и выводит результат на дисплей.
адрес0100является начальной позицией выполнения программы. После того, как Windows и другие операционные системы скопируют программу с жесткого диска в память, она установит счетчик программ в качестве начальной позиции 0100, а затем выполнит программу.После выполнения каждой инструкции значение счетчика программ будет увеличиваться на 1 (или прямо указать на следующий инструк. адрес), то ЦП прочитает команду из памяти и выполнит ее в соответствии со значением счетчика команд, т. е.Счетчик программ контролирует ход выполнения программы..
Механизмы условного ветвления и цикла
В языках высокого уровня существует три основных типа условного потока управления:顺序执行、条件分支、循环判断В-третьих, последовательное выполнение заключается в выполнении инструкций в порядке содержания адреса. Условная ветвь — это инструкция, которая выполняет произвольный адрес на основе условия. Цикл — это многократное выполнение инструкции по одному и тому же адресу.
- Случай последовательного выполнения относительно прост, значение счетчика программ равно +1 для каждой выполняемой инструкции.
- Условные и циклические переходы заставляют счетчик программ указывать на произвольный адрес, так что программа может вернуться к предыдущему адресу, чтобы повторить ту же инструкцию или перейти к любой инструкции.
В качестве примера воспринимается следующее, чтобы проиллюстрировать процесс выполнения программы (цикл также похож)
Процесс запуска программы такой же, как и процесс последовательности.ЦП начинает выполнять команду с 0100.Последовательно выполняются как 0100, так и 0101.Последовательность значений ПК равна +1.Когда инструкция по адресу 0102 выполняется, значение регистра 0106 считается больше 0. , перейти (перейти) к инструкции с адресом 0104, вывести значение на дисплей, а затем завершить программу, инструкция 0103 пропускается, что такой же как и в нашей программеif()Решение такое же, если условие не выполняется, инструкция будет пропущена напрямую. Поэтому процесс выполнения ПК не напрямую +1, а адрес следующей инструкции.
регистр флага
Используются условные и циклические переходыjump(跳转指令), он будет судить, следует ли прыгать в соответствии с текущей инструкцией, о которой мы упоминали выше.标志寄存器, независимо от того, будет ли результат работы текущего регистра накопления положительным, отрицательным или нулевым, флаговый регистр сохранит его
Когда ЦП выполняет операцию, значение регистра флага будет автоматически установлено в соответствии с результатом текущей операции Положительное, отрицательное и нулевое состояния результата операции представлены тремя битами регистра флага. Когда соответствующие результаты первого байтового бита, второго байтового бита и третьего байтового бита регистра флага равны 1, они представляют положительные числа, нуль и отрицательные числа соответственно.
Механизм реализации ЦП более интересен.Предполагается, что YYY, хранящиеся в XXX, и универсальный регистр, хранящийся в регистре накопления, за сравнением, вычислительный механизм ЦП будет выполнять операции вычитания. Независимо от результата вычитания, ноль или отрицательный результат, он будет сохранен в регистре логотипа. В результате XXX больше, чем YYY, и результат равен нулю, чтобы указать XXX и YYY, а результат отрицательно указывает на то, что XXX меньше, чем YYY. Директива для сравнения программ, фактически выполняемая внутри ЦП减法операция.
механизм вызова функции
Далее продолжаем знакомить с механизмом вызова функции.Даже если это программа, написанная на языке высокого уровня, обработка вызова функции реализуется путем установки значения программного счетчика на адрес хранения функции. После того, как функция выполнит инструкцию перехода, она должна выполнить обработку возврата.Простой переход инструкции не имеет смысла.Ниже приведен пример реализации перехода функции.
Переменным FIG a и b соответственно будут присвоены 123 и 456, вызывая метод MyFun (a, b), инструкцию перехода. Адрес FIG на языке C компилируется в машинный язык после адресной операции, поскольку строчная программа C, скомпилированная во множество строк, обычно превращает машинный язык, адрес на диаграмме рассредоточен. После выполнения инструкции MyFun (a, b) программа возвращается к следующей инструкции MyFun (a, b), ЦП продолжает выполнять следующие инструкции.
Две инструкции, которые важны для вызова и возврата функции:callиreturnПрежде чем установить адрес входа функции в программный счетчик, инструкция вызова сохранит адрес инструкции, которая должна быть выполнена после вызова функции, в основной памяти, называемой стеком. После обработки функции инструкция возврата выполняется через выход из функции. Функция инструкции возврата состоит в том, чтобы установить адрес, хранящийся в стеке, в программный счетчик. Перед вызовом функции MyFun в стеке сохраняется адрес 0154. После обработки функции MyFun адрес 0154 сохраняется в программном счетчике. Процесс вызова выглядит следующим образом
В некоторых условных операторах или операторах цикла языка высокого уровня обработка вызовов функций будет преобразована в инструкции вызова, а обработка после завершения функции будет преобразована в инструкции возврата.
Массив по адресу и индексу
Далее, давайте посмотрим на базовый регистр и индексный регистр. С помощью этих двух регистров мы можем разделить определенную область в основной памяти для выполнения операций, подобных массивам. Во-первых, мы используем шестнадцатеричные числа для разделения памяти компьютера. на 00000000 - FFFFFFFF. Затем для любого адреса памяти в этом диапазоне, пока есть 32-битный регистр, можно просмотреть все адреса. Но если вы хотите разделить конкретную область памяти наподобие массива для непрерывного просмотра, удобнее использовать два регистра.
Например, мы используем два регистра (базовый регистр и индексный регистр) для представления значения памяти.
Это представление очень похоже на построение массива,数组Это относится к структуре данных, в которой данные одинаковой длины располагаются в памяти непрерывно. Используйте имя массива для представления всех значений массива и различайте каждый элемент данных массива по индексу, например: a[0] - a[4],[]0 - 4 внутри являются нижними индексами массива.
Процесс выполнения инструкций ЦП
Почти все процессоры типа фон Неймана работают в пять этапов:Прием инструкций, расшифровка инструкций, выполнение инструкций, доступ к номеру и запись в ответ.
-
取指令Стадия — это процесс чтения инструкции из памяти в регистр ЦП, а программный регистр используется для хранения адреса следующей инструкции. -
指令译码На этапе, после завершения выборки инструкции, он сразу переходит к этапу декодирования инструкции.На этапе декодирования инструкции декодер инструкции разделяет и интерпретирует выбранные инструкции в соответствии с заранее определенным форматом инструкции, а также идентифицирует и различает различные типы инструкций и различные методы получения операндов. -
执行指令На этапе после завершения декодирования эту инструкцию необходимо выполнить.Задачей этого этапа является выполнение различных операций, указанных в инструкции, и конкретная реализация функции инструкции. -
访问取数На этапе, в соответствии с потребностями инструкции, может потребоваться извлечение данных из памяти.Задачей этого этапа является получение адреса операнда в основной памяти по коду адреса инструкции, и чтение операнд из основной памяти для работы. -
结果写回Стадия, как последняя стадия, стадия обратной записи результата (Write Back, WB) «записывает» данные результата операции стадии выполнения инструкции в какую-либо форму хранения: данные результата часто записываются во внутренние регистры ЦП для последующего использовать быстрый доступ к инструкции;
ОЗУ
ЦП и память как кучка неразлучных любовников.Они неразлучные пары.Без памяти ЦП не может выполнять программные инструкции,поэтому компьютер теряет смысл;если только память не может выполнять инструкции,то компьютер все равно не может работать.
Так что же такое память? Как взаимодействуют память и процессор? Давайте представим
что такое память
Память — один из важнейших компонентов компьютера, это мост между программой и процессором. Все программы в компьютере выполняются в памяти, поэтому память имеет большое влияние на компьютер, и память также называется主存, функция которого заключается в хранении рабочих данных в ЦП и обмене данными с внешними запоминающими устройствами, такими как жесткие диски. Пока компьютер работает, ЦП будет передавать данные для расчета в основную память для работы.По завершении операции ЦП передает результат.Работа основной памяти также определяет стабильную работу компьютер.
физическая структура памяти
Внутренняя часть памяти состоит из различных схем ИС, и ее типы очень велики, но в основном она делится на три типа памяти.
- Оперативная память (ОЗУ): самый важный тип памяти, что означает, что данные могут быть как считаны, так и записаны. Когда машина выключена, информация в памяти будет
丢失. - Память только для чтения (ПЗУ): ПЗУ обычно можно использовать только для чтения данных, а не для записи данных, но когда машина выключена, данные не будут потеряны.
- Кэш: Кэш также то, что мы часто видим, он делится на кеш первого уровня (кэш L1), вторичный кеш (кэш L2), трехуровневый кеш (кэш L3), расположен между памятью и процессором. скорость записи выше памяти
更快памяти. Когда ЦП записывает данные в память, эти данные также записываются в кэш. Когда процессору необходимо прочитать данные, он будет считывать их непосредственно из кеша.Конечно, если требуемых данных нет в кеше, процессор снова считывает данные из памяти.
ИС памяти представляет собой полную структуру, и она также имеет источник питания, сигналы адреса, сигналы данных, сигналы управления и выводы ИС для адресации для чтения и записи данных. Ниже приведена макетная схема распиновки микросхемы.
На рисунке VCC и GND представляют собой источник питания, A0–A9 — контакты адресного сигнала, D0–D7 представляют сигнал управления, RD и WR — хорошие управляющие сигналы, я использовал разные цвета, чтобы различать, подключите источник питания к VCC. и GND, вы можете передавать сигналы 0 и 1 на другие контакты, в большинстве случаев,+5В означает 1, 0В означает 0.
Все мы знаем, что память используется для хранения данных, так сколько же данных можно хранить в этой микросхеме памяти? D0 - D7 представляют сигналы данных, то есть 8 бит = 1 байт данных могут быть введены и выведены одновременно. A0 - A9 - всего десять адресных сигналов, что означает, что можно указать 00000 00000 - 11111 11111, всего 2 в 10-й степени =1024个地址.每个地址都会存放 1 byte 的数据,因此我们可以得出内存 IC 的容量就是 1 KB。
Процесс чтения и записи памяти
Давайте сосредоточимся на процессе чтения и записи данных микросхемой памяти! Давайте рассмотрим модель записи и чтения данных в микросхему памяти и из нее.
Чтобы описать этот процесс подробно, если мы хотим записать 1 байт данных в микросхему памяти, процесс выглядит следующим образом:
- Сначала подключите источник питания +5 В к VCC, подключите источник питания 0 В к GND и используйте
A0 - A9указать место хранения данных, а затем ввести значение данных вD0 - D7сигнал данных и положитьWR(write)установлен в 1, после выполнения этих операций данные могут быть записаны в память IC - При чтении данных необходимо только указать место хранения данных через адресные сигналы A0 - A9, а затем установить значение RD равным 1.
- RD и WR на рисунке также называются управляющими сигналами. Когда и WR, и RD равны 0, операции записи и чтения выполняться не могут.
Реалистичная модель памяти
Чтобы облегчить память, мы сопоставляем модель памяти с моделью нашего реального мира.В реальном мире модель памяти очень похожа на здание, в котором мы живем. В этом здании первый этаж может хранить один байт данных, а номер этажа地址Ниже приведена модельная диаграмма памяти и интеграции пола
Мы знаем, что данные в программе представляют собой не только числовые значения, но и数据类型Понятие , с точки зрения памяти, означает размер занимаемой памяти (количество занимаемых этажей). Даже если физически заставить читать и записывать данные блоками по 1 байту, в программе, указав тип данных, можно читать и записывать блоками определенное количество байт.
бинарный
Все мы знаем, что нижний уровень компьютера использует двоичные данные для потоковой передачи данных, так зачем использовать двоичные данные для представления компьютера? Другими словами, что такое двоичное число? На шаге расширения, как использовать двоичный код для сложения, вычитания, умножения и деления? Давайте взглянем
Что такое двоичное число
Так что же такое двоичные числа? Чтобы проиллюстрировать этот момент, мы сначала00100111Преобразуйте это число в десятичное число, чтобы увидеть, преобразуйте двоичное число в десятичное число, непосредственно преобразуйте значение в каждой позиции * битовый вес, затем мы преобразуем указанное выше значение.
То есть двоичные числа представляют00100111В десятичном виде получается 39. Это 39 записывается не как 3 и 9, а как 3*10+9*1.10 , 1Это вес позиции и т. д. Вес позиции в приведенном выше примере идет от высокого к низкому.7 6 5 4 3 2 1 0. Этот битовый вес также называется мощностью, поэтому старший бит равен 2 в 7-й степени, 2 в 6-й степени и так далее. Операция с двоичными числами каждый раз принимает в качестве основания 2. Это 2 относится к основанию, поэтому основание десятичных чисел также равно 10. В любом случае значение битового веса равноКоличество цифр - 1, тогда вес первого бита равен 1 - 1 = 0, вес второго бита равен 2 - 1 = 1 и так далее.
Тогда двоичное число, о котором мы говорим, на самом деле является числом, представленным двумя числами 0 и 1. Его основание равно 2, а его значение является результатом суммирования количества цифр * веса каждого числа. Обычно мы говорим, что значение относится к десятичному числу, то его значение равно 3 * 10 + 9 * 1 = 39.
Связь между операциями сдвига и умножения и деления
Изучив двоичные числа, давайте взглянем на двоичные операции.Как и десятичные числа, сложение, вычитание, умножение и деление также применимы к двоичным числам, если вы обращаете внимание на каждое двоичное число. Работа с двоичными числами также является уникальной операцией компьютерных программ, поэтому необходимо понимать работу с двоичными числами.
Сначала давайте представим移位Операция, операция сдвига относится к операциям сдвига влево и вправо элементов в различных позициях двоичного значения, как показано на следующем рисунке.
Дополнение
Мы сейчас не рассматривали случай сдвига вправо, потому что старшее значение, освободившееся после сдвига вправо, имеет две формы: 0 и 1. Чтобы различать, когда прибавлять 0, а когда прибавлять 1, сначала нужно освоить представление двоичных чисел.负数Методы.
При представлении отрицательных значений в двоичных числах в качестве знака обычно используется старший бит, поэтому мы берем этот старший бит в качестве бита знака.Когда бит знака равен 0, это означает正数, когда это 1, это означает负数. Итак, как представить -1 в двоичном формате? Многие люди могут так подумать: поскольку двоичное число 10000 0001, старший бит является битом знака, поэтому правильное представление -1 должно быть1000 0001, но действительно ли этот ответ правильный?
В компьютерном мире нет вычитания, когда компьютер выполняет вычитание, он фактически выполняет сложение, то есть вычитание, которое реализуется сложением. Например, 100 - 50, на самом деле должно быть 100 + (-50) при просмотре компьютером, по этой причине необходимо использовать его при представлении отрицательных чисел.二进制补数, дополнение представляет собой отрицательное число, представленное положительным числом.
чтобы достичь补数, нам нужно инвертировать все значения двоичных разрядов, а затем прибавить к результату +1. Сначала запомните этот вывод, давайте его продемонстрируем.
В частности, необходимо сначала получить двоичное число определенного значения, затем инвертировать каждый бит двоичного числа (0 ---> 1 , 1 ---> 0) и, наконец, инвертировать инвертированное Число + 1, таким образом завершение приобретения дополнения.
Приобретение дополнений нелегко понять интуитивно, но это очень логически строго.Например, давайте посмотрим на процесс 1-1.Давайте сначала воспользуемся приведенным выше1000 0001(Это дополнение до 1, если вы не знаете, см. выше, правильность игнорируется, просто используется для некоторых вычислений) для выражения
Странно, 1 - 1 становится 130 , а не 0, так что можно сделать вывод1000 0001Представление -1 совершенно неверно.
Так как же правильно выразиться? На самом деле, мы уже приводили результаты выше, т.е.1111 1111, чтобы продемонстрировать свою правильность
Мы можем видеть, что 1 - 1 на самом деле 1 + (-1), и после отрицания приведенного выше + 1 для -1 становится1111 1111, а затем добавьте 1, чтобы получить девятибитный результат1 0000 0000, результат получился溢出, компьютер будет напрямую игнорировать бит переполнения, то есть напрямую отбрасывать старший бит 1, станет0000 0000. То есть 0, результат правильный, поэтому1111 1111Это означает -1 .
Следовательно, двоичное представление отрицательного числа заключается в том, чтобы сначала найти его дополнение.Процесс решения дополнения заключается в инвертировании двоичных разрядов исходного значения, а затем прибавлении результата + 1.
Разница между арифметическим сдвигом вправо и логическим сдвигом вправо
Поняв дополнение, давайте еще раз рассмотрим вопрос о сдвиге вправо.Есть два случая, когда старший бит освобождается при сдвиге вправо после сдвига.0 和 1.
При выполнении операции сдвига вправо над двоичным числом как значением со знаком старший бит должен быть заполнен значением бита знака (0 или 1) перед сдвигом. это называется算数右移. Если значение использует отрицательное значение, представленное дополнением, то после сдвига вправо добавьте 1 к освободившемуся старшему биту, это может быть правильно представлено1/2,1/4,1/8Числовые операции и т.д. Если это положительное число, просто добавьте 0 к пустой позиции.
Давайте посмотрим на пример сдвига вправо. Сдвинем -4 вправо на два места, посмотрим на схему сдвига
Как показано на рисунке выше, в случае логического сдвига вправо -4, сдвинутое вправо на два бита, станет63, явно не 1/4 его, поэтому логический сдвиг вправо использовать нельзя, то в случае арифметического сдвига вправо сдвиг вправо на два бита станет-1, что, очевидно, составляет 1/4 от него, поэтому используется арифметический сдвиг вправо.
Тогда можно сделать вывод:При сдвиге влево, будь то графическое или числовое значение, после сдвига нужно только заполнить младшие разряды 0, при сдвиге вправо нужно судить, логический это сдвиг вправо или арифметический сдвиг вправо по ситуации.
Далее описывается расширение знака:Назначение расширения данных по знаку состоит в том, чтобы получить результат с удвоенным числом цифр, но размер значения остается неизменным, чтобы удовлетворить требованиям некоторых инструкций по количеству операндов, таких как делимое, которое в два раза длиннее делителя, и, например, число разрядов данных удлиняется, чтобы сократить процесс вычисления ошибок в .
Взяв в качестве примера 8-битный двоичный код, расширение знака относится к преобразованию значения в 16-битные и 32-битные двоичные числа при сохранении значения без изменений. будет0111 1111Когда это положительное 8-разрядное двоичное число преобразуется в 16-разрядное двоичное число, легко получить0000 0000 0111 1111Это правильный результат, но что-то вроде1111 1111Как быть со значением, представленным таким дополнением? непосредственно представить его как1111 1111 1111 1111Вот и все. Другими словами, независимо от того, является ли это число положительным или отрицательным, представленным дополнением, вам нужно только заполнить старшие биты 0 и 1.
Отношения между памятью и диском
Все мы знаем, что пять основных компонентов компьютера存储器,控制器,运算器,输入和输出设备, с точки зрения функции хранения, память можно разделить на内存и磁盘, мы представили память выше, давайте представим диск и связь между диском и памятью
Программа не может работать без чтения в память
Основными компонентами хранения данных компьютера являются память и диски.Программы, хранящиеся на диске, должны быть загружены в память для запуска, программа, сохраненная на диске, не может быть запущена напрямую, потому что центральный процессор, отвечающий за синтаксический анализ и запуск содержимого программы, должен указать адрес памяти через программный счетчик, чтобы прочитать инструкции программы.
структура диска
дисковый кеш
Как мы упоминали выше, диски и память часто имеют взаимовыгодные и симбиотические отношения, взаимодействуют друг с другом и поддерживают хорошие отношения сотрудничества друг с другом. Каждый раз, когда памяти нужно прочитать данные с диска, она неизбежно будет считывать одно и то же содержимое, поэтому должна быть роль, отвечающая за хранение того, что нам часто нужно читать. Когда мы делаем программное обеспечение, мы часто используем его缓存技术, то и аппаратный уровень не исключение, на диске тоже есть кеш, а кеш диска называется磁盘缓存.
Дисковый кеш относится к способу хранения данных, считанных с диска, в память, так что, когда то же самое содержимое нужно будет прочитать в следующий раз, оно будет считано не через фактический диск, а через дисковый кеш. Появление определенной технологии или фреймворка обязательно решит определенную проблему, тогда дисковый кеш значительно увеличится.Улучшена скорость доступа к диску.
Виртуальная память
虚拟内存Это вторая среда, через которую взаимодействуют память и диск. Виртуальная память относится к использованию части диска в качестве假想内存использовать. Это отличается от того, что дисковый кеш является воображаемым диском (фактически памятью), а виртуальная память является воображаемой памятью (фактически диском).
Виртуальная память — это метод управления памятью компьютерных систем. это заставляет приложение думать, что оно连续可用памяти (полное адресное пространство), но на практике обычно разбивается на несколько физических фрагментов, а части хранятся на внешнем менеджере дисков с подкачкой данных при необходимости.
С помощью виртуальной памяти программы могут работать даже при нехватке памяти. Например, вы по-прежнему можете запустить программу размером 10 МБ, имея всего 5 МБ свободного места в памяти. Поскольку ЦП может выполнять только программы, загруженные в память, пространство в виртуальной памяти необходимо сравнить с пространством в памяти.置换(swap), затем запустите программу.
Переключение между виртуальной памятью и памятью
Методы виртуальной памяти分页式и分段式два вида. Windows использует пейджинг. Этот метод означает, что без учета структуры программы работающая программа разбивается на страницы определенного размера, а页Замените устройство. При подкачке мы читаем содержимое диска в память, называемуюPage In, запись содержимого памяти на диск называетсяPage Out. Размер страницы компьютеров Windows составляет 4 КБ, то есть приложение нужно разделить на страницы по 4 КБ, разместить на диске постранично, а затем заменить.
Для реализации функции памяти Windows предоставляет файл (файл подкачки, файл подкачки), используемый виртуальной памятью на диске. Этот файл создается и управляется Windows, а размер файла равен размеру виртуальной памяти, обычно в 1-2 раза больше размера памяти.
физическая структура диска
Прежде чем мы представили физическую структуру ЦП и памяти, теперь давайте представим физическую структуру диска.Физическая структура диска относится к форме, в которой диск хранит данные..
Диск используется путем разделения его физической поверхности на пробелы. Существует два способа деления:可变长方式и扇区方式. Первый делит физическую структуру на пространства переменной длины, а второй делит структуру диска на пространства фиксированной длины. Как правило, жесткие диски и дискеты, используемые Windows, используют сектора. В секторе пространство, которое делит поверхность диска на несколько концентрических окружностей, равно磁道, дорожка делится на пространство для хранения фиксированного размера, которое扇区
扇区Это наименьшая единица физического чтения и записи на диск. Диски, используемые в Windows, обычно имеют размер сектора 512 байт. Однако Windows логически считывает и записывает диск в единицах секторов, кратных кластерам. В соответствии с различными функциями емкости диска 1 кластер может быть 512 байт (1 кластер = 1 сектор), 1 КБ (1 кластер = 2 сектора), 2 КБ, 4 КБ, 8 КБ, 16 КБ, 32 КБ (1 кластер = 64 сектора). Размеры кластера и сектора равны.
алгоритм сжатия
Мы должны иметь压缩и解压缩Работа с файлами: когда файл слишком большой, мы используем сжатие файла, чтобы уменьшить размер файла. Например, ограничение на загрузку файлов в WeChat — 100 МБ, у меня здесь есть папка, которую нельзя загрузить, но файл после того, как я его распаковаю, точно будет меньше 100 МБ, тогда мой файл можно будет загрузить.
Кроме того, когда мы сохраняем фотографии, сделанные камерой, на компьютер, мы также будем использовать алгоритм сжатия для сжатия файлов.JPEG.
Так что же такое алгоритм сжатия? Как определяется алгоритм сжатия? Прежде чем мы поймем алгоритм, нам нужно понять, как хранится файл
файловое хранилище
Файл — это форма хранения данных на носителе данных, таком как диск. Основной единицей хранения данных в программном файле является字节. Размер файла выражается в xxxKB, xxxMB и т. д., поскольку файл находится в байтах.B = Byteхранится в единицах.
Файл представляет собой набор байтов данных. Существует 256 видов байтовых данных, представленных 1 байтом (8 бит), и в двоичном представлении это 0000 0000 - 1111 1111 . Файл является текстовым файлом, если данные, хранящиеся в файле, являются текстовыми. Если это графика, то файл является файлом изображения. В любом случае количество байтов в файле равно连续存储из.
Определение алгоритмов сжатия
Вышеупомянутая коллекция файлов на самом деле представляет собой набор байтовых данных, поэтому мы можем определить алгоритм сжатия.
压缩算法(compaction algorithm)Он относится к алгоритму сжатия данных, который в основном включает два этапа сжатия и восстановления (декомпрессии).
По сути, это алгоритм уменьшения байтового пространства и занимаемого пространства файла без изменения исходных атрибутов файла.
В соответствии с определением алгоритма сжатия мы можем разделить его на разные типы:
С потерями и без потерь
Сжатие без потерь: есть无失真地Реконструируйте из сжатых данных, чтобы точно восстановить исходные данные. Его можно использовать в случаях, когда требуется строгая точность данных, например, при сжатии исполняемых файлов и обычных файлов, сжатии дисков и сжатии мультимедийных данных. Сжатие этого метода относительно невелико. Например, дифференциальное кодирование, RLE, кодирование Хаффмана, LZW-кодирование, арифметическое кодирование.
Сжатие с потерями: есть искажения,不能完全准确地Чтобы восстановить исходные данные, реконструированные данные являются лишь приближением к исходным данным. Его можно использовать в случаях, когда точность данных невысока, например, при сжатии мультимедийных данных. Сжатие этого метода относительно велико. Например, предиктивное кодирование, фонологическое кодирование, фрактальное сжатие, вейвлет-сжатие, JPEG/MPEG.
симметрия
Если сложность алгоритма кодека аналогична требуемому времени, это симметричный метод кодирования, и большинство алгоритмов сжатия являются симметричными. Но есть и асимметричные, обычно трудно кодируемые и легко декодируемые, такие как кодирование Хаффмана и фрактальное кодирование. Но метод кодирования, используемый в криптографии, является противоположным, его легко кодировать и очень трудно декодировать.
Межкадровый и внутрикадровый
При кодировании видео используются как внутрикадровые, так и межкадровые методы кодирования.Внутрикадровое кодирование относится к методу кодирования, который выполняется независимо внутри кадра изображения, что совпадает с кодированием статических изображений, таких как JPEG. ; в то время как межкадровое кодирование должно относиться к передней и задней части.Только кадры могут быть закодированы и декодированы, и в процессе кодирования учитывается сжатие временной избыточности между кадрами, например MPEG.
в реальном времени
В некоторых мультимедийных приложениях необходимо обрабатывать или передавать данные в режиме реального времени (например, цифровая запись в реальном времени и видеозапись, воспроизведение MP3/RM/VCD/DVD, видео/аудио по запросу, сетевое вещание в прямом эфире, видеотелефония, видеоконференции). ), кодирование и декодирование Обычно требуется, чтобы задержка составляла ≤50 мс. Для этого требуются простые/быстрые/эффективные алгоритмы и высокоскоростные/сложные чипы CPU/DSP.
оценка
Некоторые алгоритмы сжатия могут одновременно обрабатывать мультимедийные данные с разным разрешением, разной скоростью передачи и разным уровнем качества, например, JPEG2000, MPEG-2/4.
Эти понятия несколько абстрактны, в основном для того, чтобы каждый мог понять классификацию алгоритмов сжатия.Давайте проанализируем характеристики, преимущества и недостатки нескольких часто используемых алгоритмов сжатия.
Понимание нескольких часто используемых алгоритмов сжатия
Механизм алгоритма RLE
Далее давайте формально рассмотрим механизм сжатия файлов. Сначала попробуемAAAAAABBCDDEEEEEFЭти 17 файлов символов половинной ширины (текстовые файлы) сжаты. Хотя эти слова имеют мало практического значения, они очень подходят для описанияRLEкомпрессионный механизм.
Поскольку символы половинной ширины (на самом деле английские символы) хранятся в файле как 1 байт, размер вышеуказанного файла составляет 17 байт. Как показано
Итак, как я могу сжать этот файл? С таким же успехом можно подумать, что если файл может быть меньше 17 байт, мы можем использовать любой алгоритм сжатия.
Самый очевидный способ сжатия, о котором, я думаю, вы уже подумали, это поместить одинаковые символы去重化, это,字符 * 重复次数способ сжатия. Итак, после того, как вышеуказанный файл будет сжат, он станет следующим
Из рисунка мы видим, чтоAAAAAABBCDDEEEEEF17 символов были успешно сжаты вA6B2C1D2E5F112 символов, то есть 12/17 = 70%, степень сжатия 70%, сжатие прошло успешно.
Таким образом, используйте содержимое файла с数据 * 重复次数Метод сжатия, выраженный в видеRLE(Run Length Encoding, 行程长度编码)алгоритм. Алгоритм RLE является хорошим методом сжатия, часто используемым в сжатых изображениях и т.п. Поскольку природа файла изображения также представляет собой набор байтовых данных, его можно сжать с помощью алгоритма RLE.
Алгоритм Хаффмана и код Морзе
Давайте представим другой алгоритм сжатия, алгоритм Хаффмана. Прежде чем вы поймете алгоритм Хаффмана, вы должны отказаться半角英文数字的1个字符是1个字节(8位)的数据. Давайте рассмотрим основную идею алгоритма Хаффмана.
Текстовые файлы состоят из разных типов символов, и количество вхождений разных символов также различно. Например, в определенном текстовом файле буква A встречается около 100 раз, а буква Q используется только 3 раза, что очень часто встречается в таких случаях. Ключ к алгоритму Хаффмана заключается в том, чтоМножественные вхождения данных, представленных числом байтов меньше 8, не часто используемые данные могут использоваться более 8 байт представления. Когда и A, и Q представлены 8 битами, размер исходного файла составляет 100 x 8 бит + 3 x 8 бит = 824 бита, предполагая, что A представлен 2 битами, а Q представлен 10 битами, это 2 * 100 + 3 * 10 = 230 бит.
Однако следует отметить, что конечное хранилище на диске составляет 8 бит в качестве байта для сохранения файла.
Алгоритм Хаффмана сложнее, давайте попробуем его, прежде чем углубляться甜品,Узнать о莫尔斯编码, вы, должно быть, смотрели американское телевидение или фильмы о войне.В связи на войне часто используется кодировка Морзе для передачи информации, такой как следующие
Далее, давайте объясним кодировку Морзе, далее идет кодировка Морзе示例, все считают 1 короткой точкой (di), а 11 — длинной точкой (щелчок).
В кодировке Морзе обычно используются наиболее часто встречающиеся символы в тексте.短编码Представлять. Как показано в таблице, если бит, представляющий короткую точку, равен 1, а бит, представляющий длинную точку, равен 11, то символ данных E (тик) может быть представлен как 1, а C (тик) может быть представлен как 9 бит110101101Представлять. В реальной кодировке Морзе, если длина короткой точки равна 1, длина длинной точки равна 3, а интервал между короткой точкой и длинной точкой равен 1. Длина здесь относится к длине звука. Например, мы хотим использовать приведенный выше пример AAAAAABBCDDEEEEEF, чтобы переписать его в кодировке Морзе, В кодировке Морзе между каждым символом необходимо добавлять символы, представляющие временные интервалы. Здесь мы используем 00 для различения.
Таким образом, текст AAAAAABBCDDEEEEEF становится A * 6 раз + B * 2 раза + C * 1 раз + D * 2 раза + E * 5 раз + F * 1 раз + символьный интервал * 16 = 4 бита * 6 раз + 8 бит * 2 раза + 9 бит * 1 раз + 6 бит * 2 раза + 1 бит * 5 раз + 8 бит * 1 раз + 2 бита * 16 раз = 106 бит = 14 байт.
Следовательно, степень сжатия кода Морсиана составляет 14/17 = 82 %..效率并不太突出。
Реализуйте алгоритм Хаффмана с двоичным деревом
Как упоминалось ранее, кодировка Морзе определяет длину закодированных данных, представляющих каждый символ, в соответствии с частотой появления каждого символа в повседневном тексте. Однако эта схема кодирования не самая эффективная для текстов типа AAAAAABBCDDEEEEEF.
Давайте посмотрим на алгоритм Хаффмана. Алгоритм Хаффмана заключается в построении оптимальной системы кодирования для каждого целевого файла сжатия и выполнении сжатия на основе системы кодирования. Поэтому то, какая кодировка (кодировка Хаффмана) используется для разделения данных, зависит от каждого файла. Закодированная по Хаффману информация и сжатые данные хранятся в файлах, сжатых с помощью алгоритма Хаффмана.
Далее мы имеем дело с символами A - F в AAAAAABBCDDEEEEEF, согласно出现频率高的字符用尽量少的位数编码来表示Этот принцип организован. После сортировки по частоте появления от высокого к низкому результаты следующие, а также указана схема кодирования.
| персонаж | Частота возникновения | кодировка (схема) | количество цифр |
|---|---|---|---|
| A | 6 | 0 | 1 |
| E | 5 | 1 | 1 |
| B | 2 | 10 | 2 |
| D | 2 | 11 | 2 |
| C | 1 | 100 | 3 |
| F | 1 | 101 | 3 |
В схеме кодирования в приведенной выше таблице, по мере уменьшения частоты появления, количество битов данных символьной информации кодирования также постепенно увеличивается, от первых 1 бита, 2 битов до 3 битов. Однако с этой системой кодирования есть проблема: вы не знаете трехбитный код числа 100. Что означает использование трех кодов 1, 0 и 0 для представления Е, А и А? Или использовать 10, 0 для представления B, A? Или использовать 100 для представления C?
В алгоритме Хаффмана, используя дерево Хаффмана для построения системы кодирования, даже без использования отличительного знака, можно построить систему кодирования, которую можно четко различить. Однако алгоритм дерева Хаффмана более сложен.Следующий процесс построения дерева Хаффмана.
Деревья в природе выращивают листья от корня, а деревья Хаффмана растут от листьев к ветвям.
Дерево Хаффмана может улучшить степень сжатия
После использования дерева Хаффмана данные с более высокой частотой занимают меньше битов, что также является основной идеей дерева Хаффмана. Как видно из шага 2 на приведенном выше рисунке, когда ветви соединяют данные, мы начинаем с данных с более низкой частотой. Это означает, что менее частые данные достигают корней и больше ветвей. А большее количество ветвей означает, что количество закодированных битов увеличивается.
Далее, давайте посмотрим на степень сжатия дерева Хаффмана.Используя данные, полученные на рисунке выше, AAAAAABBCDDEEEEEF составляет 000000000000 100100 110 101101 0101010101 111, 40 бит = 5 байт. Данные до сжатия составляют 17 байт, а сжатые данные достигают поразительных 5 байт, то есть степень сжатия = 5/17 = 29%.Такая высокая степень сжатия просто поражает.
Вы можете ссылаться на него, независимо от типа данных, вы можете использовать дерево Хаффмана в качестве алгоритма сжатия.
| тип файла | До сжатия | после сжатия | коэффициент сжатия |
|---|---|---|---|
| текстовый файл | 14862 байта | 4119 байт | 28% |
| файл изображения | 96062 байта | 9456 байт | 10% |
| EXE | 24576 байт | 4652 байта | 19% |
Обратимое и необратимое сжатие
Наконец, давайте взглянем на формат данных файла изображения. Целью использования файлов изображений обычно является вывод данных изображения на такие устройства, как мониторы и принтеры. Распространенные форматы изображений:BMP,JPEG,TIFF,GIFформат и т.д.
- BMP: это форма изображения, созданная с помощью кисти, поставляемой с Windows.
- JPEG: это форма данных изображения, обычно используемая в цифровых камерах и т. д.
- TIFF: это формат изображения, который может быстро отображать природу данных, включая «теги» в файл.
- GIF: это форма данных, разработанная в США и требующая не более 256 цветов.
Файлы изображений могут использовать алгоритм RLE и алгоритм Хаффмана, описанные выше, потому что в большинстве случаев файлы изображений не требуют восстановления данных до того же состояния, что и до сжатия, что позволяет потерять некоторые данные. Мы называем сжатие, которое восстанавливает состояние до сжатия, как可逆压缩, сжатие, которое не может быть восстановлено до состояния до сжатия, называется非可逆压缩.
Вообще говоря, файлы в формате JPEG необратимо сжаты, поэтому после восстановления некоторая информация об изображении становится размытой. GIF — это обратимое сжатие.
Операционная система
Среда операционной системы
программа содержит运行环境Это содержание можно назватьОперационная среда = операционная система + оборудованиеоперационную систему также можно назвать программным обеспечением, состоящим из набора инструкций. Мы не вводим операционную систему, мы в основном вводим идентификацию оборудования.
Мы должны все играть в игры, что вам нужно сделать, прежде чем играть? Вам нужно проверить, может ли ваш ноутбук или компьютер играть в игры? Ниже приведена конфигурация игры (мисс вау)
Основная конфигурация на рисунке выглядит следующим образом
-
Версия операционной системы: относится к системной среде, в которой работает приложение.Сегодня на рынке представлены в основном три среды операционных систем: Windows, Linux и Unix.Как правило, большинство крупномасштабных игр, в которые мы играем, работают на Windows. можно сказать, что Windows Это игровой рай. Операционные системы Windows также будут дифференцированы, разделены на 32-битные операционные системы и 64-битные операционные системы, которые несовместимы друг с другом.
-
Процессор: процессор относится к центральному процессору.Вычислительная мощность вашего компьютера, как правило, количество инструкций, которые могут быть обработаны в секунду.Если ваш компьютер чувствует, что кассета не может быть загружена, это, вероятно, вызвано недостаточной вычислительной мощностью центрального процессора . . . Для более глубокого понимания, пожалуйста, прочитайте другую статью блогера:Процессор основных знаний, которые должны знать программисты
-
Видеокарта: Видеокарта отвечает за задачу вывода графики, поэтому ее еще называют графическим процессором (Graphic Processing Unit, GPU).Графическая карта тоже очень важна, например та, в которую я играл раньше.
剑灵Включение пятой передачи (на самом деле изображение становится четче) будет зависать, собственно, причина, по которой не может отображаться видеокарта. -
Память: это основная память, часть пространства для хранения, где ваше приложение может динамически анализировать инструкции во время работы.Его размер также может определять скорость работы вашего компьютера.Если вы хотите углубить свое понимание, пожалуйста, прочитайте статья другого блоггера статьяПамять о фундаментальных знаниях, которые должны знать программисты
-
Место для хранения: Место для хранения относится к дисковому пространству, занимаемому установкой приложения.Как видно из рисунка, минимальный объем памяти для этой игры должен быть больше 5 ГБ.На самом деле мы оставим большую его часть для установки игр .
С точки зрения операционной среды программы тип ЦП является особенно важным параметром.Для того, чтобы программа работала нормально, должна быть соблюдена минимальная конфигурация, требуемая ЦП.
CPU может интерпретировать только свой родной язык. Разные ЦП могут интерпретировать разные виды машинного языка. Программы на машинном языке называются本地代码(native code), программа, написанная программистом на языке высокого уровня, таком как C, представляет собой просто текстовый файл.文本文件(排除文字编码的问题)Отображение и редактирование в любой среде. мы называем его源代码. Скомпилировав исходный код, вы можете получить本地代码. Диаграмма ниже отражает этот процесс.
uploading-image-703074.png
ОС Windows преодолевает аппаратные различия за пределами процессора
Аппаратное обеспечение компьютера состоит не только из ЦП, но также данных и памяти для хранения программных инструкций, а также периферийных устройств, таких как клавиатуры, мониторы, жесткие диски и принтеры, подключенные через ввод-вывод.
В программном обеспечении WIndows ввод с клавиатуры, вывод на монитор и т. д. не посылают инструкции аппаратному обеспечению напрямую. Вместо этого он делает это, отправляя инструкции в Windows. Поэтому программисту не нужно обращать внимание на различный состав памяти и адресов ввода/вывода. Windows управляет аппаратным обеспечением, а не программным обеспечением, и программное обеспечение может управлять аппаратным обеспечением, управляя системой Windows.
Различия API между разными операционными системами
Далее мы рассмотрим типы операционных систем. Для одного и того же типа компьютера также будут различные варианты типов операционных систем, которые можно установить. Например, в дополнение к Windows, AT-совместимые машины также могут использовать Linux серии Unix и FreeBSD (также операционную систему Unix) и другие операционные системы. Конечно, прикладное программное обеспечение должно быть специально разработано для различных типов операционных систем.Тип ЦП отличается, и язык соответствующей машины также отличается, таким же образом,Тип операционной системы отличается, и способ, которым приложение передает инструкции в операционную систему, также отличается..
Способ, которым приложение отправляет инструкции в систему, называетсяAPI(Application Programming Interface). API-интерфейсы операционных систем Windows и Linux предоставляют комбинацию функций, которые может использовать любое приложение. Потому что API разных операционных систем разные. Следовательно, способ переноса того же приложения в другую операционную систему должен охватывать часть API, используемого приложением.
Ввод с клавиатуры, ввод с помощью мыши, вывод на монитор, ввод и вывод файлов, а также другие функции для взаимодействия с периферийными устройствами предоставляются через API.
Вот почему приложения Windows нельзя напрямую переносить в операционные системы Linux, поскольку API-интерфейсы настолько разные.
Под одним и тем же типом операционной системы API почти не зависит от железа. Однако из-за разных машинных языков разных типов процессоров собственный код также отличается.
История возможностей операционной системы
操作系统По сути, это тоже своего рода программное обеспечение, появление любой новой вещи должно иметь свою историческую подоплеку, поэтому операционная система не появилась из воздуха, она должна иметь свою историческую подоплеку.
Во времена, когда на компьютере не было операционной системы, вообще не было программ, и люди проходили различные按钮Для управления компьютером этот процесс очень хлопотный. В результате кто-то разработал только функцию загрузки и запуска监控程序, которая является прототипом операционной системы. Запустив программу мониторинга заранее, программист может загрузить в память различные программы для запуска по мере необходимости. Хотя это все еще громоздко, рабочая нагрузка значительно уменьшилась по сравнению с разработкой без каких-либо программ.
С развитием времени люди обнаружили, что многие программы имеют общие части в процессе написания программ с использованием программ мониторинга. Например, ввод текста через клавиатуру, отображение данных на дисплее и т. д. Пустая трата времени, если требуется одна и та же обработка каждый раз при написании нового приложения. Поэтому в программу мониторинга добавляется программа основной части ввода и вывода. Так родились первые операционные системы.
Подобными идеями можно делиться, и люди обнаруживают, что в программу мониторинга можно добавить больше приложений, таких как硬件控制程序,编程语言处理器(汇编、编译、解析)А также различные приложения и т. д., в результате получается операционная система, которая мало чем отличается от текущей, то есть операционная система фактически представляет собой набор из нескольких программ.
Особенности операционных систем Windows
Операционная система Windows является самой большой группой пользователей в мире.资深Пользователь, вы знаете особенности операционной системы Windows? Ниже перечислены некоторые функции операционной системы Windows.
- Существует две версии операционной системы Windows: 32-разрядная и 64-разрядная.
- пройти через
APIИнтеграция функций для обеспечения системных вызовов - Предоставляет пользовательский интерфейс с графическим интерфейсом пользователя
- пройти через
WYSIWYGДля достижения вывода на печать WYSIWYG на самом деле означает «что видишь, то и получишь». - Обеспечивает функцию многозадачности, то есть может открывать несколько задач одновременно
- Обеспечивает сетевые функции и функции базы данных
- Самоконфигурация на основе устройства с помощью plug-and-play
Это некоторые функции, которые более важны для программистов.Следующие функции представлены отдельно.
32-битная операционная система
Представленная здесь 32-битная операционная система представляет собойСамый эффективный размер данных. Базовая единица, с помощью которой Windows обрабатывает данные, составляет 32 бита. Это началоMS-DOS16-разрядная операционная система отличается тем, что для обработки 32-разрядных данных в 16-разрядной операционной системе требуется два раза, а 32-разрядная операционная система должна иметь возможность обрабатывать 32-разрядные данные только один раз. данные все 32-битные.
Например, когда целочисленные данные обрабатываются на языке C, остается 8 бит.charтип, 16-битныйshortтип и 32-битныйlongТипа три варианта, если для обработки используется длинный тип с большим количеством цифр, увеличение идет только накладные расходы памяти и диска, что мало влияет на производительность.
Большинство операционных систем, представленных сегодня на рынке, являются 64-разрядными операционными системами, и то же самое относится и к 64-разрядным операционным системам.
Обеспечивает системные вызовы через набор функций API
винда называетсяAPIнабор функций для обеспечения системных вызовов. API — это интерфейс между приложением и операционной системой, полное название называетсяApplication Programming Interface, интерфейс прикладной программы.
Текущая основная 32-разрядная версия Windows API также известна какWin32 API, названный так потому, что его нужно отличать от разных операционных систем, таких как исходная 16-разрядная версия.Win16 API, а позднее популярныйWin64 API.
API предоставляется через несколько файлов DLL, а объекты каждого API представляют собой функции, написанные на языке C. Поэтому в среде языка C проще использовать API, например используемый APIMessageBox()Функция сохраняется в DLL-файле user32.dll, предоставленном Windows.
Предоставляет пользовательский интерфейс с графическим интерфейсом
GUI(Graphical User Interface)Это относится к графическому пользовательскому интерфейсу, который представляет собой визуальный пользовательский интерфейс, щелкая окна и значки на дисплее.Например, существует две версии операционной системы Linux, одна из которых является простой версией, которая управляет оборудованием напрямую через командная строка, а другая — это визуальная версия, которая управляет оборудованием, щелкая курсором по графическому интерфейсу.
Распечатка через WYSIWYG
WYSIWYG означает, что то, что выводится на монитор, может быть распечатано непосредственно через принтер. В Windows мониторы и принтеры рассматриваются как эквивалентные устройства вывода графики, и эта функция также обеспечивает условия для WYSIWYG.
С помощью функций WYSIWYG программисты могут значительно упростить работу. Изначально для отображения на мониторе и печати на принтере необходимо писать свои программы, но в Windows можно в основном использовать WYSIWYG для выполнения функций отображения и печати в одной программе.
Обеспечивает многозадачность
Многозадачность означает возможность одновременного запуска нескольких приложений, Windows时钟分割технологии для достижения многозадачности. Разделение часов относится к тому, как несколько программ переключаются на запуск через короткие промежутки времени. С точки зрения пользователя кажется, что несколько программ запущены одновременно, а нижний слойCPU 时间切片, который также является ядром многопоточности и многозадачности.
Обеспечивает сетевые функции и функции базы данных
В Windows сетевые функции входят в стандартную комплектацию. Также иногда добавляется функция базы данных (сервера базы данных). Хотя сетевые функции и функции базы данных не являются обязательными для операционной системы, они упоминаются вместе, потому что они очень близки к операционной системе.中间件а не приложение. Это означает, что он находится на среднем уровне операционной системы и приложения, а операционная система и промежуточное ПО объединены вместе, что называется系统软件. Приложения могут использовать преимущества не только операционной системы, но и возможностей промежуточного программного обеспечения.
По сравнению с операционной системой, которую нельзя легко заменить после установки, промежуточное программное обеспечение можно заменить по мере необходимости.Однако для большинства приложений замена промежуточного программного обеспечения приведет к замене приложения.С этой точки зрения замена промежуточного программного обеспечения также не так проста .
Автоматическая настройка драйверов устройств с помощью plug and play
即插即用(Plug-and-Play)Это относится к механизму, который можно использовать сразу после подключения нового устройства (штекер).После того, как новое устройство подключено к компьютеру, компьютер автоматически установит и настроит устройство для управления устройством.驱动程序
Драйвер устройства — это часть операционной системы, которая обеспечивает основные функции ввода и вывода с аппаратным обеспечением. Клавиатура, мышь, монитор, дисковое устройство и т. д. Драйверы устройств для необходимого оборудования в этих компьютерах обычно устанавливаются вместе с операционной системой.
Иногда файлы DLL также устанавливаются вместе с файлами драйверов устройств. В этих DLL-файлах хранятся API-интерфейсы для использования недавно добавленного оборудования, и с помощью API-интерфейсов можно создать приложение, которое запускает аппаратное обеспечение.
Язык ассемблера и собственный код
Как мы обсуждали в предыдущих статьях, ЦП компьютера может запускать только программы с собственным кодом (машинным языком).Код, написанный на языках высокого уровня, таких как язык C, должен быть скомпилирован компилятором и преобразован в собственный код, прежде чем его можно будет интерпретируется и исполняется процессором.
Однако удобочитаемость местного кода очень плохая, поэтому необходимо заменить местный код на язык, который может быть прочитан напрямую, то есть в каждый местный код добавлена английская аббревиатура, указывающая на его функцию, например локальный код операции сложения.плюсadd(addition)сокращение от , добавление в нативный код оператора сравненияcmp(compare)Аббревиатуры и т.п., эти знаки для обозначения конкретных нативных инструкций кода посредством аббревиатур называются助记符, язык, использующий мнемонику, называется汇编语言. Таким образом, читая язык ассемблера, вы также можете понять значение нативного кода.
Однако даже исходный код, написанный на языке ассемблера, в конечном итоге должен быть преобразован в собственный код для запуска, и программа, отвечающая за это, называется编译器, этот процесс преобразования называется汇编. Ассемблер и компиляторы идентичны в своей способности преобразовывать исходный код в собственный код.
Существует однозначное соответствие между исходным кодом и собственным кодом, написанным на языке ассемблера. Таким образом, собственный код также может быть преобразован обратно в код, написанный на языке ассемблера. Процесс преобразования собственного кода в ассемблерный код называется反汇编, программа, выполняющая дизассемблирование, называется反汇编程序.
Даже исходный код, написанный на языке C, после компиляции будет преобразован в собственный код для конкретного процессора. Разобрав его, можно получить исходный код языка ассемблера и исследовать его содержимое. но,Декомпиляция нативного кода в исходный код на языке C сложнее, чем дизассемблирование нативного кода в ассемблерный код., это связано с тем, что между кодом языка C и собственным кодом нет однозначного соответствия.
Вывод исходного кода на ассемблере через компилятор
Выше мы упоминали, что нативный код можно преобразовать в ассемблерный код путем дизассемблирования, но существует ли только один способ преобразования? Очевидно, что нет, исходный код, написанный на языке C, также может быть скомпилирован компилятором, называемым ассемблерным кодом, давайте попробуем.
Прежде всего, вам нужно сделать некоторые приготовления, вам нужно сначала скачатьBorland C++ 5.5Компилятор для удобства я скачал здесь и ридер может извлечь его прямо с моего сетевого диска Baidu (ссылка:Disk.Baidu.com/Yes/19l нечетный Vic PN…Пароль: hz1u)
После того, как загрузка завершена, ее необходимо настроить.Ниже приведены инструкции по настройке (Wenku.Baidu.com/view/22 О, 2 отправить 4…
Сначала напишите следующий код в текстовом редакторе, таком как Блокнот Windows.
// 返回两个参数值之和的函数
int AddNum(int a,int b){
return a + b;
}
// 调用 AddNum 函数的函数
void MyFunc(){
int c;
c = AddNum(123,456);
}
После записи сохраните его имя файла как Sample4.c , расширение исходного файла языка C, обычно с.cчтобы указать, что приведенная выше программа должна предоставлять два входных параметра и возвращать их сумму.
Открыть под ОС Windows命令提示符, перейдите в папку, в которой сохранен Sample4.c, и введите в командной строке
bcc32 -c -S Sample4.c
bcc32 — это команда для запуска Borland C++,-cОпция относится к простой компиляции без компоновки,-Sопция используется для указания исходного кода для создания языка ассемблера
В результате компиляции появился файл с именемSample4.asmисходный код на языке ассемблера. Расширение для исходных файлов на ассемблере, обычно с.asmДля представления откроем его в редакторе и посмотрим на содержимое Sample4.asm.
.386p
ifdef ??version
if ??version GT 500H
.mmx
endif
endif
model flat
ifndef ??version
?debug macro
endm
endif
?debug S "Sample4.c"
?debug T "Sample4.c"
_TEXT segment dword public use32 'CODE'
_TEXT ends
_DATA segment dword public use32 'DATA'
_DATA ends
_BSS segment dword public use32 'BSS'
_BSS ends
DGROUP group _BSS,_DATA
_TEXT segment dword public use32 'CODE'
_AddNum proc near
?live1@0:
;
; int AddNum(int a,int b){
;
push ebp
mov ebp,esp
;
;
; return a + b;
;
@1:
mov eax,dword ptr [ebp+8]
add eax,dword ptr [ebp+12]
;
; }
;
@3:
@2:
pop ebp
ret
_AddNum endp
_MyFunc proc near
?live1@48:
;
; void MyFunc(){
;
push ebp
mov ebp,esp
;
; int c;
; c = AddNum(123,456);
;
@4:
push 456
push 123
call _AddNum
add esp,8
;
; }
;
@5:
pop ebp
ret
_MyFunc endp
_TEXT ends
public _AddNum
public _MyFunc
?debug D "Sample4.c" 20343 45835
end
Таким образом, компилятор успешно преобразует язык C в ассемблерный код.
Директивы, которые не транслируются в собственный код
Читатели, которые впервые видят ассемблерный код, могут столкнуться с трудностями, но на самом деле он относительно прост и может быть проще, чем язык C. Чтобы облегчить чтение исходного кода ассемблерного кода, есть несколько моментов, на которые следует обратить внимание.
Исходный код языка ассемблера состоит из инструкций, преобразованных в собственный код (опкоды, описанные ниже) и псевдоинструкций для ассемблера. Директивы отвечают за указание ассемблеру (программе преобразования) построения программы и метода сборки. Однако псевдоинструкции нельзя собрать в собственный код. Ниже приведена псевдоинструкция, перехваченная вышеуказанной программой.
_TEXT segment dword public use32 'CODE'
_TEXT ends
_DATA segment dword public use32 'DATA'
_DATA ends
_BSS segment dword public use32 'BSS'
_BSS ends
DGROUP group _BSS,_DATA
_AddNum proc near
_AddNum endp
_MyFunc proc near
_MyFunc endp
_TEXT ends
end
по псевдоинструкцииsegmentиendsВложенная часть получается путем добавления имени к набору команд и данных, составляющих программу, называемых段定义. Английское выражение определения сегмента имеет区域В этой программе определение сегмента относится к совокупности программ, таких как команды и данные, а программа состоит из нескольких определений сегментов.
Начальная позиция приведенного выше кода определяет 3 имени как_TEXT、_DATA、_BSSОпределение сегмента ,_TEXTзаданное определение сегмента,_DATAэто определение сегмента инициализируемых данных (с начальным значением),_BSS— это определение сегмента для данных, которые еще не были инициализированы. Имена таких определений определяются Borland C++ и автоматически назначаются компилятором Borland C++, поэтому порядок определений сегментов становится_TEXT、_DATA、_BSS, что также обеспечивает непрерывность памяти
_TEXT segment dword public use32 'CODE'
_TEXT ends
_DATA segment dword public use32 'DATA'
_DATA ends
_BSS segment dword public use32 'BSS'
_BSS ends
Определение сегмента ( сегмент ) используется для различения или разделения значения области диапазона. Директива segment на языке ассемблера указывает начало определения сегмента, а директива ends указывает конец определения сегмента. Определение сегмента представляет собой непрерывное пространство памяти.
иgroupЭта псевдоинструкция означает, что_BSS和_DATAЭти два сегмента определяют группу с именем DGROUP.
DGROUP group _BSS,_DATA
окруженный_AddNumи_MyFunиз_TEXTсегмент и_TEXTзаканчивается, указывая_AddNumи_MyFunпринадлежит_TEXTопределено в настоящем пункте.
_TEXT segment dword public use32 'CODE'
_TEXT ends
Поэтому, даже если в исходном коде смешаны инструкции и данные, после компиляции и сборки они будут преобразованы в обычный нативный код.
_AddNum procи_AddNum endpогороженная часть и_MyFunc procи_MyFunc endpЗаключенные части представляют собой диапазоны функций AddNum и MyFunc соответственно.
_AddNum proc near
_AddNum endp
_MyFunc proc near
_MyFunc endp
После компиляции добавьте подчеркивание перед именем функции_, является спецификацией Borland C++. Функция AddNum, написанная на языке C, имеет внутреннее имя _AddNum. Часть, заключенная в псевдоинструкции proc и endp, указывает, что过程(procedure)диапазон. На языке ассемблера эта форма эквивалента функции на языке C называется процедурой.
в концеendПсевдоинструкция, указывающая конец исходного кода.
Синтаксис языка ассемблера: код операции + операнд.
На ассемблере строка представляет одну инструкцию для пары процессоров. Синтаксическая структура инструкций языка ассемблера такова.код операции + операнд, есть также инструкции только с кодами операций и без операндов.
Код операции представляет действие инструкции, а операнд представляет объект инструкции. Код операции и операнд, используемые вместе, представляют собой инструкцию на английском языке. Например, из анализа английской грамматики код операции — это глагол, а операнд — объект. например, это предложениеGive me moneyВ этой инструкции на английском языке Give — это код операции, а me и money — операнды. Если имеется несколько операндов на ассемблере, разделяйте их запятыми, например Дайте мне деньги.
Какие формы кодов операций можно использовать, зависит от типа процессора.Функции кодов операций перечислены ниже.
Нативный код необходимо загрузить в память, прежде чем он сможет работать, а память хранит инструкции и данные, составляющие нативный код. Когда программа работает, ЦП считывает данные и инструкции из памяти, а затем помещает их в регистры внутри ЦП для обработки.
Если вы не знакомы с взаимосвязью процессора и памяти, прочтите другую статью автора.Процессор основных знаний, которые должны знать программистыВыучить больше.
Регистры - это области хранения в ЦП.Помимо функций временного хранения и вычислений регистры имеют еще и вычислительные функции.Основные типы и роли серии x86 показаны на рисунке ниже.
Разбор инструкций
Ниже приводится анализ инструкций в ЦП.
Наиболее часто используемые команды перемещения
Чаще всего используются инструкции для хранения данных в регистрах и памяти.movИнструкция, два операнда инструкции mov, используются для указания места хранения и источника считывания данных соответственно. Операнды могут указывать регистры, константы, метки (предваряемые адресами) и использовать квадратные скобки.([])эти прилагаются. Бесполезно, если указано([])Содержимое, заключенное в квадратные скобки, означает, что значение обрабатывается; если указано содержимое, заключенное в квадратные скобки, значение в квадратных скобках будет интерпретировано как адрес памяти, а затем будет прочитано значение, соответствующее адресу памяти. операция записи. Давайте проиллюстрируем фрагмент кода выше
mov ebp,esp
mov eax,dword ptr [ebp+8]
В mov ebp,esp значение регистра esp хранится непосредственно в ebp, то есть если значение регистра esp равно 100, то значение регистра ebp также равно 100.
пока вmov eax,dword ptr [ebp+8]В этой инструкции значение регистра ebp + 8 будет разрешено и названо адресом памяти. если ebp
Если значение регистра равно 100, то значением регистра eax является значение адреса 100 + 8.dword ptrтакже называемыйdouble word pointerПростое объяснение — прочитать 4 байта данных из указанного адреса памяти.
толкать и выталкивать стек
Когда программа запускается, она выделяет в памяти пространство данных, называемое стеком. Характеристика стека «последний вошел первым вышел», когда данные сохраняются, они постепенно накапливаются от нижнего уровня (большой номер адреса) к верхнему слою (маленький номер адреса), а при чтении они считываются сверху вниз. , взято.
Стек — это область для хранения временных данных, которая характеризуется хранением и чтением данных с помощью инструкций push и pop. Хранение данных в стеке называется入栈, чтение данных из стека называется出栈, 32-разрядные (4-байтовые) данные могут быть обработаны в 32-разрядном ЦП серии x86 одним нажатием или нажатием.
механизм вызова функций
Давайте вместе разберем механизм вызова функции на примере кода, написанного на языке C выше. Во-первых, давайте начнем сMyFuncвызов функцииAddNumАссемблерная часть функции начинает объяснять механизм вызова функции. Стек играет огромную роль в вызове функции.Ниже приведено содержимое обработки сборки обработанной функции MyFunc.
_MyFunc proc near
push ebp ; 将 ebp 寄存器的值存入栈中 (1)
mov ebp,esp ; 将 esp 寄存器的值存入 ebp 寄存器中 (2)
push 456 ; 将 456 入栈 (3)
push 123 ; 将 123 入栈 (4)
call _AddNum ; 调用 AddNum 函数 (5)
add esp,8 ; esp 寄存器的值 + 8 (6)
pop ebp ; 读出栈中的数值存入 esp 寄存器中 (7)
ret ; 结束 MyFunc 函数,返回到调用源 (8)
_MyFunc endp
Обработка (1), (2), (7) и (8) в объяснении кода применяется ко всем функциям на языке C, которые мы покажем позже.AddNumОбъясните, когда функция обрабатывает содержимое. Здесь, я надеюсь, вы сначала обратите внимание на (3) - (6), что очень важно для понимания механизма вызова функции.
(3) и (4) указывают, что параметры, переданные функции AddNum, помещаются в стек. В исходном коде языка C, хотя она и описывается как функция AddNum(123, 456), при помещении ее в стек она будет иметь порядок 456, 123. То есть значение в конце помещается в стек первым. Это правило языка C. Инструкция вызова, обозначенная (5), перейдет в потоке программы к адресу функциональной инструкции AddNum. На языке ассемблера函数名Представляет адрес памяти, где находится функция. После обработки функции AddNum поток программы должен вернуться к строке с номером (6). После выполнения инструкции call адрес памяти следующей строки инструкции call (то есть строки (6)) (адрес памяти, который должен быть возвращен после завершения вызывающей функции) будет автоматически помещен в стек. Это значение будет передано в конце обработки функции AddNum.retКоманда pop выталкивает стек, и программа возвращается к строке (6).
Часть (6) уничтожит два параметра (456 и 123), хранящиеся в стеке. Хотя это также может быть достигнуто двумя инструкциями pop, более эффективно использовать метод esp register + 8 (только 1 раз). При вводе и выводе значения в стек единицей измерения является 4 байта. Поэтому, добавив 2 раза по 8 из 4 в регистр esp, отвечающий за управление адресами стека, можно добиться того же эффекта, что и дважды запустить команду pop. Хотя данные в памяти фактически остаются, до тех пор, пока значение регистра esp обновляется до местоположения данных перед адресом хранения данных, данные эквивалентны уничтожению.
я компилируюSample4.cфайла появляется следующее сообщение
Смысл на рисунке означает, что значение c определено в MyFunc, но не использовалось. На самом деле это функция оптимизации компилятора. Поскольку переменная c, в которой хранится возвращаемое значение функции AddNum, в дальнейшем не используется, компилятор просто думайпеременная не имеет значения, а значит иСоответствующий код на ассемблере не генерируется.
На следующем рисунке показано изменение стековой памяти до и после вызова функции AddNum.
Внутренняя обработка функций
Выше мы использовали ассемблерный код для анализа кода всего процесса Sample4.c Теперь сосредоточимся на анализе исходной части кода функции AddNum, а также на анализе механизма получения параметра, возвращаемого значения и возврата.
_AddNum proc near
push ebp -----------(1)
mov ebp,esp -----------(2)
mov eax,dword ptr[ebp+8] -----------(3)
add eax,dword ptr[ebp+12] -----------(4)
pop ebp -----------(5)
ret ----------------------------------(6)
_AddNum endp
Значение регистра ebp помещается в стек в (1) и извлекается из стека в (5), в основном для восстановления содержимого регистра ebp, используемого в функции, до состояния перед вызовом функции.
В (2) значение регистра esp, отвечающего за управление адресом стека, присваивается регистру ebp. Это связано с тем, что параметры в квадратных скобках в инструкции mov не могут указывать регистр esp. Поэтому здесь принят метод чтения и записи содержимого стека с использованием регистра ebp, а не напрямую через esp.
(3) Используйте [ebp + 8], чтобы указать первый параметр 123, сохраненный в стеке, и считать его в регистр eax. Таким образом, на содержимое стека можно ссылаться без использования инструкции pop. Причина, по которой регистр eax выбирается из нескольких регистров, заключается в том, что eax является регистром накопления, ответственным за операцию.
С помощью инструкции добавления (4) результат добавления текущего значения регистра eax ко второму параметру сохраняется в регистре eax. [ebp + 12] используется для указания второго параметра 456. В языке C возвращаемое значение функции должно возвращаться через регистр eax, что также оговаривается. этоПараметры функции передаются через стек, а возвращаемое значение возвращается через регистр.
(6) После выполнения инструкции ret функция возвращается к адресу памяти назначения.自动出栈, в соответствии с которым поток программы вернется к(6) (Call _AddNum)следующая строка. В это время состояние стека на входе и выходе из функции AddNum изменяется, как показано на следующем рисунке.
Глобальные и локальные переменные
После знакомства с языком ассемблера давайте взглянем на глобальные переменные и локальные переменные.Переменные, определенные вне функции, называются全局变量, переменная, определенная внутри функции, называется局部变量, глобальные переменные могут использоваться в любой функции, локальные переменные могут использоваться только внутри локальных переменных определения функции. Далее, давайте посмотрим на разницу между глобальными переменными и локальными переменными через язык ассемблера.
Определенный ниже код языка C определяет локальные переменные и глобальные переменные соответственно и присваивает значения каждой переменной.Давайте сначала посмотрим на часть исходного кода.
// 定义被初始化的全局变量
int a1 = 1;
int a2 = 2;
int a3 = 3;
int a4 = 4;
int a5 = 5;
// 定义没有初始化的全局变量
int b1,b2,b3,b4,b5;
// 定义函数
void MyFunc(){
// 定义局部变量
int c1,c2,c3,c4,c5,c6,c7,c8,c9,c10;
// 给局部变量赋值
c1 = 1;
c2 = 2;
c3 = 3;
c4 = 4;
c5 = 5;
c6 = 6;
c7 = 7;
c8 = 8;
c9 = 9;
c10 = 10;
// 把局部变量赋值给全局变量
a1 = c1;
a2 = c2;
a3 = c3;
a4 = c4;
a5 = c5;
b1 = c6;
b2 = c7;
b3 = c8;
b4 = c9;
b5 = c10;
}
Приведенный выше код довольно жесток, но это не беда, нам полезно проанализировать его исходный код сборки. Код сборки, который мы скомпилировали с помощью Borland C++, выглядит следующим образом. Изменен порядок определения абзацев и удалены некоторые комментарии)
_DATA segment dword public use32 'DATA'
align 4
_a1 label dword
dd 1
align 4
_a2 label dword
dd 2
align 4
_a3 label dword
dd 3
align 4
_a4 label dword
dd 4
align 4
_a5 label dword
dd 5
_DATA ends
_BSS segment dword public use32 'BSS'
align 4
_b1 label dword
db 4 dup(?)
align 4
_b2 label dword
db 4 dup(?)
align 4
_b3 label dword
db 4 dup(?)
align 4
_b4 label dword
db 4 dup(?)
align 4
_b5 label dword
db 4 dup(?)
_BSS ends
_TEXT segment dword public use32 'CODE'
_MyFunc proc near
push ebp
mov ebp,esp
add esp,-20
push ebx
push esi
mov eax,1
mov edx,2
mov ecx,3
mov ebx,4
mov esi,5
mov dword ptr [ebp-4],6
mov dword ptr [ebp-8],7
mov dword ptr [ebp-12],8
mov dword ptr [ebp-16],9
mov dword ptr [ebp-20],10
mov dword ptr [_a1],eax
mov dword ptr [_a2],edx
mov dword ptr [_a3],ecx
mov dword ptr [_a4],ebx
mov dword ptr [_a5],esi
mov eax,dword ptr [ebp-4]
mov dword ptr [_b1],eax
mov edx,dword ptr [ebp-8]
mov dword ptr [_b2],edx
mov ecx,dword ptr [ebp-12]
mov dword ptr [_b3],ecx
mov eax,dword ptr [ebp-16]
mov dword ptr [_b4],eax
mov edx,dword ptr [ebp-20]
mov dword ptr [_b5],edx
pop esi
pop ebx
mov esp,ebp
pop ebp
ret
_MyFunc endp
_TEXT ends
Скомпилированные программы сгруппированы в группы, называемые определениями сегментов.
- Инициализированные глобальные переменные объединяются в определение раздела с именем _DATA.
_DATA segment dword public use32 'DATA'
...
_DATA ends
- Неинициализированные глобальные переменные объединяются в определение раздела с именем _BSS.
_BSS segment dword public use32 'BSS'
...
_BSS ends
- Ассемблерный код, заключенный в определении секции _TEXT, является определением Borland C++.
_TEXT segment dword public use32 'CODE'
_MyFunc proc near
...
_MyFunc endp
_TEXT ends
Прежде чем мы проанализируем приведенный выше ассемблерный код, давайте познакомимся с дополнительными инструкциями по сборке.Эта таблица предназначена для вышеуказанногоНекоторые коды операций и их функциипродолжение
| Опкод | операнд | Функции |
|---|---|---|
| add | A,B | Сложите значения A и B и присвойте результат A |
| call | A | функция вызова А |
| cmp | A,B | Сравните A и B, результат сравнения будет автоматически сохранен в регистре флагов. |
| inc | A | + 1 к значению А |
| ige | название ярлыка | Используется в сочетании с командой cmp. Перейти к строке метки |
| jl | название ярлыка | Используется в сочетании с командой cmp. Перейти к строке метки |
| jle | название ярлыка | Используется в сочетании с командой cmp. Перейти к строке метки |
| jmp | название ярлыка | Используется в сочетании с командой cmp. Перейти к строке метки |
| mov | A,B | присвоить значение B значению A |
| pop | A | Прочитать значение из стека и сохранить в A |
| push | A | положить значение A в стек |
| ret | никто | Обработка возврата вызывающему источнику |
| xor | A,B | ИЛИ сравните биты A и B и сохраните результат в A |
Давайте сначала посмотрим на_DATAСодержимое определения сегмента._a1 label dwordОпределенный_a1этот ярлык. Метка представляет положение относительно начала определения сегмента. так как_a1существует_DATA 段Начальная позиция определения, поэтому относительная позиция равна 0._a1Это эквивалентно глобальной переменной a1. Скомпилированному имени функции и имени переменной будет предшествовать(_), что также является требованием Borland C++.dd 1Это означает, что приложение выделяет 4 байта памяти и сохраняет начальное значение 1. дд относится кdefine double wordУказывает, что есть два байтовых поля (слова) длиной 2, что означает 4 байта.
В Borland C++, начиная сintДлина типа 4 байта, поэтому ассемблер превращает int a1 = 1 в_a1 label dword 和 dd 1. Точно так же здесь определяются метки a2 - a5, эквивалентные глобальным переменным._a2 - _a5, их соответствующие начальные значения 2 - 5 также хранятся в соответствующих 4 байтах.
Далее поговорим о_BSSСодержимое определения сегмента. Это определяет метки, эквивалентные глобальным переменным b1 - b5._b1 - _b5. один из нихdb 4dup(?)Указывает, что приложение выделило 4-байтовое поле, но значение еще не определено (представлено здесь знаком ?).db(define byte)Указывает, что имеется пространство памяти длиной 1 байт. Следовательно, в случае db 4 dup(?) это 4 байта памяти.
Примечание: db 4 dup(?) не следует путать с dd 4, первый представляет 4 области памяти длиной 1 байт. А db 4 означает, что значение, хранящееся в пространстве памяти двойных байтов (= 4 байта), равно 4
Временно обеспечьте пространство памяти, используемое локальными переменными
Мы знаем, что локальные переменные временно хранятся в регистрах и стеках. Функция внутренне использует стек для хранения локальных переменных, после завершения вызова функции значения локальных переменных уничтожаются, но регистры могут использоваться для других целей. так,Локальные переменные просто временно сохраняются в регистрах и стекаются функцией во время обработки..
Помните, что приведенный выше код не определяет 10 локальных переменных? Это указывает на то, что локальные переменные хранятся не только в стеке, но и в регистрах. Чтобы обеспечить поля, требуемые c1 - c10, регистры используются, когда регистры свободны, а стек используется, когда недостаточно места в регистрах.
Продолжим анализировать содержимое приведенного выше кода._TEXTОпределение сегмента означает, чтоMyFuncобъем функции. Область памяти, требуемая локальными переменными, определенная в функции MyFunc. будет размещено в регистрах как можно больше. Вы можете подумать, что использование высокопроизводительных регистров вместо обычной памяти — пустая трата ресурсов, но компиляторы так не считают, пока есть место для регистра, компилятор будет его использовать. Поскольку скорость доступа к регистрам намного выше, чем к памяти, прямой доступ к регистрам может осуществляться эффективно. Локальные переменные используют регистры и оптимизируются компилятором Borland C++.
Следующее в листинге кода представляет часть, которая размещает локальные переменные в регистрах.
mov eax,1
mov edx,2
mov ecx,3
mov ebx,4
mov esi,5
Недостаточно определить локальную переменную, только когда локальной переменной будет присвоено значение, оно будет размещено в области памяти регистра. Приведенный выше код эквивалентен присвоению значений 1 — 5 пяти локальным переменным c1 — c5 соответственно.eax, edx, ecx, ebx, esiэто название семейства 32-битных регистров процессора x86. Что касается того, какой регистр использовать, это определяется编译器принимать решение.
Среди регистров, принадлежащих ЦП серии x86, программа может оперировать более десятка, а свободных — максимум несколько. Поэтому, когда количество локальных переменных превышает количество регистров, регистров для выделения недостаточно, и в этом случае компилятор будет использовать стек для хранения оставшихся локальных переменных.
В этой части кода выше, после выделения регистров локальным переменным c1 - c5, количество доступных регистров недостаточно. Таким образом, оставшиеся 5 локальных переменных c6 - c10 размещаются в пространстве памяти стека. как показано в коде ниже
mov dword ptr [ebp-4],6
mov dword ptr [ebp-8],7
mov dword ptr [ebp-12],8
mov dword ptr [ebp-16],9
mov dword ptr [ebp-20],10
запись функцииadd esp,-20Это означает вычесть 20 из значения регистра esp (указателя стека) в месте хранения данных стека. Для того, чтобы переменные памяти c6 - c10 находились в стеке, необходимо зарезервировать место, необходимое для 5 локальных переменных типа int (4 байта * 5 = 20 байт).mov ebp,espЭта строка инструкции означает присвоение значения регистра esp регистру ebp. Причина, по которой это необходимо сделать, заключается в том, чтобы передать на выходе функцииmov esp ebpЭтот процесс восстанавливает значение регистра esp в исходное состояние, тем самым освобождая выделенное пространство стека, а локальные переменные, используемые в стеке, исчезают. Это также очистка стека. В случае использования регистров локальные переменные автоматически исчезнут, когда регистры будут использоваться для других целей, как показано на следующем рисунке.
mov dword ptr [ebp-4],6
mov dword ptr [ebp-8],7
mov dword ptr [ebp-12],8
mov dword ptr [ebp-16],9
mov dword ptr [ebp-20],10
Эти пять строк кода являются частью подстановки значений в пространство стека, потому что перед обращением за пространством памяти из стекаmov ebp, espВ этом процессе значение регистра esp сохраняется в регистре esp, поэтому, используя форму [ebp - 4], [ebp - 8], [ebp - 12], [ebp - 16], [ebp - 20 ] , вы можете применить, чтобы выделить 20 байт пространства памяти стека и разделить его на 5 пространств с длиной 4 байта для использования. Например,mov dword ptr [ebp-4],6Это означает, что, начиная с нижнего конца выделенного пространства памяти (позиция, указанная регистром ebp), 4-байтовые данные 6 сохраняются по адресу ([ebp - 4]) вперед на 4 байта.
Обработка операторов управления циклом
Все вышеперечисленное является последовательными процессами, поэтому теперь давайте проанализируем обработку циклического процесса и посмотримfor 循环а такжеif 条件分支и т.д. Программа на языке C流程控制Как этого добиться, давайте в качестве примера возьмем код и скомпилированный результат, чтобы увидеть процесс обработки потока управления программой.
// 定义MySub 函数
void MySub(){
// 不做任何处理
}
// 定义MyFunc 函数
void Myfunc(){
int i;
for(int i = 0;i < 10;i++){
// 重复调用MySub十次
MySub();
}
}
Приведенный выше код использует локальную переменную i в качестве условия цикла, и цикл вызывается десять раз.MySubфункция, ниже приведен ее основной ассемблерный код
xor ebx, ebx ; 将寄存器清0
@4 call _MySub ; 调用MySub函数
inc ebx ; ebx寄存器的值 + 1
cmp ebx,10 ; 将ebx寄存器的值和10进行比较
jl short @4 ; 如果小于10就跳转到 @4
Оператор for на языке C выполняет обработку цикла, указывая начальное значение счетчика цикла (i = 0), условие продолжения цикла (i 比较指令(cmp)и跳转指令(jl)быть реализованным.
Давайте объясним приведенный выше код
MyFuncЕдинственная локальная переменная, используемая в функции, — это i, и переменная i применяется для выделения пространства памяти регистра ebx. i = 0 в скобках оператора for преобразуется вxor ebx,ebxВ этом процессе инструкция xor выполняет операцию XOR над первым операндом слева и вторым операндом справа и сохраняет результат в первом операнде. Поскольку и первый операнд, и второй операнд обозначены как ebx, это становится операцией XOR над одним и тем же значением. То есть независимо от текущего значения регистра конечный результат равен 0. Точно так же мы используемmov ebx,0Получается тот же результат, но инструкция xor обрабатывается быстрее и компилятор включает оптимизации.
XOR относится к операции исключающее или, и ее правила операцииЕсли два значения a и b не совпадают, результат XOR равен 1. Если значения a и b совпадают, результат XOR равен 0.
Это же значение подвергается операции XOR, и результат равен 0. Правило операции XOR заключается в том, что результат равен 1, если значения разные, и результат равен 0, если значения совпадают. Например, если оперировать 01010101 и 01010101, операция XOR будет выполняться соответственно для каждого цифрового бита. Поскольку все цифры одинаковы, результатом операции будет 0.
После того, как значение регистра ebx будет инициализировано, функция _MySub будет вызвана вызовом, а после возврата из функции _MySub будет выполненаinc ebxИнструкция, выполнить операцию +1 над значением ebx, эта операция эквивалентна значению i++, ++ означает текущее значение +1.
Здесь вам нужно знать разницу между i++ и ++i
i++ — это первое присваивание, а затем операция + 1 выполняется над i после завершения копирования
++i - сначала выполнить операцию +1, а затем присвоить ее после завершения
incследующая строкаcmpэто инструкция, используемая для сравнения значений первого операнда и второго операнда.cmp ebx,10Это эквивалентно обработке i
На ассемблере их несколько跳转指令, эти инструкции перехода будут решать, нужно ли переходить, в соответствии со значением флагового регистра, такого как jl в последней строке, он будет решать, следует ли переходить, в соответствии со значением, хранящимся в флаговом регистре инструкции cmp ebx,10,jlЭта команда означаетjump on less than(小于的话就跳转). Обнаружено, что если i меньше 10, он перейдет к инструкции, где находится @4, чтобы продолжить выполнение.
Затем смысл ассемблерного кода также можно переписать на языке C, чтобы углубить понимание.
i ^= i;
L4: MySub();
i++;
if(i < 10) goto L4;
Первая строка кода i ^= i относится к операции XOR между i и i, то есть к операции XOR.Функция MySub() заменяется меткой L4, а затем выполняется операция увеличения i. () будет продолжать цикл.
Как обрабатывать условные ветки
Условные переходы обрабатываются так же, как и циклы, с использованием инструкций cmp и инструкций перехода. Ниже приведен код условного перехода, написанный на языке C.
// 定义MySub1 函数
void MySub1(){
// 不做任何处理
}
// 定义MySub2 函数
void MySub2(){
// 不做任何处理
}
// 定义MySub3 函数
void MySub3(){
// 不做任何处理
}
// 定义MyFunc 函数
void MyFunc(){
int a = 123;
// 根据条件调用不同的函数
if(a > 100){
MySub1();
}
else if(a < 50){
MySub2();
}
else
{
MySub3();
}
}
Очень простой код на языке C, который реализует условное суждение, затем мы компилируем его с помощью Borland C++, и результат выглядит следующим образом.
_MyFunc proc near
push ebp
mov ebp,esp
mov eax,123 ; 把123存入 eax 寄存器中
cmp eax,100 ; 把 eax 寄存器的值同100进行比较
jle short @8 ; 比100小时,跳转到@8标签
call _MySub1 ; 调用MySub1函数
jmp short @11 ; 跳转到@11标签
@8:
cmp eax,50 ; 把 eax 寄存器的值同50进行比较
jge short @10 ; 比50大时,跳转到@10标签
call _MySub2 ; 调用MySub2函数
jmp short @11 ; 跳转到@11标签
@10:
call _MySub3 ; 调用MySub3函数
@11:
pop ebp
ret
_MyFunc endp
В приведенном выше коде используются три инструкции перехода, которыеjle(jump on less or equal)Сравните результат часов с прыжком,jge(jump on greater or equal)Перейти, когда результат сравнения большой, и перейти независимо от результатаjmp, перед этими инструкциями перехода есть инструкции для сравненияcmp, которые составляют основную логическую форму приведенного выше ассемблерного кода.
Необходимость понимать логику работы программы
Сравнивая приведенный выше код сборки с исходным кодом языка C, мы должны получить новое понимание того, как работает программа, и знания, полученные из исходного кода сборки, также полезны для понимания характеристик языков высокого уровня, таких как Java, например Java Существуют переменные, модифицированные ключевым словом native, поэтому нижний слой этой переменной написан на языке C, а некоторый синтаксический сахар в Java может знать логику своей работы только через ассемблерный код. В некоторых случаях также может быть полезно найти причину ошибки.
Все методы программирования, которые мы изучили выше, представляют собой последовательную обработку, так каковы же характеристики последовательной обработки?
Одной из самых больших особенностей последовательной обработки является то, что专心只做一件事情, после того как сделано одно, делается другое.
Компьютер поддерживает многопоточность, и ядром многопоточности является переключение ЦП, как показано на следующем рисунке.
Возьмем практический пример, посмотрим на кусок кода
// 定义全局变量
int counter = 100;
// 定义MyFunc1()
void MyFunc(){
counter *= 2;
}
// 定义MyFunc2()
void MyFunc2(){
counter *= 2;
}
Приведенный выше код представляет собой программу на языке C, которая обновляет значение счетчика.Содержимое обработки MyFunc1() и MyFunc2() заключается в удвоении значения счетчика, а затем присвоении значения счетчика счетчику. Здесь мы предполагаем использовать多线程处理, функции MyFunc1 и MyFunc2 вызываются одновременно, в это время значение глобальной переменной counter должно быть запрограммировано как 100 * 2 * 2 = 400. Если вы откроете несколько потоков, вы обнаружите, что значение счетчика иногда равно 200. Что касается того, почему это происходит, если вы не понимаете, как работает программа, трудно найти причину.
Код, который мы преобразуем вышеприведенный код в язык ассемблера, выглядит следующим образом.
mov eax,dword ptr[_counter] ; 将 counter 的值读入 eax 寄存器
add eax,eax ; 将 eax 寄存器的值扩大2倍。
mov dword ptr[_counter],eax ; 将 eax 寄存器的值存入 counter 中。
В многопоточной программе каждый раз, когда запускается строка кода, выраженная на языке ассемблера, обработка может переключаться на другой поток. Поэтому, если предположить, что функция MyFun1 считывает значение счетчика 100, прежде чем она успеет записать свое двойное значение 200 в счетчик, функция MyFun2 считывает значение счетчика 100, тогда результатом станет 200.
Чтобы избежать этой ошибки, мы можем использовать блок функции поведения или код языка C, чтобы запретить переключение потоков.锁定метод или используйте какой-либо потокобезопасный способ, чтобы избежать этой проблемы.
Сейчас в основном никто не использует язык ассемблера для написания программ, потому что эффективность языков высокого уровня, таких как C и Java, намного выше, чем у языка ассемблера. Тем не менее, опыт языка ассемблера по-прежнему очень важен, благодаря использованию языка ассемблера мы можем лучше понять механизм работы компьютера.
Ссылка на статью
woohoo.computer Hope.com/jargon/no/why…
baike.baidu.com/item/queue/145…
baike.baidu.com/item/stack/1280…
baike.baidu.com/item/ringbuffer/…
«Как работает программа»
baike.baidu.com/item/язык ассемблера/6…
Encyclopedia.Baidu.com/item/window…
диск
дисковый кеш
Виртуальная память
baike.baidu.com/item/алгоритм сжатия/2…
En. Wikipedia.org/wiki/cent RA…
woohoo.цифровые тренды.com/computing/i…
baike.baidu.com/item/register/18…
baike.baidu.com/item/memory/103…
blog.CSDN.net/mark_basketball/art…
baike.baidu.com/item/счетчик программ/…
Знайте. Baidu.com/question/12…