Язык программирования ассемблер 8086

Emu8086

Если вы скачали и установили эмулятор процессора 8086 (см. раздел ВВЕДЕНИЕ), то вы можете использовать его для создания ваших первых программ на языке ассемблера. На текущий момент (ноябрь 2011 г) доступна версия программы 4.08. Справку на русском языке вы можете найти здесь: Справка Emu8086.

Программа Emu8086 платная. Однако в течение 30 дней вы можете использовать её для ознакомления бесплатно.

Итак, вы скачали и установили программу Emu8086 на свой компьютер. Запускаем её и создаём новый файл через меню FILE – NEW – COM TEMPLATE (Файл – Новый – Шаблон файла COM). В редакторе исходного кода после этого мы увидим следующее:

Язык программирования ассемблер 8086. Смотреть фото Язык программирования ассемблер 8086. Смотреть картинку Язык программирования ассемблер 8086. Картинка про Язык программирования ассемблер 8086. Фото Язык программирования ассемблер 8086

Рис. 1.1. Создание нового файла в Emu8086.

Здесь надо отметить, что программы, создаваемые с помощью Ассемблеров для компьютеров под управлением Windows, бывают двух типов: COM и EXE. Отличия между этими файлами мы рассмотрим позже, а пока вам достаточно знать, что на первое время мы будем создавать исполняемые файлы с расширением COM, так как они более простые.

Также отметим, что регистр символов в языке ассемблера роли не играет. Вы можете написать RET, ret или Ret – это будет одна и та же команда.

Вы можете сохранить этот файл куда-нибудь на диск. Но можете и не сохранять. Чтобы выполнить программу, нажмите кнопку EMULATE (с зелёным треугольником) или клавишу F5. Откроется два окна: окно эмулятора и окно исходного кода (рис. 1.2).

Язык программирования ассемблер 8086. Смотреть фото Язык программирования ассемблер 8086. Смотреть картинку Язык программирования ассемблер 8086. Картинка про Язык программирования ассемблер 8086. Фото Язык программирования ассемблер 8086

Рис. 1.2. Окно эмулятора Emu8086.

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

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

Язык программирования ассемблер 8086. Смотреть фото Язык программирования ассемблер 8086. Смотреть картинку Язык программирования ассемблер 8086. Картинка про Язык программирования ассемблер 8086. Фото Язык программирования ассемблер 8086

Рис. 1.3. Сообщение о завершении программы.

Язык программирования ассемблер 8086. Смотреть фото Язык программирования ассемблер 8086. Смотреть картинку Язык программирования ассемблер 8086. Картинка про Язык программирования ассемблер 8086. Фото Язык программирования ассемблер 8086

Рис. 1.4. Ваша первая программа выполнена.

Как мы уже говорили, наша первая программа выводит на экран английскую букву «А». Результат оправдал наши ожидания – буква «А» выведена на экран.

Здесь стоит отметить, что Emu8086 – это ЭМУЛЯТОР, то есть он эмулирует работу компьютера с процессором 8086. Поэтому в описанном выше примере программа выполняется не операционной системой, а эмулятором. Emu8086 может создавать и реальные программы, которые могут самостоятельно выполняться на компьютере. Но описание работы с Emu8086 не входит в наши планы. Читайте справку и экспериментируйте – всё у вас получится.

В нашем случае пока не важно, как выполняется программа – эмулятором или операционной системой. Главное – разобраться с вопросом создания программ на языке ассемблера. Поэтому разберём нашу простенькую программку подробно.

ORG 100h – 2-ая строка. Эта команда устанавливает значение программного счетчика в 100h, потому что при загрузке СОМ-файла в память, DOS выделяет под блок данных PSP первые 256 байт (десятичное число 256 равно шестнадцатеричному 100). Код программы располагается только после этого блока. Все программы, которые компилируются в файлы типа СОМ, должны начинаться с этой директивы.

MOV AH, 02h – 3-я строка. Инструкция (или команда) MOV помещает значение второго операнда в первый операнд. То есть значение 02h помещается в регистр АН. Для чего это делается? 02h – это ДОСовская функция, которая выводит символ на экран. Мы пишем программу для DOS, поэтому используем команды этой операционной системы (ОС). А записываем мы эту функцию (а точнее ее номер) именно в регистр АН, потому что прерывание 21h использует именно этот регистр.

MOV DL, 41h – 4-я строка. Код символа «A» заносится в регистр DL. Код символа «A» по стандарту ASCII – это 41h.

INT 21h – 5-я строка. Это и есть то самое прерывание 21h – команда, которая вызывает системную функцию DOS, заданную в регистре АН (в нашем примере это функция 02h). Команда INT 21h – основное средство взаимодействия программ с ОС.

INT 20h – 6-я строка. Это прерывание, которое сообщает операционной системе о выходе из программы и о передаче управления консольному приложению. Значит, при использовании INT 20h в нашем примере, управление будет передаваться программе Emu8086. А в том случае, если программа уже откомпилирована и запущена из ОС, то команда INT 20h вернет нас в ОС (например, в DOS). В принципе, в случае с Emu8086 эту команду можно было бы пропустить, так как эту же функцию выполняет команда RET, которая вставляется в исходный текст автоматически при создании нового файла по шаблону (как это сделали мы ранее). Но я решил использовать INT 20h и здесь для совместимости с другими ассемблерами.

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

Источник

Основные возможности эмулятора EMU8086.

Ассемблер

Перечислите цели, функции и состав СПО.

Системное программное обеспечение – комплекс программ, которые обеспечивают управление компонентами компьютерной системы, такими как процессор, оперативная память, устройства ввода-вывода, сетевое оборудование, выступая как «межслойный интерфейс», с одной стороны которого аппаратура, а с другой — приложения пользователя.

Целью СПО является, в отличие от прикладного ПО, не решать конкретные практические задачи, а лишь обеспечивать работу других программ, предоставляя им сервисные функции.

Операционная система – комплекс системных программ, расширяющий возможности вычислительной системы.

Функции ОС:

· загрузка приложений в оперативную память и их выполнение;

· стандартизированный доступ к периферийным устройствам (устройствам ввода-вывода);

· распределение оперативной памяти между процессами;

· управление доступом к данным на носителях;

· сетевые операции, поддержка стека протоколов.

Состав СПО:

· драйверы – программы предназначенные, для управления портами периферийных устройств, загружающиеся при запуске компьютера;

· утилиты – вспомогательные или служебные программы с дополнительными услугами.

Основные понятия и определения СПО.

Перечислить этапы подготовки программы. Дать основные определения.

Этапы подготовки программы:

· обработка процессором;

· трансляция – это процесс преобразования программы, представленной на языке высокого уровня в программу на язык низкого уровня;

· выполнение.

Каковы отличия ассемблерных программ от ЯВУ?

Язык ассемблера – это машинно-ориентированный язык программирования низкого уровня. Его команды прямо соответствуют отдельным командам машины или их последовательностям.

Языки программирования низкого уровня – это языка, близкие к программированию непосредственно на машинных кодах с различием, что команды в машинных кодах выражаются наборами чисел, а в ЯПНУ в виде слов или буквенных сокращений.

Языки программирования высокого уровня – это языки, разработанные для быстроты и удобства их использования разработчиками. Они не зависят от внутренних машинных кодов любого типа, поэтому программы, написанные на языках высокого уровня, требуют перевода в машинные коды программами транслятора.

Транслятор (интерпретатор, компилятор) – программа, преобразующая программу на одном языке программирования в другой, чаще всего из высокоуровневого или низкоуровневого в машинный.

Какова структура ассемблерной программы?

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

Предложения ассемблера бывают четырех типов:

· команды или инструкции – символические аналоги машинных команд;

· макрокоманды – предложения, которые во время трансляции замещаются другими предложениями;

· директивы – указания транслятору ассемблера на выполнение некоторых действий. У директив нет аналогов в машинном представлении;

· строки комментариев – игнорируются транслятором.

В чем отличие инструкции от директивы?

(Подробнее в вопросе 5.)

Директивы выполняются в процессе превращения программы в машинный код. Инструкции составляют машинных код программы.

Каковы правила оформления программ на языке ассемблера?

· директивы производится большими буквами, инструкции – малыми;

· нельзя выходить за край экрана, текст одной строки не должен превышать 80 символов;

· для отступов возможно использование клавиши Tab;

· блоки компонентов необходимо задавать с одинаковым отступом;

· каждая новая инструкция пишется с новой строки;

· комментарии пишутся после «;» (символ точки с запятой).

История процессоров х86.

Архитектура x86 – самая распространенная архитектура для персональных компьютеров. Она берет свое начало с процессора Intel 8086. Название образовано от двух цифр, которыми заканчивались названия процессоров Intel ранних моделей — 8086, 80186, 80286 (i286), 80386 (i386), 80486 (i486).

Регистры процессора.

Регистр процессора – блок ячеек памяти, образующий сверхбыструю оперативную память внутри процессора.

Пользовательские регистры называются так потому, что программист может использовать их при написании своих программ. К этим регистрам относятся:

· восемь 32-битных регистров

o eax/ax/ah/al – аккумулятор, применяется для хранения промежуточных данных;

o ebx/bx/bh/bl – базовый регистр, применяется для хранения базового адреса некоторого объекта в памяти;

o edx/dx/dh/dl – счетчик, применяется в командах, производящих повторяющиеся действия;

o ecx/cx/ch/cl – регистр данных, он хранит промежуточные значения;

Типы данных, представленных в ПК.

Основные возможности эмулятора EMU8086.

· Программа EMU8086 сочетает в себе редактор исходного кода, ассемблер, дизассемблер, программный эмулятор с отладчиком.

· Эта программа позволяет наблюдать за регистрами, флагами и памятью во время исполнения программ.

· Программа выполняет программы на эмулированном ПК.

· Emu8086 имеет более легкий синтаксис, чем любые другие ассемблеры, но будет генерировать программу, которая сможет быть выполнена на любом компьютере, поддерживающем машинный код 8086.

Источник

1. Первая программа на ассемблер (i8086)

Статья основана на материале xrnd с сайта asmworld (из учебного курса по программированию на ассемблер 16-битного процессора 8086 под DOS).

В качестве инструментов для разработки я рекомендую этот, но примеры статьи написаны в FASM, а для отладки исопльзовался Turbo Debugger из пакета TASM.

Для того, чтобы написать программу, нам надо запустить fasmw.exe. Откроется окошко, в которое можно смело набивать код:

Язык программирования ассемблер 8086. Смотреть фото Язык программирования ассемблер 8086. Смотреть картинку Язык программирования ассемблер 8086. Картинка про Язык программирования ассемблер 8086. Фото Язык программирования ассемблер 8086

В это окошко надо ввести следующее (я подробно объясню ниже, что значит каждая строчка):

Первая строка « use16 » сообщает FASM’у, что нужно генерировать 16-битный код. Нам нужен именно такой для нашей первой программы. Точка с запятой — это символ комментария. Все что идет после «;» до конца строки игнорируется компилятором. Там можно писать все что угодно.

Вторая строка org 100h объясняет FASM’у, что следующие команды и данные будут располагаться в памяти, начиная с адреса 100h. Дело в том, что при загрузке нашей программы в память, DOS размещает в первых 256 байтах (с адресов 0000h — 00FFh ) свои служебные данные. Нам эти данные изменять нежелательно.

Далее идут непосредственно команды! Программа на ассемблере состоит из команд процессора. Каждая команда обозначается мнемоникой (символическим именем). Например «mov», «inc», «nop» и т.д. После мнемоники могут идти операнды. Они отделяются одним или несколькими пробелами (или табуляцией).

Команды бывают без операндов, с одним или несколькими операндами. Если операндов больше одного, то они отделяются друг от друга запятыми.

Отступы не обязательны, но желательны — с ними код гораздо легче читать. Пустые строки игнорируются. Регистр символов значения не имеет. Можно писать большими буквами, или маленькими, или в перемешку.

Четвертая строка определяет команду «поместить число 255 в регистр AX ». «mov» — это мнемоника команды (от английского «MOVe»). AX — первый операнд — приёмник. 255 — второй операнд — источник. Первый операнд является регистром. Второй операнд — константа 255.

Пятая строка. Тут команда « inc » с одним операндом. Она заставит процессор выполнить инкремент, то есть увеличение на единицу. Единственный операнд — это регистр AX, содержимое которого и будет увеличено на 1.

Две последние строки — это стандартное завершение процесса в DOS. Так мы будем завершать все наши программы. Команда «mov» должна быть вам понятна, а про команду «int» я ещё расскажу, это отдельная тема.

Язык программирования ассемблер 8086. Смотреть фото Язык программирования ассемблер 8086. Смотреть картинку Язык программирования ассемблер 8086. Картинка про Язык программирования ассемблер 8086. Фото Язык программирования ассемблер 8086

В общем, наша программа ничего не делает, а в следующий раз мы научимся работать с отладчиком. Загляните сюда если работаете в Tubro Debugger, или туда — если выбрали SimpleASM.

Источник

3. Регистры процессора 8086

Статья основана на материале xrnd с сайта asmworld (из учебного курса по программированию на ассемблер 16-битного процессора 8086 под DOS).

Для того, чтобы писать программы на ассемблере, нам необходимо знать, какие регистры процессора существуют и как их можно использовать. Все процессоры архитектуры x86 (даже многоядерные, большие и сложные) являются дальними потомками древнего Intel 8086 и совместимы с его архитектурой. Это значит, что программы на ассемблере 8086 будут работать и на всех современных процессорах x86.

Все внутренние регистры процессора Intel 8086 являются 16-битными:

Язык программирования ассемблер 8086. Смотреть фото Язык программирования ассемблер 8086. Смотреть картинку Язык программирования ассемблер 8086. Картинка про Язык программирования ассемблер 8086. Фото Язык программирования ассемблер 8086

Всего процессор содержит 12 программно-доступных регистров, а также регистр флагов ( FLAGS ) и указатель команд ( IP ).

Регистры общего назначения (РОН) AX, BX, CX и DX используются для хранения данных и выполнения различных арифметических и логических операций. Кроме того, каждый из этих регистров поделён на 2 части по 8-бит, с которыми можно работать как с 8-битными регистрами (AH, AL, BH, BL, CH, CL, DH, DL). Младшие части регистров имеют в названии букву L (от слова Low), а старшие H (от слова High). Некоторые команды неявно используют определённый регистр, например, CX может выполнять роль счетчика цикла.

Индексные регистры предназначены для хранения индексов при работе с массивами. SI (Source Index) содержит индекс источника, а DI (Destination Index) — индекс приёмника, хотя их можно использовать и как регистры общего назначения.

Регистры-указатели BP и SP используются для работы со стеком. BP (Base Pointer) позволяет работать с переменными в стеке. Его также можно использовать в других целях. SP (Stack Pointer) указывает на вершину стека. Он используется командами, которые работают со стеком. (Про стек я подробно расскажу в отдельной части учебного курса)

Сегментные регистры CS (Code Segment), DS (Data Segment), SS (Stack Segment) и ES (Enhanced Segment) предназначены для обеспечения сегментной адресации. Код находится в сегменте кода, данные — в сегменте данных, стек — в сегменте стека и есть еще дополнительный сегмент данных. Реальный физический адрес получется путём сдвига содержимого сегментного регистра на 4 бита влево и прибавления к нему смещения (относительного адреса внутри сегмента). Подробнее о сегментной адресации рассказывается в части 31.

COM-программа всегда находится в одном сегменте, который является одновременно сегментом кода, данных и стека. При запуске COM-программы сегментные регистры будут содержать одинаковые значения.

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

Регистр флагов FLAGS содержит отдельные биты: флаги управления и признаки результата. Флаги управления меняют режим работы процессора:

Признаки результата устанавливаются после выполнения арифметических и логических команд:

Не волнуйтесь, если что-то показалось непонятным. Из дальнейшего объяснения станет ясно, что к чему и как всем этим пользоваться.

Источник

ЯЗЫК ASSEMBLER ПРОЦЕССОРА INTEL 8086

1 Министерство образования и науки Российской Федерации Саратовский государственный технический университет ЯЗЫК ASSEMBLER ПРОЦЕССОРА INTEL 8086 Методические указания к выполнению лабораторных работ по курсу «Архитектура ЭВМ и систем» для студентов специальности Одобрено редакционно-издательским советом Саратовского государственного технического университета Саратов 2008

2 Содержание Введение. 4 Лабораторная работа 1 Структура программы языка Assembler. 6 Теоретическая часть Память и процессор Регистры процессора и их назначение Назначение и содержание регистра флагов Флаги состояния Управляющие флаги Сегментная структура программ Компиляция и запуск программы Расположение программы в памяти ЭВМ Практическая часть Упражнение 1.1. Написание первой программы Требования к отчету Контрольные вопросы Лабораторная работа 2 Команды пересылки данных и арифметические операторы Теоретическая часть Команды пересылки данных Стек и команды работы с ним Способы адресации Регистровая адресация Непосредственная адресация Прямая адресация Косвенная адресация Адресация по базе со сдвигом Косвенная адресация с масштабированием Адресация по базе с индексированием Двоичная арифметика Практическая часть Упражнение 2.1. Знакомство с отладчиком Упражнение 2.2. Вычисление значения арифметического выражения Требования к отчету Таблица вариантов заданий для упражнения Контрольные вопросы Лабораторная работа 3 Переменные в языке Assembler. Логические и битовые операторы, операторы сдвига Теоретическая часть Псевдокоманды определения переменных Структуры Логические операции Сдвиговые операции Операции над битами и байтами Практическая часть Упражнение 3.1. Создание переменных и использование меток Упражнение 3.2. Создание массивов и организация бесконечных циклов Упражнение 3.3. Логические операции над переменными Упражнение 3.4. Операторы сдвига и работы с битами Требования к отчету

3 Контрольные вопросы Лабораторная работа 4 Команды передачи управления и организация циклов Теоретическая часть Команды передачи управления Структуры IF.. THEN. ELSE Структуры CASE Практическая часть Упражнение 4.1. Обработка фиксированной последовательности чисел Упражнение 4.2. Рекуррентные соотношения Таблица вариантов для лабораторной работы Контрольные вопросы Лабораторная работа 5 Процедуры. Ввод и вывод информации Теоретическая часть Процедуры Ввод с клавиатуры Средства DOS Средства BIOS Вывод на экран в текстовом режиме Средства DOS Средства BIOS Выбор видеорежима Управление положением курсора Вывод символов на экран Практическая часть Упражнение Варианты заданий для лабораторной работы Контрольные вопросы Список литературы Приложения Приложение 1 Коды символов ASCII Приложение 2 Расширенные ASCII-коды Приложение 3 Скан-коды

4 Введение Основным элементом ЭВМ является центральный процессор (ЦП). Процессор это устройство, предназначенное для выполнения программ и управления остальными элементами ЭВМ. Для составления программ могут использоваться различные языки программирования. В качестве одной из характеристик языка программирования используется понятие его уровня: низкий, средний или высокий. Уровень языка показывает то, насколько его команды близки к командам процессора. Языки низкого уровня позволяют выполнять практически любые инструкции и лишены защитных механизмов, таких как отслеживание выхода за границы массива или потеря памяти, что позволяет получить наиболее быстрое время выполнение программы, при наименьшем расходе ресурсов системы. Однако программы, написанные на таких языках, зачастую отличаются повышенной сложностью и громоздкостью. Кроме того программы, написанные на языках низкого уровня, предназначены для выполнения на одном из семейств процессоров и обладают низкой степенью переносимости. К таким языкам относятся языки машинных команд и ассемблеры различных процессоров. Языки высокого уровня же, напротив, позволяют создавать большие проекты, состоящие из нескольких десятков строк кода. Однако они обладают меньшей, по сравнению с языками низкого уровня, гибкостью и программы, написанные на таких языках, будут иметь меньшую скорость выполнения при большем размере запускаемого файла. Языки высокого уровня имеют унифицированный набор команд, а возможность выполнения программ, написанных на одном из этих языков, на различных семействах процессоров определяется используемым компилятором. В задачу компилятора входит перевод исходного текста программы в язык команд того или иного процессора. К таким языкам относят языки С++, Java и т.д. Поэтому для знакомства с архитектурой ЭВМ рекомендуется изучить один из языков низкого уровня. Это позволит более глубоко понять принципы и законы функционирования ЭВМ и возможные пути повышения производительности составляемых программ. В настоящее время наиболее распространенными процессорами являются микропроцессоры корпорации Intel. Архитектура этих процессоров неоднократно изменялась, порождая таким образом различные семейства процессоров, каждое со своими возможностями и особенностями. Однако, внося в микропроцессор принципиальные изменения, разработчики постоянно поддерживают работу в режиме первых микропроцессоров типа 8086, использовавших всего лишь 1 мегабайт оперативной памяти, 16-разрядные операнды и ограниченный набор команд. Режим работы такого процессора 4

8 Помимо ячеек оперативной памяти, для хранения данных используются регистры. Достоинство регистров заключается в их высоком быстродействии, но их число достаточно мало. Поэтому регистры используются лишь для кратковременного хранения данных. В режиме 8086 все регистры процессора имеют длину 16 разрядов, или 1 слово (в современных процессорах 32 разряда или даже 64). За каждым регистром закреплено определенное имя (например, АХ или DS), по которому к нему можно обращаться в программе. Особо стоит рассмотреть сегментные регистры, с помощью которых осуществляется обращение процессора к ячейкам оперативной памяти. Казалось бы, для передачи процессору адреса какого-либо байта оперативной памяти достаточно записать в один из регистров процессора его номер. В действительности поступить таким образом в 16-разрядном процессоре нельзя, так как максимальное число (данное или адрес), которое можно записать в 16-разрядный регистр, составляет всего = 65535, или 64К- 1, и мы получим возможность обращения лишь к первым 64 Кбайт памяти. Для того, чтобы с помощью 16-разрядных чисел адресовать любой байт памяти, в 8086 предусмотрена сегментная адресация памяти, реализуемая с помощью сегментных регистров процессора. Суть сегментной адресации показана на рис. 1.3 и заключается в следующем. Обращение к памяти осуществляется исключительно с помощью сегментов логических образований, накладываемых на те или иные участки физической памяти. Рис Формирование физического адреса ячейки памяти при сегментной адресации Фактический адрес любой ячейки памяти вычисляется процессором путем сложения начального адреса сегмента, в котором располагается эта ячейка, со смещением к ней (в байтах) от начала сегмента. Это смещение иногда называют относительным адресом. 8

9 1.2 Регистры процессора и их назначение В современных микропроцессорах можно выделить часть, предназначенную для использования в реальном режиме и практически соответствующую процессору Этот процессор содержит двенадцать 16- разрядных программно-адресуемых регистров, которые принято объединять в три группы: регистры данных, регистры-указатели и сегментные регистры, которые изображены на рис Регистры данных и регистрыуказатели часто объединяют под общим названием «регистры общего назначения». Кроме того, в состав процессора входят указатель команд и регистр флагов. В группу регистров данных включаются четыре регистра АХ, ВХ, СХ и DX. Программист может использовать их по своему усмотрению для временного хранения любых объектов (данных или адресов) и выполнения над ними требуемых операций. При этом регистры допускают независимое обращение к старшим (АН, ВН, СН и DH) и младшим (AL, BL, CL и DL) половинам. Рис Группы 16-ти разрядных регистров процессора 8086 Так, команда mov BL, АН пересылает старший байт регистра АХ в младший байт регистра ВХ, не затрагивая при этом вторых байтов этих регистров. Во многих случаях регистры данных вполне эквивалентны, однако предпочтительнее пользоваться регистром АХ, поскольку многие команды занимают в памяти меньше места и выполняются быстрее, если их операндом является регистр АХ (или его половина AL). С другой стороны, ряд команд использует определенные 9

10 регистры неявным образом. Так, все команды циклов используют регистр СХ в качестве счетчика числа повторений; в командах умножения и деления регистры АХ и DX выступают в качестве неявных операндов; операции ввода-вывода можно осуществлять только через регистры АХ или AL и т.д. Индексные регистры SI и DI так же, как и регистры данных, могут использоваться произвольным образом. Однако их основное назначение хранить индексы, или смещения относительно некоторой базы (т.е. начала массива) при выборке операндов из памяти. Адрес базы при этом может находиться в базовых регистрах ВХ или ВР. Специально предусмотренные команды работы со строками используют регистры SI и DI в качестве неявных указателей в обрабатываемых строках. Регистр ВР служит указателем базы при работе с данными в стековых структурах, но может использоваться и произвольным образом в большинстве арифметических и логических операций. Последний из группы регистров-указателей, указатель стека SP, стоит особняком от других в том отношении, что используется исключительно как указатель вершины специальной структуры стека. Регистры SI, DI, BP и SP, в отличие от регистров данных, не допускают побайтовую адресацию. Четыре сегментных регистра CS, DS, ES и SS являются важнейшим элементом архитектуры процессора, обеспечивая, адресацию 20- разрядного адресного пространства с помощью 16-разрядных операндов. Указатель указывает в каждый момент относительный адрес команды, следующей за исполняемой. Регистр IP программно недоступен (IP это просто его сокращенное название); наращивание адреса в нем выполняет микропроцессор, учитывая при этом длину текущей команды. Команды переходов, прерываний, вызова подпрограмм и возврата из них изменяют содержимое IP, осуществляя тем самым переходы в требуемые точки программы. 1.3 Назначение и содержание регистра флагов На рис. 1.5 показан регистр флагов (его часто называют FLAGS), эквивалентный регистру состояния процессора других вычислительных систем, который содержит информацию о текущем состоянии процессора. Он включает 6 флагов состояния и 3 бита управления состоянием процессора, которые, впрочем, тоже называются флагами. Рис Регистр флагов и условные обозначения его битов 10

14 архитектурой процессора (если обращение к памяти возможно только с помощью сегментов, то и программа, видимо, должна состоять из сегментов), особенностями той операционной системы, под управлением которой эта программа будет выполняться, правилами работы выбранного транслятора разные трансляторы предъявляют несколько различающиеся требования к исходному тексту программы. Листинг 1.1 Пример сегментной структуры программы code segment ;Откроем сегмент команд begin: assume CS:code, DS:data, SS:stk; Укажем соответствие сегментных регистров сегментам mov ax, data ; Настроим DS mov ds, ax ; установить регистр DS таким ; образом, чтобы он указывал ; на сегмент данных mov ah,9 ; функция DOS вывода строки int 21h ; Вызов DOS mov ax,4c00h ; Функция DOS завершения программы int 21h ; Вызов DOS code ends ; Закроем сегмент команд data segment ; Откроем сегмент данных msg db ‘Hello world!$’ ; Выводимая строка data ends ; Закроем сегмент данных stk segment stack ; Откроем сегмент стека db 256 dup (?) ; Отводим под стек 256 байт stk ends ; Закроем сегмент стека end begin ; Конец текста с точкой входа Рассмотрим структуру программы, приведенной в листинге 1.1. В программе описаны три сегмента: сегмент команд с именем code, сегмент данных с именем data и сегмент стека с именем stk. Описание каждого сегмента начинается с ключевого слова segment, предваряемого некоторым именем, и заканчивается ключевым словом end, перед которым указывается то же имя. Имена сегментов выбираются вполне произвольно. Текст программы заканчивается директивой ассемблера end, завершающей трансляцию. В качества операнда этой директивы указывается точка входа в программу; в нашем случае это метка begin. Порядок описания сегментов в программе, как правило, не имеет значения. Часто программу начинают с сегмента данных, это несколько облегчает чтение программы. В этой программе расположен сегмент команд, за ним сегмент данных и в конце сегмент стека; такой порядок предоставляет некоторые удобства при отладке программы. Важно только понимать, что в оперативную память 14

15 компьютера сегменты попадут в том же порядке, в каком они описаны в программе. Сегменты вводятся в программу с помощью директив ассемблера segment и ends. В тексте программы встречаются ключевые слова двух типов: команды процессора (mov, int) и директивы транслятора. К директивам языка Assembler относятся обозначения начала и конца сегментов segment и ends; ключевые слова, описывающие тип используемых данных (db, dup); специальные описатели сегментов вроде stack и т. д. Директивы служат для передачи транслятору служебной информации, которой он пользуется в процессе трансляции программы. Еще одна директива ассемблера, используемая в программе, assume CS:code, DS:data, SS:stk. Здесь устанавливается соответствие сегмента code сегментному регистру CS и сегмента data сегментному регистру DS. Первое объявление говорит о том, что сегмент code является сегментом команд, и встречающиеся в этом сегменте метки принадлежат именно этому сегменту, что помогает ассемблеру правильно транслировать команды переходов. Второе объявление помогает транслятору правильно обрабатывать предложения, в которых производится обращение к полям данных сегмента data. Выше уже отмечалось, что для обращения к памяти процессору необходимо иметь две составляющие адреса: сегментный адрес и смещение. Сегментный адрес всегда находится в сегментном регистре. Однако в процессоре два сегментных регистра данных, DS и ES, и для обращения к памяти можно использовать любой из них. Разумеется, процессор при выполнении команды должен знать, из какого именно регистра он должен извлечь сегментный адрес, поэтому команды обращения к памяти через регистры DS или ES кодируются по-разному. Объявляя соответствие сегмента data регистру DS, мы предлагаем транслятору использовать вариант кодирования через регистр DS. Однако отсюда совсем не следует, что к моменту выполнения команды с обращением к памяти в регистре DS будет содержаться сегментный адрес требуемого сегмента. Более того, можно гарантировать, что нужного адреса в сегментном регистре не будет. Директива assume влияет только на кодирование команд, но отнюдь не на содержимое сегментных регистров. Поэтому практически любая программа должна начинаться с предложений, в которых в сегментный регистр, используемый для адресации к сегменту данных (как правило, это регистр DS), заносится сегментный адрес этого сегмента. Так сделано и в нашем примере с помощью двух команд mov AX,data ;Настроим DS mov DS,AX ;на сегмент данных с которых начинается наша программа. Сначала значение имени data (т.е. адрес сегмента data) загружается командой mov в регистр общего назначения процессора АХ, а затем из регистра АХ переносится в регистр DS. Та- 15

16 кая двухступенчатая операция нужна потому, что процессор в силу некоторых особенностей своей архитектуры не может выполнить команду непосредственной загрузки адреса в сегментный регистр. Приходится пользоваться регистром АХ в качестве «перевалочного пункта». Поместив в регистр DS сегментный адрес сегмента данных, мы получили возможность обращаться к полям этого сегмента. Поскольку в программе может быть несколько сегментов данных, операционная система не может самостоятельно определить требуемое значение DS, и инициализировать его приходится «вручную». Назначением программы, приведенной в листинге 1.1, является вывод на экран текстовой строки, описанной в сегменте данных. Делается это не непосредственно, а путем обращения к функциям операционной системы DOS. Дело в том, что в составе команд процессора и, соответственно, операторов языка Assembler нет команд вывода данных на экран (как и команд ввода с клавиатуры, записи в файл на диске и т.д.). Вывод даже одного символа на экран в действительности представляет собой довольно сложную операцию, для выполнения которой требуется длинная последовательность команд процессора. В состав DOS входит большое количество программ, осуществляющих стандартные и часто требуемые функции вывод на экран и ввод с клавиатуры, запись в файл и чтение из файла, чтение или установка текущего времени, выделение или освобождение памяти и многие другие. Для того чтобы обратиться к DOS, надо загрузить в регистр общего назначения АН номер требуемой функции, в другие регистры исходные данные для выполнения этой функции, после чего выполнить команду int 21h (int от interrupt, прерывание), которая передаст управление DOS. Вывод на экран строки текста можно осуществить функцией 09h, которая требует, чтобы в регистрах DS:DX содержался полный адрес выводимой строки. Регистр DS мы уже инициализировали, осталось поместить в регистр DX относительный адрес строки, который ассоциируется с именем поля данных msg. Длину выводимой строки указывать нет необходимости, так как функция 09h DOS выводит на экран строку от указанного адреса до символа доллара, который включен в выводимую строку и для функции 09h является признаком конца строки. Заполнив все требуемые для конкретной функции регистры, можно выполнить команду int 21h, которая осуществит вызов DOS. Как завершить выполняемую программу? С точки зрения вычислительной системы, завершение программы это довольно сложная последовательность операций, в которую входит, в частности, освобождение памяти, занятой завершившейся программой. Все эти действия выполняет функция DOS с номером 4Ch. Эта функция предполагает, что в регистре AL находится код завершения нашей программы, который она передаст 16

17 DOS. Если программа завершилась успешно, код завершения должен быть равен 0, поэтому мы в одном предложении mov AX,4C00h загружаем в АН 4Ch, а в AL 0, и вызываем DOS командой int 21h. 1.5 Компиляция и запуск программы Для перевода исходного кода программы на языке Assembler в исполняемый файл необходимо его оттранслировать и скомпоновать. Пусть исходный текст программы хранится в файле с именем P.ASM. Трансляция осуществляется вызовом ассемблера TASM.EXE с помощью следующей.команды DOS; tasm /z /zi p.asm Ключ /z разрешает вывод на экран строк исходного текста программы, в которых ассемблер обнаружил ошибки. Ключ /zi управляет включением в объектный файл информации, не требуемой при выполнении программы, но используемой отладчиком. Ключ /n подавляет вывод в листинг перечня символических обозначений в программе, от чего несколько уменьшается информативность листинга, но сокращается его размер. Строка вызова компоновщика имеет следующий вид: tlink /v p.obj Ключ /v передает в загрузочный файл информацию, используемую отладчиком. Запуск подготовленной программы Р.ЕХЕ осуществляется как обычного исполняемого файла. 1.6 Расположение программы в памяти ЭВМ На рис. 1.6 показано размещение сегментов в памяти, при загрузке программы. Рис Размещение сегментов в памяти при загрузке программы 17

18 Образ программы в памяти начинается с сегмента префикса программы (Program Segment Prefics, PSP), образуемого и заполняемого системой. PSP всегда имеет размер 256 байт; он содержит таблицы и поля данных, используемые системой в процессе выполнения программы. Вслед за PSP располагаются сегменты программы в том порядке, как они объявлены в программе. Сегментные регистры автоматически инициализируются следующим образом: ES и DS указывают на начало PSP (что дает возможность, сохранив их содержимое, обращаться затем в программе к PSP), CS на начало сегмента команд, a SS на начало сегмента стека. В указатель команд IP загружается относительный адрес точки входа в программу (из операнда директивы end), а в указатель стека SP величина, равная объявленному размеру стека, в результате чего указатель стека указывает на конец стека (точнее, на первое слово за его пределами). Таким образом, после загрузки программы в память адресуемыми оказываются все сегменты, кроме сегмента данных. Инициализация регистра DS в первых строках программы позволяет сделать адресуемым и этот сегмент. Рисунок подчеркивает важнейшую особенность архитектуры процессоров Intel: адрес любой ячейки памяти состоит из двух слов, одно из которых определяет расположение в памяти соответствующего сегмента, а другое смещение в пределах этого сегмента. Размер сегмента определяется объемом содержащихся в нем данных, но никогда не может превышать величину 64 Кбайт, что определяется максимально возможной величиной смещения. Сегментный адрес сегмента команд хранится в регистре CS, а смещение к адресуемому байту в указателе команд IP. Как уже отмечалось, после загрузки программы в IP заносится смещение первой команды программы; процессор, считав ее из памяти, увеличивает содержимое IP точно на длину этой команды (команды процессоров Intel могут иметь длину от 1 до 6 байт), в результате чего IP указывает на вторую команду программы. Выполнив первую команду, процессор считывает из памяти вторую, опять увеличивая значение IP. В результате в IP всегда находится смещение очередной команды, т. е. команды, следующей за выполняемой. Описанный алгоритм нарушается только при выполнении команд переходов, вызовов подпрограмм и обслуживания прерываний. Сегментный адрес сегмента данных обычно хранится в регистре DS, a смещение может находиться в одном из регистров общего назначения, например, в ВХ или SI. Однако в 8086 два сегментных регистра данных DS и ES. Дополнительный сегментный регистр ES часто используется для обращения к полям данных, не входящим в программу, например к видеобуферу или системным ячейкам. Однако при необходимости его можно настроить и на один из сегментов программы. В частности, если программа работает с большим объемом данных, для них можно предусмотреть два сегмента и обращаться к одному из них через регистр DS, а к другому через ES. 18

20 5. Скомпилируйте программу, запустив файл comp.bat, указав в качестве параметра путь к файлу Hello.asm или заменив в comp.bat «%1» на путь к файлу Hello.asm. 6. Убедитесь, что нет ошибок компиляции, у вас должно появиться окно приблизительно следующего вида: 7. Запустите программу и убедитесь, что она выводит текст. 8. Модифицируйте текст программы для вывода на экран двух сообщений. 9. Составьте отчет по лабораторной работе в соответствии с требованиями. 10. Ответьте на контрольные вопросы. Требования к отчету Отчет по лабораторной работе должен содержать следующие разделы: 1. Титульный лист. 2. Исходный код программы, составленной в пункте 8 практической части. 3. Скриншоты компиляции и выполнения программы. 4. Вывод по лабораторной работе. Контрольные вопросы 1. Расскажите о том, как нумеруются биты данных, и об их представлении на бумаге и расположении в памяти ЭВМ. 2. Почему удобнее описывать содержимое байта двумя шестнадцатеричными цифрами? 3. В чем заключается достоинство регистров? 4. Расскажите о том, как в ЭВМ адресуется память размером больше 64 Кбайт. 5. Расскажите о том, какие есть группы регистров процессора и их назначении. 6. Расскажите о регистре флагов. 7. Объясните в чем причина сегментной организации структуры программ. 8. Расскажите, как скомпилировать и запустить программу. 20

21 Лабораторная работа 2 Команды пересылки данных и арифметические операторы Цель работы: Изучить команды пересылки данных. Научиться использовать стек в программах. Познакомиться с типами адресаций, используемых в ЭВМ. Изучить команды двоичной арифметики и научиться с их помощью вычислять значение арифметических выражений. Теоретическая часть 2.1 Команды пересылки данных Команда: MOV приемник, источник Назначение: Пересылка данных Базовая команда пересылки данных. Копирует содержимое источника в приемник, источник не изменяется. Команда MOV действует аналогично операторам присваивания из языков высокого уровня, то есть команда mov ax,bx эквивалентна выражению ах = bх; языка С, за исключением того, что команда Assembler позволяет работать не только с переменными в памяти, но и со всеми регистрами процессора. В качестве источника для MOV могут использоваться: число (непосредственный операнд), регистр общего назначения, сегментный регистр или переменная (то есть операнд, находящийся в памяти). В качестве приемника регистр общего назначения, сегментный регистр (кроме CS) или переменная. Оба операнда должны быть одного и того же размера байт, слово или двойное слово. Нельзя выполнять пересылку данных с помощью MOV из одной переменной в другую, из одного сегментного регистра в другой и нельзя помещать в сегментный регистр непосредственный операнд эти операции выполняют двумя командами MOV (из сегментного регистра в обычный и уже из него в другой сегментный). Для выполнения условной пересылки данных, т.е. пересылки при выполнении определенных условий, могут использоваться различные модификации команды CMOVcc (процессор P6), с которыми вы можете ознакомиться самостоятельно, например в [1, 2]. 21

22 Еще одной полезной командой пересылки данных является команда XCHG, предназначенная для обмена значений операндов, с которой также рекомендуется ознакомиться самостоятельно 4. Стек и команды работы с ним Стеком называют область программы для временного хранения произвольных данных. Преимуществом стека, по сравнению с сегментом данных, как области для хранения данных является отсутствие необходимости заводить отдельную именованную ячейку памяти для каждого сохраняемого на время данного, что уменьшает размер программы и количество используемых имен. Удобство стека заключается в том, что его область используется многократно, причем сохранение в стеке данных и выборка их оттуда выполняются с помощью эффективных команд push и pop без указания каких-либо имен. Стек традиционно используется, например, для сохранения содержимого регистров, используемых программой, перед вызовом подпрограммы, которая, в свою очередь, будет использовать регистры процессора «в своих личных целях». Исходное содержимое регистров извлекается из стека после возврата из подпрограммы. Другой распространенный прием передача подпрограмме требуемых ею параметров через стек. Подпрограмма, зная, в каком порядке помещены в стек параметры, может забрать их оттуда и использовать при своем выполнении. Элементы стека располагаются в области памяти, отведенной под стек, начиная со дна стека (т.е. с его максимального адреса) по последовательно уменьшающимся адресам. Адрес верхнего, доступного элемента хранится в регистре-указателе стека SP. Как и любая другая область памяти программы, стек должен входить в какой-то сегмент или образовывать отдельный сегмент. В любом случае сегментный адрес этого сегмента помещается в сегментный регистр стека SS. Таким образом, пара регистров SS:SP описывают адрес доступной ячейки стека: в SS хранится сегментный адрес стека, а в SP смещение последнего сохраненного в стеке данного. Обратите внимание на то, что в исходном состоянии указатель стека SP указывает на ячейку, лежащую под дном стека и не входящую в него. На рис. 2.1 показаны различные состояния регистра SP и стека при операциях с ним. Обратите внимание на то, что после выгрузки сохраненных в стеке данных они физически не стерлись, а остались в области стека на своих местах. Правда, при «стандартной» работе со стеком они оказываются недоступными. Действительно, поскольку указатель стека SP указывает под дно стека, стек считается пустым; очередная команда push поместит новое данное на место сохраненного ранее содержимого АХ, затерев его. Однако пока стек физически не затерт, сохраненными и уже выбранными из него данными можно пользоваться, если помнить, в каком порядке они распо- 22

23 ложены в стеке. Этот прием часто используется при работе с подпрограммами. Рис Различные состояния регистра SP и стека при операциях с ним (а исходное состояние, б после загрузки одного элемента (содержимого регистра АХ), в после загрузки второго элемента (содержимого регистра DS), г после выгрузки одного элемента, д после выгрузки двух элементов и возврата в исходное состояние). Команда: PUSH источник Назначение: Поместить данные в стек Помещает содержимое источника в стек. Источником могут быть регистр, сегментный регистр, непосредственный операнд или переменная. Фактически эта команда копирует содержимое источника в память по адресу SS:[SP] и уменьшает SP на размер источника в байтах (2 или 4). Команда: POP приемник Назначение: Считать данные из стека Помещает в приемник слово или двойное слово, находящееся в вершине стека, увеличивая SP на 2 или 4 соответственно. POP выполняет действие, полностью обратное PUSH. Приемником может быть регистр общего назначения, сегментный регистр, кроме CS (чтобы загрузить CS из стека, надо воспользоваться командой RET), или переменной. Если в роли приемника выступает операнд, использующий SP для косвенной адресации, команда POP вычисляет адрес операнда уже после того, как она увеличивает SP. Команда PUSH практически всегда используется в паре с командой POP. Так, например, чтобы скопировать содержимое одного сегментного регистра в другой (что нельзя выполнить одной командой MOV), можно использовать такую последовательность команд: push cs pop ds ; теперь DS указывает на тот же сегмент, что и CS Другое частое применение команд PUSH/POP временное хранение переменных, например: push ax ; сохраняет текущее значение АХ. ; здесь располагаются какие-нибудь команды, которые используют АХ pop ax ; восстанавливает старое значение АХ 23

24 Для работы со стеком также могут использоваться команды PUSHA/POPA или PUSHAD/POPAD (процессоры 80186, 80386), предназначенные для копирования/извлечения из стека сразу всех регистров общего назначения [2, 3]. Кроме команд пересылки данных и команд работы со стеком, в процессоре 8086 предусмотрена пара команд IN/OUT для прямой работы с портами [2, 3]. 2.2 Способы адресации Большинство команд процессора вызывается с аргументами, которые в ассемблере принято называть операндами. Например: команда сложения содержимого регистра с числом требует задания двух операндов содержимого регистра и числа. Регистровая адресация Операнды могут располагаться в любых регистрах общего назначения и сегментных регистрах. В этом случае в тексте программы указывается название соответствующего регистра, например команда, копирующая в регистр AX содержимое регистра BX, записывается как mov ax,bx Непосредственная адресация Некоторые команды (все арифметические команды, кроме деления) позволяют указывать один из операндов непосредственно в тексте программы, например команда mov ax,2 помещает в регистр AX число 2. Прямая адресация Если известен адрес операнда, располагающегося в памяти, можно использовать этот адрес. Если операнд слово, находящееся в сегменте, на который указывает ES, со смещением от начала сегмента 0001, то команда mov ax,es:0001 поместит это слово в регистр AX. В реальных программах обычно для задания статических переменных используют директивы определения данных 4, которые позволяют ссылаться на статические переменные не по адресу, а по имени. Тогда, если в сегменте, указанном в ES, была описана переменная word_var размером в слово, можно записать ту же команду как mov ax,es:word_var В таком случае ассемблер сам заменит слово «word_var» на соответствующий адрес. Если селектор сегмента данных находится в DS, имя сег- 24

25 ментного регистра при прямой адресации можно не указывать, DS используется по умолчанию. Прямая адресация иногда называется адресацией по смещению. Адресация отличается для реального и защищенного режимов. В реальном режиме (так же как и в режиме V86) смещение всегда 16-битное, это значит, что ни непосредственно указанное смещение, ни результат сложения содержимого разных регистров в более сложных методах адресации не могут превышать границ слова. При программировании для Windows, для DOS4G, PMODE и в других ситуациях, когда программа будет запускаться в защищенном режиме, смещение не может превышать границ двойного слова. Косвенная адресация По аналогии с регистровыми и непосредственными операндами адрес операнда в памяти также можно не указывать непосредственно, а хранить в любом регистре. До для этого можно было использовать только BX, SI, DI и BP, но потом эти ограничения были сняты и адрес операнда разрешили считывать также и из EAX, EBX, ECX, EDX, ESI, EDI, EBP и ESP (но не из AX, CX, DX или SP напрямую надо использовать EAX, ECX, EDX, ESP соответственно или предварительно скопировать смещение в BX, SI, DI или BP). Например, следующая команда помещает в регистр AX слово из ячейки памяти, селектор сегмента которой находится в DS, а смещение в BX: mov ax,[bx] Как и в случае прямой адресации, DS используется по умолчанию, но не во всех случаях: если смещение берут из регистров ESP, EBP или BP, то в качестве сегментного регистра используется SS. В реальном режиме можно свободно пользоваться всеми 32-битными регистрами, надо только следить, чтобы их содержимое не превышало границ 16-битного слова. Адресация по базе со сдвигом Можно комбинировать косвенную и прямую адресацию. Команда mov ax,[bx+2] помещает в регистр AX слово, находящееся в сегменте, указанном в DS, со смещением на 2 большим, чем число, находящееся в BX. Так как слово занимает ровно два байта, эта команда поместила в AX слово, непосредственно следующее за тем, которое есть в предыдущем примере. Такая форма адресации используется в тех случаях, когда в регистре находится адрес начала структуры данных, а доступ надо осуществить к какомунибудь элементу этой структуры. Другое важное применение адресации по базе со сдвигом доступ из подпрограммы к параметрам, переданным в стеке, используя регистр BP (EBP) в качестве базы и номер параметра в 25

26 качестве смещения 6. Другие допустимые формы записи этого способа адресации: mov mov ax,[bp]+2 ax,2[bp] С помощью этого метода можно организовывать доступ к одномерным массивам байт: смещение соответствует адресу начала массива, а число в регистре индексу элемента массива, который надо считать. Очевидно, что, если массив состоит не из байт, а из слов, придется умножать базовый регистр на два, а если из двойных слов на четыре. Для этого предусмотрен следующий специальный метод адресации. Косвенная адресация с масштабированием Этот метод адресации полностью идентичен предыдущему, за исключением того, что с его помощью можно прочитать элемент массива слов, двойных слов или учетверенных слов, просто поместив номер элемента в регистр: mov ax,[esi*2]+2 Множитель, который может быть равен 1, 2, 4 или 8, соответствует размеру элемента массива байту, слову, двойному слову, учетверенному слову соответственно. Из регистров в этом варианте адресации можно использовать только EAX, EBX, ECX, EDX, ESI, EDI, EBP, ESP, но не SI, DI, BP или SP, которые можно было использовать в предыдущих вариантах. Адресация по базе с индексированием В этом методе адресации смещение операнда в памяти вычисляется как сумма чисел, содержащихся в двух регистрах, и смещения, если оно указано. Все следующие команды это разные формы записи одного и того же действия: mov mov mov mov mov ax,[bx+si+2] ax,[bx][si]+2 ax,[bx+2][si] ax,[bx][si+2] ax,2[bx][si] В регистр AX помещается слово из ячейки памяти со смещением, равным сумме чисел, содержащихся в BX и SI, и числа 2. Из шестнадцатибитных регистров так можно складывать только BX + SI, BX + DI, BP + SI и BP + DI, а из 32-битных все восемь регистров общего назначения. Так же как и для прямой адресации, вместо непосредственного указания числа можно использовать имя переменной, заданной одной из директив определения данных. Так можно прочитать, например, число из двумерного массива: если задана таблица 10×10 байт, 2 смещение ее начала от начала сегмента данных (на практике будет использоваться имя этой таблицы), 26

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *