Язык Ассемблера


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

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

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

Значение каждой инструкции имеет для данного процессора конкретный, строго определенный смысл. Например, значение инструкции 4 говорит процессору 8088 (или 8086), что нужно сложить значение, хранящееся в следующей ячейке памяти, с регистром AL (далее мы рассмотрим, что это за регистр). В итоге можно указать процессору, чтобы он выполнил желаемую последовательность действий с помощью соответствующего набора значений инструкций. В действительности программа представляет собой просто последовательность инструкций и ничего более.

Откуда же процессор знает, какую инструкцию нужно выполнить следующей? С помощью отслеживания внутреннего указателя, который указывает на то место в памяти, где хранится значение следующей выполняемой инструкции. Когда из памяти считывается и выполняется следующая инструкция, указатель перемещается на следующую инструкцию. Некоторые инструкции могут устанавливать указатель инструкций в новое значение, это дает процессору возможность выполнять ряд инструкций не строго последовательно и даже выполнять различные группы инструкций, в зависимости от определенных условий.

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

add al,1

чем

4

1

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

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

i = j + k;

а на Ассемблере процессора 8088 это потребует шести строк:

mov ax,[j]

mov dx,[j+2]

add ax,[k]

addc dx,[k+2]

mov [i],ax

mov [i+2],dx

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

Зачем же тогда вообще использовать Ассемблер, если на нем программировать труднее, чем на других языках? Причина состоит в том, что Ассемблер позволяет вам достигать любой части памяти и непосредственно управлять любым устройством Ввода-вывода, поскольку программы на Ассемблере могут делать все то, на что способен процессор. С другой стороны, поскольку Ассемблер является «родным» языком компьютера, хорошо написанная на Ассемблере программа позволит получить код с наименьшим временем выполнения. Качество выполняемого кода, получаемого в других языках, страдает от того, что приходится выполнять трансляцию с этого языка на машинный язык, а код на языке ассемблера отображается в машинный язык непосредственно, без малейшей потери эффективности. На языке Ассемблера вы указываете компьютеру, что нужно делать, и он делает именно это не больше и не меньше.

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

Теперь, когда вы поняли соотношение между процессором и его языком Ассемблера, давайте рассмотрим конкретно язык Ассемблера процессора 8088.

Процессоры 8088 и 8086

Процессор 8088 это процессор, который используется в компьютерах IMP PC и XT, и благодаря которому создано одно из наиболее удачных семейств компьютеров. Однако процессор 8088 представляет собой только один процессор из серии процессоров, известных, как серия iAPx86. Другие процессоры данной серии включают в себя процессоры 8086, используемые в компьютерах IBM модели 25 и 30, процессор 80286, используемый в компьютере IBM AT и IBM PS/2 (модели 50 и 60) и процессор 80386, применяемый в компьютерах IBM PS/2 модели 80. Каждый из этих процессором так или иначе отличается от процессора 8088. В Главе 11 «Процессор 80386 и другие процессоры» различные процессоры серии iAPx86 обсуждаются более подробно. Процессоры серии iAPx86 объединяет одно общее свойство: все они могут выполнять код, написанный для процессоров 8086 и 8088.

Процессор 8086 представляет собой основание всей ветви процессоров серии iAPx86. Процессор 8086 это тот же процессор 8088 с расширенной шиной внешних данных. В то время как процессор 8086 может осуществлять передачу данных в память и из память по 16 битов за операцию, процессор 8088 может передавать данные только по 8 бит. Оба процессора имеют одинаковый набор инструкций. Вообще говоря, язык Ассемблера, используемый для программирования на IBM PC и последующих компьютерах, известен, как язык Ассемблера процессора 8086, а не язык Ассемблера процессора 8088. Поэтому при изучении остальной части данной главы нужно иметь в виду, что язык Ассемблера процессора 8086 включает в себя также Ассемблер процессора 8088.

Загрузка...