Московский государственный университет имени М.В.Ломоносова
Опубликован: 16.09.2005 | Доступ: свободный | Студентов: 15630 / 1107 | Оценка: 4.26 / 4.03 | Длительность: 15:06:00
ISBN: 978-5-9556-0039-0
Специальности: Программист
Лекция 7:

Машинно-независимый Ассемблер RTL и Ассемблер Intel 80x86. Внешние устройства и прерывания. Виртуальная память и поддержка параллельных задач

< Лекция 6 || Лекция 7: 1234 || Лекция 8 >
Аннотация: Рассматривается способ записи программ на языке RTL (Register Transfer Language), представляющем собой Ассемблер, не зависящий от команд конкретного процессора. Приводятся примеры записи программ на RTL и на Ассемблере процессора Intel 80386. Кратко рассматриваются более сложные принципы работы компьютера: взаимодействие с внешними устройствами, асинхронные и синхронные прерывания, использование виртуальной памяти для поддержки параллельных задач, процессы, нити и их синхронизация.

RTL: машинно-независимый Ассемблер

Каждый процессор имеет свои специфические команды, наборы регистров и режимы адресации, поэтому программу на Ассемблере невозможно перенести с одной аппаратной платформы на другую. Для того чтобы не зависеть от конкретного процессора, часто используют язык описания команд RTL, от англ. Register Transfer Language — язык перемещения регистров. Фактически RTL представляет собой Ассемблер, не зависящий от конкретного процессора. Многие компиляторы, например, gcc, не переводят программу с языка высокого уровня сразу на язык машинных команд, а сначала транслируют ее на язык RTL. Затем на уровне RTL выполняется оптимизация кода, которая составляет 99% работы компилятора. И лишь на последнем этапе программа c языка RTL переводится на язык команд конкретного процессора. Поскольку RTL максимально приближен к Ассемблеру, трансляция из RTL в конкретный Ассемблер не представляет никакого труда.

Такой подход позволяет сделать компилятор с языка высокого уровня практически независимым от конкретной архитектуры. Зависим лишь модуль, осуществляющий перевод с RTL в Ассемблер, но его реализация требует минимальных усилий.

Мы будем использовать RTL для записи примеров несложных программ в кодах вместо какого-либо конкретного Ассемблера.

В RTL имеется неограниченное число регистров общего назначения

R0, R1, R2, R3, ...

и несколько выделенных регистров:

  1. счетчик команд PC;
  2. указатель стека SP;
  3. регистр флагов CC0 (от слов Conditional Codes), иногда добавляют также дополнительные регистры флагов CC1, CC2, ...;
  4. указатель кадра FP.

Слово памяти с адресом a обозначается в RTL через m[a]. Выражение a может быть константой, регистром или суммой регистра и константы, что соответствует абсолютному, косвенному и относительному режимам адресации. Примеры:

m[1000]; m[R0]; m[FP - 4].

Байт с адресом a обозначается через mb[a], короткое (двухбайтовое) слово — через ms[a].

Арифметические команды, такие, как сложение или умножение, записываются в RTL в естественном виде, например, команда сложения двух регистров R0 и R1, помещающая результат в R2, записывается в RTL в виде

R2 := R0 +R1

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

L:
      . . . 
      goto L;

Ветвление в RTL реализуется с помощью команд условного перехода, которые в зависимости от состояния различных битов или их комбинаций в регистре флагов CC0 либо осуществляют переход на указанную метку, либо ничего на делают. Например, команда

if (eq) goto L;

осуществляет переход на метку L в случае, когда результат предыдущей команды равен нулю ( eq — от слова equal), т.е. в регистре CC0 установлен бит z (от слова zero). Большинство арифметических команд автоматически устанавливают биты-признаки результата в регистре флагов CC0. Очень часто требуется просто сравнить два числа, никуда не записывая результат. Команда сравнения присутствуют в системе команд любого процессора, чаще всего она называется cmp (от слова compare). Логически команду сравнения следует понимать как вычитание двух чисел, при этом результат как бы помещается в регистр флагов. На самом деле, в регистре флагов от результата остаются лишь биты-признаки (равен ли он нулю, больше нуля и т.п.). В RTL команда сравнения двух регистров R0 и R1 записывается следующим образом:

CC0 := R0 - R1;

Результат как бы помещается в регистр флагов CC0.

В командах условного перехода, таких как

if (eq) goto L;

можно использовать следующие условия:

eq     результат равен нулю (equal)
ne     результат не равен нулю (not equal)
g      результат больше нуля (greater)
l      результат меньше нуля (less)
ge     результат больше или равен нулю (greater or equal)
le     результат меньше или равен нулю (less or equal)

Перечисленные сравнения используются для чисел со знаком. Для неотрицательных чисел (например, в случае сравнения адресов памяти) вместо слов "больше" и "меньше" используются слова "выше" и "ниже" (above и below):

a      первое число выше второго (above)
b      первое число ниже второго (below)
ae     первое число выше или равно второму (above or equal)
be     первое число ниже или равно второму (below or equal)

Приведем простой пример реализации конструкции "если":

если R0 == R1, то R2 := 77;
конец если

На RTL этот фрагмент реализуется так:

СС0 := R0 - R1;
if (ne) goto L;
R2 := 77;
L:

Отметим, что в команде условного перехода используется отрицание условия после слова "если", т.е. фактически условие обхода фрагмента кода после слова "то".

< Лекция 6 || Лекция 7: 1234 || Лекция 8 >
Кирилл Юлаев
Кирилл Юлаев
Федор Антонов
Федор Антонов

Здравствуйте!

Записался на ваш курс, но не понимаю как произвести оплату.

Надо ли писать заявление и, если да, то куда отправлять?

как я получу диплом о профессиональной переподготовке?