Автор: Пользователь скрыл имя, 10 Марта 2013 в 15:44, курс лекций
Один из основных принципов машины фон Неймана — то, что и программы, и данные хранятся в одной и той же памяти. Сохраняемая в памяти программа представляет собой некоторые коды, которые могут рассматриваться как данные. Возможно, с точки зрения программиста программа — активный компонент, она выполняет некоторые действия. Но с точки зрения процессора команды программы — это данные, которые процессор читает и интерпретирует. С другой стороны программа — это данные с точки зрения обслуживающих программ, например, с точки зрения компилятора, который на входе получает одни данные — программу на языке высокого уровня (ЯВУ), а на выходе выдает другие данные — программу в машинных кодах.
u большую гибкость в сопровождении, так как позволяет менять отдельные объектные модули программы, не меняя остальных модулей;
u экономию внешней памяти, т.к. объектные модули, используемые во многих программах не копируются в каждый загрузочный модуль, а хранятся в одном экземпляре.
Вариант интерпретации подразумевает прямое исполнение исходного модуля.
Интерпретация — реализация смысла некоторого синтаксически законченного текста, представленного на конкретном языке.
Интерпретатор читает из исходного модуля очередное предложение программы, переводит его в машинный язык и выполняет. Все затраты на подготовку тиражируются при каждом выполнении, следовательно, интерпретируемая программа принципиально менее эффективна, чем транслируемая. Однако, интерпретация обеспечивает удобство разработки, гибкость в сопровождении и переносимость.
Не обязательно подготовка программы должна вестись на той же вычислительной системе и в той же операционной среде, в которых программа будет выполняться. Системы, обеспечивающие подготовку программ в среде, отличной от целевой называются кросс-системами. В кросс-системе может выполняться вся подготовка или ее отдельные этапы:
u Макрообработка и трансляция
u Редактирование связей
u Отладка
Типовое применение кросс-систем — для тех случаев, когда целевая вычислительная среда просто не имеет ресурсов, необходимых для подготовки программ, например, встроенные системы. Программные средства, обеспечивающие отладку программы на целевой системе можно также рассматривать как частный случай кросс-системы.
Лекция 2.
Ассемблеры
4
Программирование на языке Ассемблера
Язык Ассемблера — система записи программы с детализацией до отдельной машинной команды, позволяющая использовать мнемоническое обозначение команд и символическое задание адресов.
Поскольку в
разных аппаратных архитектурах разные
программно-доступные
Программирование
на языке Ассемблера позволяет в
максимальной степени использовать
особенности архитектуры
Но это уже
не так для RISK-архитектур. Для того,
чтобы программа могла эффектив
Доля программ, которые пишутся на языках Ассемблеров в мире, неуклонно уменьшается, прикладное программирование на языках Ассемблеров применяется только по недомыслию. Язык Ассемблера «в чистом виде» применяется только для написания отдельных небольших частей системного ПО: микроядра ОС, самых нижних уровней драйверов — тех частей, которые непосредственно взаимодействуют с реальными аппаратными компонентами.
Этим занимается узкий круг программистов, работающих в фирмах, производящих аппаратуру и ОС. Зачем же нам тогда изучать построение Ассемблера?
Хотя разработка программ, взаимодействующих с реальными аппаратными компонентами, — редкая задача, в современном программировании при разработке прикладного, а еще более — промежуточного ПО довольно часто применяется технологии виртуальных машин. Для выполнения того или иного класса задач программно моделируется некоторое виртуальное вычислительное устройство, функции которого соответствуют нуждам этого класса задач.
Для управления таким устройством для него может быть создан соответствующий язык команд. (Широко известные примеры: MI AS/400, JVM.) Говоря шире, любую программу можно представить себе как виртуальное «железо», решающее конкретную задачу. (Конечный пользователь обычно не видит разницы между программой и аппаратурой и часто говорит не «мне программа выдала то-то», а «мне компьютер выдал то-то»). В некоторых случаях интерфейс программы удобно представить в виде системы команд, а следовательно, нужен соответствующий Ассемблер. (Это, конечно, относится не к программам «для чайников», а к инструментальным средствам программистов, системам моделирования).
4
Предложения языка Ассемблера
Предложения языка Ассемблера описывают команды или псевдокоманды (директивы). Предложения-команды задают машинные команды вычислительной системы; обработка Ассемблером команды приводит к генерации машинного кода. Обработка псевдокоманды не приводит к непосредственной генерации кода, псевдокоманда управляет работой самого Ассемблера. Для одной и той же аппаратной архитектуры могут быть построены разные Ассемблеры, в которых команды будут обязательно одинаковые, но псевдокоманды могут быть разные.
Во всех языках Ассемблеров каждое новое предложение языка начинается с новой строки. Каждое предложение, как правило, занимает одну строку, хотя обычно допускается продолжение на следующей строке/строках. Формат записи предложений языка м.б. жесткий или свободный. При записи в жестком формате составляющие предложения должны располагаться в фиксированных позициях строки. (Например: метка должна располагаться в позициях 1-8, позиция 9 — пустая, позиции 10-12 — мнемоника команды, позиция 13 — пустая, начиная с позиции 14 — операнды, позиция 72 — признак продолжения). Обычно для записи программ при жестком формате создаются бланки. Жесткий формат удобен для обработки Ассемблером (удобен и для чтения).
Свободный формат допускает любое количество пробелов между составляющими предложения.
В общих случаях предложения языка Ассемблера состоят из следующих компонент:
u метка или имя;
u мнемоника;
u операнды;
u комментарии.
Метка или имя является необязательным компонентом. Не во всех языках Ассемблеров эти понятия различаются. Если они различаются (например, MASM), то метка — точка программы, на которую передается управление, следовательно, метка стоит в предложении, содержащем команду; имя — имя переменной программы, ячейки памяти, следовательно, имя стоит в предложении, содержащем псевдокоманду резервирования памяти или определения константы. В некоторых случаях метка и имя могут отличаться даже синтаксически, так, в MASM/ TASM после метки ставится двоеточие, а после имени — нет.
Однако, физический смысл и метки, и имени — одинаков, это — адрес памяти. Во всех случаях, когда Ассемблер встречает в программе имя или метку, он заменяет ее на адрес той ячейки памяти, к которую имя/метка именует.
Правила формирования
имен/меток совпадают с
В языке должны
предусматриваться некоторые
u метка/имя должна начинаться в 1-й позиции строки
u если метки/имени нет, то в 1-й позиции должен быть пробел, или за меткой/именем должно следовать двоеточие, и т.п.
Мнемоника — символическое обозначение команды/псевдокоманды.
Операнды — один или несколько операндов, обычно разделяемые запятыми. Операндами команд являются имена регистров, непосредственные операнды, адреса памяти (задаваемые в виде констант, литералов, символических имен или сложных выражений, включающих специальный синтаксис). Операнды псевдокоманд могут быть сложнее и разнообразнее.
Комментарии — любой текст, который игнорируется Ассемблером. Комментарии располагаются в конце предложения и отделяются от текста предложения, обрабатываемого Ассемблером, каким-либо специальным символом (в некоторых языках — пробелом). Всегда предусматривается возможность строк, содержащих только комментарий, обычно такие строки содержат специальный символ в 1-й позиции.
Константы — могут представлять непосредственные операнды или абсолютные адреса памяти. Применяются 10-е, 8-е, 16-е, 2-е, символьные константы.
Непосредственные операнды — записываются в сам код команды.
Имена — адреса ячеек памяти.
При трансляции Ассемблер преобразует имена в адреса. Способ преобразования имени в значение зависит от принятых способов адресации. Как правило, в основным способом адресации в машинных языках является адресация относительная: адрес в команде задается в виде смещения относительно какого-то базового адреса, значение которого содержится в некотором базовом регистре. В качестве базового могут применяться либо специальные регистры (DS, CS в Intel) или регистры общего назначения (S/390).
Литералы — записанные в особой форме константы. Концептуально литералы — те же имена. При появлении в программе литерала Ассемблер выделяет ячейку памяти и записывает в нее заданную в литерале константу. Далее все появления этого литерала Ассемблер заменяет на обращения по адресу этой ячейки. Таким образом, литеральные константы, хранятся в памяти в одном экземпляре, независимо от числа обращений к ним.
Специальный синтаксис — явное описание способа адресации (например, указание базового регистра и смещения).
4
Регистры
Программа в
машинном коде состоит из различных
сегментов для определения
Для выполнения программ компьютер временно записывает программу и данные в основную память. Компьютер имеет также ряд pегистров, которые он использует для временных вычислений.
4
Биты и байты
Минимальной единицей информации в компьютере является бит. Бит может быть выключен, так что его значение есть нуль, или включен, тогда его значение равно единице. Единственный бит не может представить много информации в отличие от группы битов.
Группа из девяти битов представляет собой байт; восемь битов которого содержат данные и один бит — контроль на четность. Восемь битов обеспечивают основу для двоичной арифметики и для представления символов, таких как буква A или символ *. Восемь битов дают 256 различных комбинаций включенных и выключенных состояний: от «все выключены» (00000000) до «все включены» (11111111). Например, сочетание включенных и выключенных битов для представления буквы A выглядит как 01000001, а для cимвола * — 00101010 (это можно не запоминать). Каждый байт в памяти компьютера имеет уникальный адрес, начиная с нуля.
Требование контроля на четность заключается в том, что количество включенных битов в байте всегда должно быть не четно. Контрольный бит для буквы A будет иметь значение единица, а для символа * — ноль. Когда команда обращается к байту в памяти, компьютер проверяет этот байт. В случае, если число включенных битов является четным, система выдает сообщение об ошибке. Ошибка четности может явится результатом сбоя оборудования или случайным явлением, в любом случае, это бывает крайне редко.
Откуда компьютер «знает», что значения бит 01000001 представляют букву A? Когда на клавиатуре нажата клавиша A, система принимает сигнал от этой конкретной клавиши в байт памяти. Этот сигнал устанавливает биты в значения 01000001. Можно переслать этот байт в памяти и, если передать его на экран или принтер, то будет сгенерирована буква A.
По соглашению биты в байте пронумерованы от 0 до 7 справа налево:
Номера бит: 7 6 5 4 3 2 1 0
Значения бит: 0 1 0 0 0 0 0 0
Число 2 в десятой степени равно 1024, что составляет один килобайт и обозначается буквой К. Например, компьютер с памятью в 512 К содержит 512 х 1024, то есть, 524288 байт. Процессор в PC и в совместимых моделях использует 16-битовую архитектуру, поэтому он имеет доступ к 16-битовым значениям как в памяти, так и в регистрах. 16-битовое (двухбайтовое) поле называется словом. Биты в слове пронумерованы от 0 до 15 справа налево.
4
ASCII
Для целей стандартизации в микрокомпьютерах используется aмериканский национальный стандартный код для обмена информацией ASCII (American National Standard Code for Information Interchange). Читается как «аски» код. Именно по этой причине комбинация бит 01000001 обозначает букву A.
Наличие стандартного
кода облегчает обмен данными
между различными устройствами компьютера.
8-битовый расширенный ASCII-код, используемый
в PC обеспечивает представление 256 символов,
включая символы для
4
Двоичные числа
Так как компьютер может различить только нулевое и единичное состояние бита, то он работает системе исчисления с базой 2 или в двоичной системе. Фактически бит унаследовал cвое название от английского «Binary digit» (двоичная цифра).
Сочетанием двоичных цифр (битов) можно представить любое значение. Значение двоичного числа определяется относительной позицией каждого бита и наличием единичных битов.
Самый правый бит имеет весовое значение 1, следующая цифра влево — 2, следующая — 4 и так далее. Общая сумма для восьми единичных битов в данном случае составит 1+2+4+...+128, или 255 (2 в восьмой степени — 1).
Для двоичного числа 01000001 единичные биты представляют значения 1 и 64, то есть, 65. Но 01000001 представляет также букву A! Действительно, здесь момент, который необходимо четко уяснить. Биты 01000001 могут представлять как число 65, так и букву A:
u если программа определяет элемент данных для арифметических целей, то 01000001 представляет двоичное число эквивалентное десятичному числу 65;
u если программа определяет элемент данных (один или более смежных байт), имея в виду описательный характер, как, например, заголовок, тогда 01000001 представляет собой букву или «строку».