Аппаратно-ориентированное программирование
Ф 73 Аппаратно-ориентированное программирование; Учеб. пособие – Омск: Изд-во ОмГТУ, 2005. -128 с.
Рассматривается аппаратно-зависимое программирование для современных компьютеров, базирующееся на свободно распространяемых инструментальных средствах. Изучение ведется параллельно в операционных системах Linux и Windows, начиная с простейшего использования механизма программных прерываний до применения вызываемых по имени системных подпрограмм.
Предназначено для профессиональной подготовки студентов и бакалавров направления «Информатика и вычислительная техника» по важнейшей части дисциплины «Системное программное обеспечение».
Печатается по решению редакционно-издательского совета ОмГТУ.
Удк 681.3 ббк 32.973.73ф 73
Подписано в печать 28.04.05. Бумага офсетная
. Формат 60х84 1/16Отпечатано на дупликаторе.
Усл. печ. л. 8,0. Уч.- изд. л.8,0. Тираж 150 экз. Заказ 345.
Издательство ОмГТУ. 644050, г.Омск, пр.Мира, 11
технический университет, 2005
В государственном стандарте Российской Федерации от 2000 года для специальности 220100 (Вычислительные машины, комплексы, системы и сети) содержание учебной дисциплины «Системное программное обеспечение» задается перечислением следующих базовых вопросов: «пользовательский интерфейс операционной среды; управление задачами; управление памятью; управление вводом-выводом; управление файлами; пример современной операционной системы; программирование в операционной среде; ассемблеры; мобильность программного обеспечения; макроязыки; трансляторы; формальные языки и грамматики, типы грамматик; вывод цепочек; конечный и магазинный автоматы, распознаватели и преобразователи, построение автомата по заданной грамматике; структура компиляторов и интерпретаторов, лексический, синтаксический и семантический анализаторы, генератор кода; распределение памяти, виды переменных; статическое и динамическое связывание; загрузчики; функции загрузчика; настраивающий и динамический загрузчики; подключение библиотек». Как видим, одним из принципиальных вопросов, требующих изучения будущими специалистами по информатике и вычислительной технике, является изучение даже не одного какого-то ассемблера, а более широкое их изучение. Аналогичным образом изучение ассемблеров включено в ту же учебную дисциплину и для специальности 220200 «Автоматизированные системы обработки информации и управления».
К настоящему времени на книжном рынке России присутствует немало книг и учебных пособий по программированию на ассемблере [1-2,5-13,17-20 ]. Характерным свойством практически всех этих изданий является их базирование на ассемблере, созданном еще четверть века назад и предназначенном исключительно для семейства процессоров Intel8086. Модификации указанных ассемблеров позже стали охватывать и возможности 32-битных моделей процессоров, но содержание практически всех учебных пособий строятся в архаической последовательности: вначале детально излагается ассемблер и основанные на нем средства доступа к операционной системе MS DOS, а потом, по мере накопления опыта, читателя переводят на освоение особенностей 32-битной архитектуры процессоров и приемы программирования на ассемблере для операционных систем типа MS Windows.
В XXI веке однозадачная операционная система MS DOS, бывшая такой актуальной и, казалось, удобной более двадцати лет назад, окончательно устарела. Тем не менее инерция мышления и действий преподавания настолько велика, что обучение организуется по старому. Отчасти это обусловлено тем, что программирование на языке ассемблера для операционных систем типа MS Windows требует значительно большего числа деталей и с содержательной стороны требует сознательного владения рядом понятий, которые невозможно единовременно дать читателям или слушателям из-за большого суммарного объема.
Косвенным следствием указанной ситуации стало неявное «выталкивание» из учебных программ и учебных пособий по системному программному обеспечению темы программирования на ассемблере. В качестве характерного примера можно привести, например, пособие [3], которое другие разделы государственного стандарта излагает систематически и подробно. Можно отметить и явное игнорирование ассемблеров современными педагогами, мышление которых сформировалось под влиянием формальных систем. Для последних близким и естественным кажется изучение и использование языков программирования высокого уровня (чем выше уровень, тем лучше!), но от ассемблеров они отворачиваются, как от чего-то мало значимого.
Нельзя не отметить, что великие умы не только не устранялись от систем, возможно близких реальному материальному миру, но именно на них строили свои наиболее глубокие принципиальные конструкции. В частности, один из основоположников современной информатики как фундаментальной науки — английский математик Тьюринг — описал свою вычислительную машину (названную благодарными последователями «машиной Тьюринга») как устройство с последовательной запоминающей лентой и головкой для записи и считывания символов. До сих пор «машина Тьюринга» используется как фундаментальное понятие теории алгоритмов и вычислимости, несмотря на инженерный и образный характер ее устройства.
Изучение ассемблеров для высококвалифицированных специалистов в информатике совершенно необходимо по той причине, что с помощью их человек-создатель (называемый на современном языке «инженер») способен почувствовать и уяснить, что информация в материальном мире обязательно имеет место расположения, которое для нее необходимо где-то выделить! Практически к настоящему времени известны три уровня информационных понятий, имеющих операционный характер. (Операционными считаются такие понятия, которые можно подвергать операциям достаточно универсальным, чтобы не зависеть от субъекта или наблюдателя.)
К наиболее высокому уровню операционных понятий относятся математические множества и переменные. Для них не делается никаких предположений о месте в реальном или еще каком-то пространстве и не задается никаких частных особенностей или атрибутов. К другому уровню понятий, появившемуся как раз в связи с технической информатикой, относятся информационные объекты языков программирования высокого уровня, в частности переменные в программах этих языков. Информационные объекты в языках программирования высокого уровня требуют предварительного описания, которое формально определяет их тип и/или атрибуты. В лучшем случае обучение программированию на языках высокого уровня вкладывает четкое понимание, что значение числовых переменных таких языков и математическое число существенно отличаются.
Действительно, компьютер — не абстрактный и не идеальный объект и все информационные объекты внутри него существенно отличаются от понятий языка высокого уровня (как бы ни хотелось, чтобы они совпадали). Любой информационный объект исполняемой программы вынужденно должен иметь местонахождение внутри памяти компьютера. При выполнении подавляющего большинства программ попытка выполнения действий, которые переходят действительные границы объекта, отнюдь не бессмысленна (хотя часто и приводит к ошибочным результатам). Более того, этот прием очень часто практически используется на уровне аппаратуры! Настойчивые попытки заставить выполняться программу со стороны человека, владеющего только первыми двумя из перечисленных уровней операционных понятий, в ряде случаев подобны усилиям поместить ее в «прокрустово ложе» технической реализации. Если до сих пор такие попытки не являлись «камнем преткновения», то исключительно по той причине, что основные создатели программного обеспечения начала XXI века учились еще десять-двадцать лет назад, когда было естественным понимание не только машины Тьюринга, но и особенностей программирования на ассемблере.
Уровнем ассемблера будем называть аппаратно-ориентированное программирование. (В старых терминах его называли машинно-ориентированным.) Аппаратно-ориентированное программирование понимается как программирование на уровне информационных и программных средств, непосредственно отражающих строение и размещение программной информации в аппаратуре компьютера. Этот уровень использует не только язык ассемблера, но и всю совокупность инструментов и методов при программировании на ассемблере. Сюда относятся методы и средства компиляции ассемблерных программ, приемы компоновки программ (сборки и настройки из множества объектных модулей исполняемого файла), функционирование настраивающих загрузчиков и использование отладчиков, работающих на уровне машинных кодов.
С учетом сделанных выше замечаний об архаизме традиционных путей изучения ассемблера предлагаемый далее учебный курс будет базироваться на ассемблере NASM — Netwide Assembler. Этот ассемблер как программный пакет с соответствующей документацией [22] представляет собой свободно распространяемый продукт. Последнее обстоятельство должно быть особенно существенным для современных российских вузов, так как традиционные ассемблеры фирм Microsoft и Borland/Inprise являются коммерческими продуктами, и далеко не каждый из российских вузов может позволить себе их приобретение.
Еще более существенной особенностью NASM оказывается его многоплатформенность: с помощью ее можно разрабатывать и выполнять программы как в ОС MS Windows и старой MS DOS, так и в ОС Linux, приобретающей сейчас все большее значение как в образовании, так и в корпоративных сетях. Хотя программирование на основе ассемблера не обеспечивает мобильности в пределах семейства ни только UNIX, но и более узкого семейства Linux, начальное знакомство с ассемблером оказывается проще всего осуществить именно на основе операционной системы Linux для PC компьютеров (компьютеров на процессорах, совместимых с Intel386). Это обусловлено тем, что указанная реализация Linux использует 32-битную архитектуру процессора и имеет простой доступ через прерывания к функциям ядра этой ОС.
Освоив основные языковые средства и приемы программирования в архитектуре Intel386 (называемой также архитектурой IA32), уже не сложно перейти на особенности доступа к системным функциям операционных систем типа MS Windows, что и делается в следующей части пособия. Для настойчивых любителей устаревшей ОС MS-DOS оказывается, что доступ к последней очень похож на описываемый здесь доступ к функциям ядра Linux. Поэтому для желающих появляется возможность провести практическое освоение излагаемых средств на нескольких операционных системах. В частности, первые темы можно выполнять с помощью операционных систем Linux и MS-DOS. Причем во втором случае наглядно видна ограниченность 16-битной архитектуры вместе с общностью самих практических приемов задания обработки информации на нижнем уровне архитектуры программирования.
Лекция 8. Языки программирования
Компьютерная программа представляет собой логически упорядоченную последовательность команд, предназначенных для управления компьютером. Процессор компьютера исполняет программы, написанные на машинным кодом. Писать программы в машинных кодах вручную очень сложно, причем с ростом размера программы эта задача усложняется. В компьютерах первого поколения использовались программы, написанные в машинных кодах, причем для каждого компьютера существовал свой собственный машинный код. В тот период (начало 50-х гг.) средства программирования и программное обеспечение только зарождались и были еще не развиты. Для того чтобы сделать программу читабельной и иметь возможность следить за ее смысловой структурой, разработали символический язык ассемблер, близкий к машинному (конец 50-х – начало 60-х гг.), в котором появилось понятие переменной. Ассемблер стал первым полноценным языком программирования. Благодаря этому заметно уменьшилось время разработки и возросла надежность программ. Для записи кодов операций и обрабатываемой информации в ассемблере используются стандартные обозначения, позволяющие записывать числа и текст в общепринятом виде, для кодов команд приняты мнемонические обозначения, например MOV AX, BX (переместить машинное слово из регистра AX в регистр BX), ADD AX, CX (сложить регистр AX c CX), JMP loop1 (безусловный переход не метку loop1) и др. Для обозначения величин, размещаемых в памяти, можно применять имена констант. После ввода программы ассемблер сам заменяет символические имена на адреса памяти, а символические коды команд на числовые. Использование ассемблера сделало процесс программирование более наглядным. Дальнейшее развитие этой идеи привело к созданию языков программирования высокого уровня, в которых длинные и сложные последовательности машинных кодов были заменены одним единственным обозначающим их словом – операторы.