
- •Программирование эвм
- •Int 21h ;кодом возврата 0 прерывания 21h
- •Работа с битами
- •Порядок выполнения работы
- •Устройства ввода-вывода
- •Ввод исходных данных с клавиатуры и вывод результатов на дисплей
- •Inc di ;смещение в видеопамяти на следующий символ
- •Порядок выполнения работы
- •Контрольные задания
- •Система команд процессора
- •Способы адресации
- •Влияние команд на регистр флагов
- •Расширенные регистры и типы данных процессоров x86
- •Система команд процессоров ia-32 и Intel 64
- •Int 21h ;системного прерывания 21h
- •Использование дальней подпрограммы
- •X dw 0aabBh, 0abbAh, 0baaBh, 0bbaAh ;исходные данные
- •Использование подпрограмм для ввода-вывода
- •Порядок выполнения работы
- •Контрольные задания
- •Дескрипторы
- •Порядок работы процессора в защищенном режиме
- •Использование дальней подпрограммы в защищенном режиме
- •Использование idt. Ввод данных с клавиатуры в защищенном режиме
- •Порядок выполнения работы
Содержание
Введение
Один из основных признаков классификации процессоров — сложность системы команд, самих команд и время их выполнения. По этому признаку выделяется два класса: RISC- и CISC-процессоры.
RISC (Reduced (Restricted) Instruction Set Computer) — компьютер (процессор) с сокращенным набором команд. У RISC-процессоров система команд меньше, команды более простые и выполняются быстрее. Однако программа для RISC-процессоров длиннее. Примеры RISC-процессоров — Power PC компании IBM и SPARC компании Sun Microsystems.
CISC (Complex (Complete) Instruction Set Computer) — компьютер (процессор) с полным (сложным) набором команд. У CISC-процессоров система команд больше, команды более сложные и выполняются медленнее, но программа для них короче. Пример CISC-процессоров — семейство x86.
В принципе, можно было бы сделать процессор с еще более сложной системой команд, соответствующей, например, языку высокого уровня. Это было бы аппаратной реализацией языка высокого уровня. Но сейчас на практике так не делается, и языки высокого уровня "реализуются" программно, с помощью компиляторов и интерпретаторов. Более того, сложные команды CISC-процессоров отображаются на микропрограммы, состоящие из микрокоманд.
Множество современных процессоров сочетает в себе свойства RISC- и CISC-процессоров, поскольку в процессе развития микропроцессорной техники в CISC-процессорах все больше появлялось элементов RISC, а в RISC, соответственно — CISC. Иллюстрацией этого являются процессоры Intel Pentium и IBM Power PC.
Простые команды RISC-процессоров позволяют эффективно использовать для своего исполнения конвейер. Дополнительный уровень детализации команд в CISC-процессорах, микрокоманды, позволяет использовать конвейер и в этом типе процессоров. Микрооперации и конвейер — это и есть элементы RISC в CISC-процессорах.
В RISC-процессорах оптимизация исполняемого кода в основном выполняется компилятором. В CISC-процессорах с элементами RISC это сделать невозможно по причине того, что машинные команды таких процессоров далее при их выполнении распадаются на еще более мелкие функциональные единицы — микрооперации. Поэтому в них оптимизация осуществляется в основном во время исполнения программы самим процессором путем переупорядочивания микроопераций и распределения их по параллельным блокам. Несмотря на то, что эти процессоры с точки зрения программиста и с точки зрения проектировщика различаются очень сильно, это можно считать их преимуществом, поскольку программа, скомпилированная для конкретной модели процессора, будет эффективно выполняться и на других моделях. Поэтому и в RISC-процессорах появляются оптимизирующие элементы.
Второй важный признак классификации процессоров и компьютеров — реализация памяти команд и данных в конструктивно отдельных запоминающих устройствах или в одном совмещенном. По этому признаку также выделяется два класса компьютеров: Гарвардской и Принстонской архитектуры.
Гарвардская архитектура характеризуется раздельной памятью команд и данных. Она была реализована в Гарвардском университете в компьютере Mark I.
Основным признаком Принстонской архитектуры является объединенная (смешанная) память команд и данных (что предоставляет широкие возможности по модификации команд). Она ассоциируется с архитектурой фон Неймана, который был профессором математики в Принстонском Институте сложных (специальных) исследований.
Многие современные процессоры сочетают также и эти типы архитектур. Например, процессоры x86 используют смешанные основную память и кэш второго уровня, но раздельный кэш первого уровня.
Еще один признак классификации процессоров — отражение в системе команд внутреннего параллелизма процессора. По этому признаку выделяются суперскалярные процессоры (со скрытым (implicit) параллелизмом) и EPIC-процессоры (с явным (explicit) параллелизмом).
Суперскалярный процессор содержит не менее двух конвейеров. Конвейеры работают параллельно. Распараллеливание (распределение команд по конвейерам) происходит на аппаратном уровне. Команды суперскалярных процессоров не содержат в явном виде информации, касающейся параллельной обработки внутри процессора. Пример суперскалярного процессора — Pentium.
В EPIC-процессорах (Explicitly Parallel Instruction Computing) распараллеливание происходит уже на уровне компилятора, поскольку команды в явном виде содержат информацию, касающуюся параллельной обработки внутри процессора. Это называется параллелизмом на уровне команд (ILP, Instruction-Level Parallelism). Примером EPIC-процессора является Intel Itanium.
Подклассом EPIC-процессоров являются процессоры с длинным командным словом (VLIW, Very Long Instruction Word). Команды VLIW-процессора имеют специальные поля, содержащие информацию для каждого из параллельных обрабатывающих устройств процессора, предписывающую им определенные действия.
Наиболее известными в настоящее время семействами процессоров являются:
-
х86 — CISC с элементами RISC;
-
Intel IA-64 (Intel Itanium) — EPIC;
-
IBM Power PC — RISC с элементами CISC;
-
Sun SPARC — RISC.
По данным рейтинга Top500, списка пятисот наиболее производительных компьютеров в мире (табл.1), доля компьютеров, построенных на процессорах x86, постоянно растет и в настоящее время составляет 87,6%.
Таблица 1.
Рейтинг Top500 за последние четыре года
|
Intel x86 |
AMD x86 |
Intel IA-64 |
IBM Power |
SPARC |
2006, ноябрь |
228 |
113 |
35 |
91 |
3 |
2007, ноябрь |
333 |
79 |
21 |
61 |
1 |
2008, ноябрь |
368 |
61 |
9 |
60 |
1 |
2009, ноябрь |
396 |
42 |
6 |
52 |
2 |
В персональных компьютерах доля процессоров x86 приближается к 100%.
Первый представитель этого семейства, процессор i8086, выпущенный в 1978 году, является классическим CISC-процессором Принстонской архитектуры.
Процессоры, являющиеся развитием i8086: i80286, i80386, i486, Pentium, Core2, Core i7 (i5, i3), а также процессоры AMD — относятся к семейству архитектуры x86. 32-разрядные процессоры этого семейства (начиная с i80386) составляют подсемейство архитектуры IA-32. 64-разрядное расширение, которое появилось в поздних моделях Pentium 4 относит данные процессоры к подсемейству Intel64.
Сейчас процессоры x86 сочетают в себе все преимущества основных типов архитектур: CISC и RISC, Гарвардской и Принстонской. В них постоянно развивается и совершенствуется механизм параллельной обработки, к которому относятся многоконвейерность (суперскалярность), многозадачность, технология HyperThreading, многоядерность. И хотя в системе команд параллелизм по прежнему не проявляется, Intel вместе с процессорами производит программное обеспечение, которое позволяет еще на этапах разработки и компиляции учесть особенности параллелизма этих процессоров и оптимизировать создаваемую программу для параллельного исполнения.
Предлагаемый комплект лабораторных работ направлен на изучение основных принципов устройства и функционирования компьютеров (архитектуры фон Неймана) на примере компьютеров с процессорами x86, а также некоторых важных особенностей архитектур x86, IA-32 и Intel64. Он включает четыре работы, которые тесно связаны между собой и в совокупности дают достаточно полное представление о предмете.
В дисциплине "Микропроцессорные системы" будут изучаться системы на основе микроконтроллеров Atmel AVR, имеющих Гарвардскую RISC-архитектуру. Сравнение особенностей Принстонской CISC-архитектуры x86 и Гарвардской RISC-архитектуры Atmel AVR на основе знания общей архитектуры ЭВМ даст студентам богатую пищу для размышлений и, таким образом, возможность хорошего усвоения и закрепления материала.
Главной особенностью предлагаемого комплекта лабораторных работ является опережающее знакомство студентов с материалом. В каждой лабораторной работе имеется перечень основных рассматриваемых вопросов и вопросов, рассматриваемых с опережением. Список вопросов с опережением каждой лабораторной работы представляет собой объединение подмножеств основных вопросов последующих работ. Таким образом, вопросы с опережением являются "крючочками", которые зацепляют внимание студента для более качественного выполнения последующих работ, связывают работы между собой и дают плавный переход от предыдущих работ к последующим. При приеме лабораторной работы задаются вопросы из обоих списков, но оценка выставляется только по результатам ответа на основные вопросы.
Рассматриваемые вопросы для их изучения в необходимой степени отображаются на признаки лабораторной работы, которые делятся на две категории:
-
общие признаки, характерные для всех вариантов;
-
частные признаки, признаки формирования вариантов, по значениям которых формируются различные варианты.
Частные признаки являются вспомогательными для изучения рассматриваемых вопросов. Их значения не влияют на качество и объем формируемых при выполнении лабораторной работы знаний.
Основным частным признаком (признаком формирования вариантов) является решаемая программой общая задача. Задачи могут быть различных уровней сложности:
-
Работа с массивами (одномерными) или простое преобразование данных, например, преобразование из двоичной системы счисления в коды Бергера, Бауэра и обратно.
-
Работа с матрицами (двумерными массивами) или сложное преобразование данных.
Также в качестве усложняющих элементов могут использоваться динамические структуры данных.
По общим признакам формируются сравнения, которые студенты должны сделать в процессе выполнения работы, например, дальний — ближний вызов подпрограммы. Для удобства сравнений может быть написана не одна, а несколько программ.
По каждой работе должны быть сделаны выводы по результатам анализа работы программы (программ) и выполненным сравнениям.
Пример неправильного вывода: "Я изучил дальний и ближний вызов подпрограммы".
Пример правильного вывода: "При ближнем вызове подпрограммы в стек помещается только смещение команды, следующей за командой CALL, от начала сегмента кода (текущее значение регистра IP). При дальнем вызове — полный логический адрес (пара CS:IP)".
Сравнения могут выполняться также по признакам текущей и предшествующих лабораторных работ.
Основными признаками для выделения самих работ являются:
-
Наличие ввода-вывода (IO, Input-Output).
-
Использование подпрограмм (SR, SubRouting) и, соответственно, стека.
-
Режим, реальный или защищенный (PM, Protected Mode).
Таким образом, лабораторная работа характеризуется трехбитным числом (табл.2).
Таблица 2.
Основные признаки лабораторных работ и их значения
PM |
SR |
IO |
Лабораторная работа |
0 |
0 |
0 |
1. Архитектура фон Неймана. Основные принципы устройства и работы ЭВМ |
0 |
0 |
1 |
2. Взаимодействие процессора с памятью и устройствами ввода-вывода. Функционирование ЭВМ |
0 |
1 |
1 |
3. Регистры и система команд процессора. Способы адресации. Влияние команд на регистр флагов |
1 |
1 |
1 |
4. Системная архитектура процессоров IA-32. Сегментирование и обработка прерываний в защищенном режиме |
Основные признаки работ определяют другие важные признаки, например, минимальное количество сегментов в программе, обработку прерываний для ввода информации с клавиатуры и другие.
В каждой лабораторной работе имеется список контрольных вопросов. Они соответствуют рассматриваемым вопросам, но ответ на них не предполагает механического воспроизведения соответствующего блока из раздела "Теоретическая информация". Они контролируют именно степень понимания студентом данного блока и стимулируют вдумчивую и творческую работу студентов.
Контрольные задания к лабораторным работам даются по текстам и листингам программ.
Лабораторная работа №1. Архитектура фон Неймана. Основные принципы устройства и работы ЭВМ
Цель работы и рассматриваемые вопросы
Цель работы — изучение основ устройства и принципов работы компьютера фон-неймановской архитектуры.
Рассматриваемые вопросы:
-
Основные принципы архитектуры фон Неймана.
-
Основные устройства компьютера фон-неймановской архитектуры.
-
Взаимодействие устройств компьютера фон-неймановской архитектуры.
-
Концепция хранимой программы.
-
Команды программы и данные программы. Переменные. Память команд и память данных. Принстонская и Гарвардская архитектура.
-
Основные регистры процессора компьютера фон-неймановской архитектуры.
-
Этапы выполнения программы ЭВМ архитектуры фон Неймана.
-
Представление и выполнение команд ЭВМ архитектуры фон Неймана.
-
Изменение содержимого регистров процессора и ячеек памяти в процессе выполнения команд.
-
Уровни программирования ЭВМ. Ассемблер.
-
Редактор, компоновщик и отладчик.
-
Структура команды языка ассемблера.
-
Структура программы на языке ассемблера.
-
Листинг программы.
Вопросы с опережением:
-
Последовательность выполнения программы и отдельных команд (ЛР2).
-
Способы адресации (ЛР3).
-
Влияние команд на флаги (ЛР3).
-
Типы данных (ЛР3).
-
Порядок хранения слов в памяти (ЛР3).
-
Базовые и индексные регистры (ЛР3).
-
Сегментация, сегментные регистры (ЛР3, ЛР4).
Теоретическая информация
Структура и принципы работы ЭВМ архитектуры фон Неймана
Основные принципы архитектуры фон Неймана
Практически все современные ЭВМ в своей основе имеют архитектуру фон Неймана (рис.1).
Рис.1. Схема ЭВМ архитектуры фон Неймана
В своей знаменитой работе "First Draft of a Report on the EDVAC" (Moore School of Electrical Engineering, University of Pennsylvania, June 30, 1945) Джон фон Нейман (John von Neumann) разработал фундаментальные математические основы построения компьютеров, которые предполагалось реализовать в EDVAC — Electronic Discrete Variable Automatic Computer. Сформулированные им основные принципы и называются архитектурой фон Неймана.
Основные принципы архитектуры фон Неймана (в скобках приведены оригинальные названия частей вычислительной системы из работы "First Draft of a Report on the EDVAC"):
-
Машина состоит из пяти основных блоков, представленных на рисунке: арифметико-логического устройства (CA, central arithmetical part), устройства управления (CC, central control part), запоминающего устройства (M, memory), устройства ввода (I, input) и устройства вывода (O, output). Первые два устройства вместе составляют центральный блок (C, Central), в настоящее время называемый процессором (CPU, Central Processing Unit).
-
Запоминающее устройство содержит команды и данные (концепция хранимой программы). Данные могут включать в себя переменные — поименованные области памяти, к которым можно обращаться по имени (которое для процессора представляет собой адрес) для чтения или записи (изменения их значения).
-
Устройство управления считывает команды из памяти в соответствии со значением адреса в специальном регистре — счетчике команд, декодирует их и организует выполнение, формируя необходимые управляющие сигналы. Для выполнения арифметических и логических операций используется арифметико-логическое устройство.
-
Устройства ввода и вывода используются для ввода информации, в том числе программы, в систему (в запоминающее устройство) и, соответственно, вывода ее из системы.
Помимо пяти основных блоков, фон Нейман упоминает еще одну составляющую компьютера — носитель информации (R), т. е. внешнюю память, с которого информация вводится в основную память компьютера с помощью устройства ввода и на который выводится информация из основной памяти компьютера с помощью устройства вывода.
Концепция хранимой программы
Существенной в архитектуре фон Неймана является концепция хранимой программы. В “First Draft of a Report on the EDVAC” она впервые была сформулирована в явном виде. Однако она была известна и другим исследователям в области компьютерной науки того времени, в частности разработчикам компьютера ЕNIAC (Electronic Numerical Integrator and Calculator) Джону Пресперу Экерту (J. Presper Eckert) и Джону Моучли (John Mauchly). Поэтому в точности авторство концепции хранимой программы неизвестно. Компьютер ENIAC создавался в той же Электротехнической школе Мура Пенсильванского университета в 1943-1946 гг. Однако в ENIAC команды программы не вводились в запоминающее устройство, а формировались коммутацией определенных элементов с помощью проводников.
Принстонская и Гарвардская архитектура
В архитектуре фон Неймана и команды, и данные программы представляются в одной и той же числовой двоичной форме (в ENIAC использовалась десятичная, а не двоичная арифметика) и хранятся вместе в одном и том же запоминающем устройстве.
Другая возможность — команды и данные программы хранить в физически различных запоминающих устройствах: памяти команд и памяти данных. Она была реализована в Гарвардском университете в компьютере Mark I и называется гарвардской архитектурой.
Нейман был профессором математики в Принстонском Институте сложных (специальных) исследований, поэтому фон-неймановскую архитектуру часто называют также принстонской. Однако понятия фон-неймановской и принстонской архитектур нельзя считать полными синонимами. Под принстонской архитектурой понимают именно смешанную память команд и данных в противопоставление гарвардской архитектуре с раздельной памятью команд и данных. Но и в принстонской, и в гарвардской архитектурах реализована концепция хранимой программы, которая является существенным признаком фон-неймановской архитектуры.
Типы устройств ЭВМ архитектуры фон Неймана
Устройства ввода и вывода компьютера фон-неймановской архитектуры можно объединить в одно устройство — ввода-вывода (УВВ). Арифметико-логическое устройство в совокупности с устройством управления образует процессор. Таким образом, любая ЭВМ содержит всего три типа основных устройств — процессор, память и устройства ввода-вывода. Устройства ввода-вывода называются также внешними или периферийными устройствами.
Типы взаимодействия устройств ЭВМ архитектуры фон Неймана
В архитектуре фон Неймана информация с устройства ввода поступает непосредственно в память и выдается из памяти на устройство вывода, минуя процессор. В современных компьютерах это называется прямым доступом к памяти (DMA, Direct Memory Access). Однако во многих случаях все устройства взаимодействуют, обмениваясь информацией через процессор. Это называется программируемым вводом-выводом (PIO, Programming Input-Output).
Математическая основа процессора
В качестве математической основы процессора можно привести следующую теорему [Глушков В. М. Введение в кибернетику. - Киев, 1964. - 323 с.]: "Существует такой нормальный алгоритм U, называемый универсальным нормальным алгоритмом, который для любого нормального алгоритма А и любого входного слова Р из области определения этого последнего алгоритма переводит слово АР, полученное приписыванием слова Р к алгоритму А, в слово, являющееся соответствующим выходным словом, в которое алгоритм А перерабатывает слово Р":
U(AP) = A(P).
Теорема утверждает возможность создания устройства, которое может выполнить любое заданное преобразование информации. Таким устройством и является процессор. Процессор реализует алгоритм (U) выполнения алгоритма (А). Как следует из теоремы, процессор должен получать информацию двух типов — команды (алгоритм А) и данные или операнды (входное слово Р алгоритма А). Совокупность команд и данных и представляет собой программу.
Необходимую универсальность процессора обеспечивают следующие типы команд:
-
Передачи данных. В любой программе требуется передавать данные, например, из основной памяти в регистр процессора или обратно.
-
Передачи управления (перехода, ветвления). Только при решении простых задач команды программы могут выполняться одна за другой так, как они расположены в тексте программы (в памяти). Для решения большинства задач линейной структуры программы недостаточно, требуется осуществлять переходы в заданную точку с возвратом или без, в зависимости от выполнения некоторых условий выполнять или не выполнять тот или иной фрагмент программы, идти по одной из нескольких возможных ветвей, выполнять определенный фрагмент программы несколько раз.
-
Арифметических и логических операций. Это основной тип команд, без них никакие другие команды не нужны, ведь одним из основных устройств процессора является АЛУ, арифметико-логическое устройство, которое и выполняет эти команды.
-
Машинного управления (управления процессором). Первые три типа команд относятся непосредственно к алгоритму A, они содержат информацию о задаче. Команды четвертого типа определяют условия выполнения задачи, например, должны быть разрешены прерывания или нет. Таким образом, они относятся уже в большей степени к алгоритму U, хотя и содержатся технически в алгоритме A. Можно сказать, что с их помощью алгоритм A влияет на алгоритм U.
В каждом конкретном процессоре разбиение команд на группы и подгруппы может варьироваться, но любая команда относится к одному из перечисленных типов, и никаких других типов не существует.
Регистры ЭВМ архитектуры фон Неймана
В работе “First Draft of a Report on the EDVAC” фон Нейман всего один раз использует слово "регистр". Однако он указывает, что память может быть сложным устройством, состоящим из различных частей, выполняющих свои определенные функции. В частности, фон Нейман говорит, что арифметико-логическое устройство должно хранить результаты промежуточных вычислений в отдельных запоминающих элементах. Таким образом, часть памяти оказывается в процессоре, а также и в устройствах ввода-вывода компьютера.
Отдельные элементы памяти, содержащиеся в различных устройствах компьютера, называются регистрами. Они могут быть разных размеров: 8, 16 бит и т. д.
В соответствии с рассмотренным математическим обоснованием в каждый момент времени процессор должен знать месторасположение следующей команды и операндов, в том числе выходных (т. е. куда поместить результат операции).
Для этого в процессоре имеются следующие основные регистры:
-
счетчик команд (счетчик программы (program counter, PC) или указатель команд (instruction pointer, IP)) — содержит адрес очередного байта (или слова) команды, который должен быть считан из памяти команд;
-
регистр команд — содержит код операции команды, введенный из памяти по адресу в счетчике команд;
-
аккумулятор (accumulator, A, накопительный регистр или регистр результата) — содержит входной операнд или один из входных операндов команды и результат ее выполнения.
Поскольку на протяжении определенных участков программы команды выполняются последовательно, одна за другой, так, как они расположены в тексте программы (в памяти), то счетчик команд инкрементируется при чтении каждого байта (слова) команды:
IP ← IP + 1.
Элемент цифровой электроники, реализующий операцию инкремента — это и есть счетчик.
Если же нужно нарушить последовательность выполнения команд, то используется явное задание адреса:
IP ← новое значение
или
IP ← IP + смещение.
Помимо указанных, процессор содержит множество других регистров, некоторые из которых могут иметь подобного рода специализацию.
Этапы выполнения программы ЭВМ архитектуры фон Неймана
Устройство управления ЭВМ фон-неймановской архитектуры реализует двухшаговый цикл "выборка-исполнение" (fetch-execute cycle). На шаге выборки осуществляется извлечение команды из памяти по адресу, содержащемуся в программном счетчике, и помещение ее кода операции в регистр команд. На шаге исполнения — дешифрация и собственно исполнение. Можно говорить и о трехшаговом цикле "выборка-дешифрация-исполнение". Это зависит от того, с какой степенью детализации рассматривается процесс выполнения команды. Можно ввести и большее количество шагов. Они впрямую связаны со стадиями (этапами) конвейера в конвейерных процессорах.
Процессор может иметь несколько режимов работы, которые различаются множеством команд, которые процессор может выполнить, а также некоторыми особенностями их выполнения.
Процессоры x86, начиная с i80286, имеют два основных режима работы: реальный, в котором процессор оказывается после начала работы, и защищенный.
Представление и выполнение команд
Рассмотрим фрагмент программы сложения двух чисел, которая сначала вводит в аккумулятор первое слагаемое, а затем прибавляет к нему второе (табл.3).
Таблица 3.
Фрагмент программы сложения двух чисел
№ |
Адрес (IP) |
Команда на машинном языке |
Команда на языке ассемблера |
Регистр команд |
Аккумулятор |
1. |
0000 |
B8 01 00 |
mov ax, 01 |
B8 |
0001 |
2. |
0003 |
05 02 00 |
add ax, 02 |
05 |
0003 |
В начале выполнения программы значение IP равно 0000. По этому адресу процессор читает из памяти код операции первой команды B8 и помещает его в регистр команд. IP инкрементируется. С регистром команд связан дешифратор кода операции команды. Процессор декодирует с его помощью код операции и определяет, что это команда передачи данных, непосредственно следующих за кодом операции, в аккумулятор (mov — от move, переместить). По результатам дешифрации кода операции по содержимому IP из памяти читаются второй, а затем третий байты команды и помещаются в аккумулятор. Надо отметить, что если память команд адресуется побайтно, как это имеет место в архитектуре x86, то IP инкрементируется после чтения каждого байта команды. Отметим также, что адресация (способ нахождения операнда), при которой операнд находится в самой команде, называется непосредственной.
Перед выполнением второй команды IP равен 0003. По этому адресу процессор читает из памяти код операции второй команды 05, помещает его в регистр команд, декодирует и определяет, что это команда сложения непосредственных данных с аккумулятором (add — прибавить). По результатам дешифрации кода операции из памяти читаются второй и третий байты команды и прибавляются к значению аккумулятора.
Программирование эвм
Низкий и высокий уровни программирования
Выделяются два уровня программирования:
-
Низкий — уровень команд процессора.
-
Высокий — уровень алгоритмических действий решаемой задачи.
На низком уровне можно программировать в машинных кодах (на машинном языке, языке процессора) или на языке ассемблера. На высоком уровне используется язык программирования высокого уровня (ЯВУ). Одному оператору языка высокого уровня может соответствовать множество команд процессора. Одной команде ассемблера соответствует ровно одна команда процессора.
Как уже было отмечено, и команды, и данные в ЭВМ представляются в цифровой двоичной форме. Для человека более удобной является символьная, точнее буквенная запись, поскольку цифры — это тоже символы. Для облегчения работы человека по программированию ЭВМ и был разработан язык ассемблера, затем языки высокого уровня, затем языки четвертого поколения… В этой последовательности все более повышается уровень абстракции от деталей внутреннего устройства и функционирования ЭВМ.
Поэтому при изучении архитектуры ЭВМ необходим именно язык ассемблера. Он не скрывает деталей реализации и в то же время удобен для запоминания команд. Основная часть команды на языке ассемблера и называется мнемоникой.
Интерпретатор, транслятор, компилятор и ассемблер
При программировании на каком-либо языке, отличном от машинного, неважно, высокого или низкого уровня, требуется специальная программа, которая переводит разрабатываемую программу с языка программирования на язык процессора, машинный язык. Существует два варианта перевода и исполнения разрабатываемой программы:
-
покомандно, когда очередная команда (оператор) переводится и сразу исполняется;
-
целиком, когда переводится вся программа в целом и только после этого исполняется.
Покомандная программа-переводчик называется интерпретатором. Пример интерпретатора — Basic. Программа-переводчик второго типа называется компилятором. Пример компилятора — С. Компилятор — это вид транслятора. Транслятор — это программа, которая переводит программу с одного языка программирования на другой. Компилятор — это программа, которая переводит программу с языка программирования высокого или низкого уровня на язык процессора. Файл с программой на языке программирования называется исходным, а с программой на языке процессора — объектным.
Ассемблер — это компилятор, который переводит программу с языка ассемблера на язык процессора. Часто ассемблером называют и сам язык ассемблера. Т. е. можно говорить: "Программировать на языке ассемблера" или "Программировать на ассемблере".
Интерпретация и компиляция могут сочетаться. Для этого вводится промежуточный уровень между языком программирования и языком процессора, который можно назвать языком виртуальной машины или среды исполнения. Программа с языка высокого уровня компилируется в промежуточный код, который затем исполняется в режиме интерпретации. Так происходит в среде .NET или JAVA.
Загрузчик
Итак, компилятор переводит программу на язык процессора. Но для выполнения ее нужно поместить в необходимую область памяти и передать ей управление. Это делает еще одна программа — загрузчик. В большинстве компьютеров используется специальная программа или комплекс программ — операционная система. Ее основное назначение состоит в запуске других программ на исполнение. В этом случае загрузчик входит в состав операционной системы. Для загрузки самой операционной системы используются два загрузчика: начальный, входящий в состав BIOS (Basic Input-Output System), базовой системы ввода-вывода, расположенной в ПЗУ компьютера, и расположенный на диске в загрузочном секторе. Теоретически их может быть сколько угодно. В операционных системах на основе NT загрузочный код содержится также в файле NTLDR (NT Load Direct Record).
Редактор, компоновщик и отладчик
Помимо компилятора и загрузчика для создания и запуска программы требуется еще множество программ, основными из которых являются:
-
текстовый редактор, с его помощью осуществляется ввод программы на языке программирования;
-
компоновщик, если разрабатываемая программа использует код, созданный ранее, традиционно располагающийся в т. н. библиотеках, то компоновщик объединяет все фрагменты кода в один исполняемый файл, кроме этого добавляя информацию, необходимую для запуска программы в данной операционной системе;
-
отладчик, программа, позволяющая исследовать разрабатываемую программу, прогнав ее покомандно или с заданными точками останова.
Соответствие между языком высокого уровня, языком ассемблера и языком процессора
Напишем простую программу сложения двух целых чисел на языке C:
int A = 1, B = 2, S;
void main()
{
S = A + B;
}
Тогда телу главной функции, которое состоит всего из одной строки с оператором присваивания и операцией сложения, будет соответствовать фрагмент кода на языке ассемблера и машинном языке, приведенный в табл.4.
Таблица 4.
Соответствие между фрагментами кода на различных языках
№ |
ЯВУ C |
Язык ассемблера |
Язык процессора |
1 |
S = A + B |
mov AX, A |
A1 AA 00 |
2 |
add AX, B |
03 06 AC 00 |
|
3 |
mov S, AX |
A3 90 02 |
Видно, что язык высокого уровня скрывает важнейшие детали устройства и работы компьютера.
Оператору присваивания переменной S результата сложения значений переменных A и B соответствуют три команды ассемблера и процессора. По команде mov AX, A процессор передает значение переменной A в аккумулятор. AX становится равным единице. Отметим, что размер целочисленных переменных в языке C — 16 бит. Таков же и размер регистра AX. На машинном языке команда mov AX, A представляется как трехбайтное число. Первый байт A1 — это код операции команды, который содержит информацию о действии (передаче данных из памяти данных) и об операнде-приемнике, т. е. куда передать данные (регистр AX, аккумулятор). Код операции будет помещен процессором в регистр команд для дешифрации и выработки необходимых управляющих сигналов для выполнения команды. Второй и третий байты — это адрес переменной A. В языках программирования используются символическая запись действий и операндов, имена переменных и обозначения операторов и операций. Но процессор понимает только язык двоичных чисел. Поэтому вместо mov AX — A1, вместо имени переменной A — ее адрес, 00AA. В большинстве компьютеров принят т. н. обратный порядок хранения слов (little endian order). Если число занимает в памяти больше одного байта, то сначала, по младшему адресу, располагается младший байт, а затем последующие байты. Отметим, что адресация, при которой в команде располагается адрес операнда, называется прямой.
Почему адрес именно такой? Все три переменные, A, B и S, объявлены как глобальные. Они существуют на протяжении всего времени работы программы и доступны из любых ее частей. Такие переменные располагаются в памяти в отдельной области (сегменте) данных. Указанные адреса отсчитываются от начала этого сегмента и называются смещениями. Компилятор расположил эти переменные в сегменте данных так, что их смещения приняли именно такие конкретные значения.
Вторая команда прибавляет к аккумулятору значение переменной B и результат помещает в аккумулятор. Таким образом, в аккумуляторе оказывается сумма переменных A и B. Длина команды сложения — четыре байта. Первые два байта — 03 06 — код операции с уточнением способа адресации. Следующие два байта — адрес переменной B, 00AC. 00AC - 00AA = 2 — таким образом, переменные A и B располагаются в памяти одна за другой.
Третья команда передает результат сложения из аккумулятора в переменную S. Ее адрес — 0290. Компилятор расположил ее на некотором расстоянии от переменных A и B.
Структура команды языка ассемблера
Как уже было сказано, язык ассемблера — это язык низкого уровня. Каждой команде на языке ассемблера соответствует одна машинная команда и обратно, т. е. между записью команд процессора на машинном языке и языке ассемблера существует взаимнооднозначное соответствие. Конечно, в языке ассемблера существуют и другие элементы помимо команд, о которых речь пойдет ниже, например, директивы. Директивы в языке ассемблера — это команды самому ассемблеру, необходимые для компиляции программы, например, выделения определенных областей памяти данных и заполнения их определенными значениями.
Общая форма записи команд на языке ассемблера такова:
label: mnemonic argument1, argument2, argument3
Мнемоника — это основная и обязательная часть команды. Она несет информацию первого типа — о действии, которое должен выполнить процессор по данной команде. Можно сказать, что мнемоника — это имя класса кодов операции, которым соответствует определенное действие.
Остальные части команды присутствуют опционально. Метка требуется для передачи управления на данную команду из другого места программы. В программе на машинном языке она соответствует абсолютному или относительному адресу данной команды в памяти.
Аргументы — это информация второго типа — операнды для выполнения действия. Если операндов несколько, то приемником является первый операнд.
Структура программы на языке ассемблера
Полный текст программы на языке ассемблера, выполняющей сложение двух переменных и помещающей результат сложения в третью переменную, мог бы выглядеть так:
;sum.asm — программа, вычисляющая S=A+B
data segment ;объявление начала сегмента данных
a dw 01h ;объявление и инициализация переменной A
b dw 02h ;объявление и инициализация переменной B
s dw ? ;объявление переменной S
data ends ;объявление конца сегмента данных
code segment ;объявление начала сегмента команд (кода)
assume ds:data ;регистр DS будет указывать на сегмент data
begin: mov dx, data ;точка входа в программу, DX = data
mov ds, dx ;теперь DS указывает на сегмент data
mov ax, a ;AX = A = 1
add ax, b ;AX = AX + B = 1+ 2 = 3
mov s, ax ;S = AX = 3
mov ax, 4C00h ;функция завершения программы MS-DOS c