Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Консп_АПЗ_ПК_12_1.doc
Скачиваний:
30
Добавлен:
23.11.2019
Размер:
624.13 Кб
Скачать

6.3. Структура программ на ассемблере masm

Программа, написанная на ассемблере MASM, может состоять из нескольких частей, называемых модулями, в каждом из которых могут быть определены один или несколько сегментов данных, стека и кода. Любая законченная программа на ассемблере должна включать один главный, или основной (main), модуль, с которого начинается ее выполнение. Основной модуль может содержать программные сегменты, сегменты данных и стека, объявленные при помощи упрощенных директив. Кроме того, перед объявлением сегментов нужно указать модель памяти при помощи директивы . MODEL. Поскольку подавляющее большинство современных приложений являются 32-разрядными, то основное внимание необходимо уделить именно таким программам, хотя нужно вспомнить и 16-разрядные программы, которые все еще используются.

В следующем примере показана 16-разрядная программа на ассемблере, в которой используются упрощенные директивы ассемблера MASM:

.model small, с ; эта директива указывается до

; объявления сегментов

.stack 100h ; размер стека 256 байт

.data ; начало сегмента данных

: данные

.code

main: ; здесь начинается сегмент программ

команды ассемблера

end main

end

Здесь оператор end main указывает на точку входа main в главную процедуру. Оператор end закрывает последний сегмент и обозначает конец исходного текста программы. В 16-разрядных приложениях MS-DOS можно инициализировать сегментные регистры так, чтобы они указывали на требуемый логический сегмент данных. Следующий пример демонстрирует это:

Листинг 6.1. Пример адресации сегментов в программе MS-DOS

.model large

.data

S1 DB "TEST STRINGS"

.code

mov AX, @data

mov DS, AX

lea DX, S1

mov AH, 9h

int 21h

mov ax, 4c00h

int 21h end

Здесь на экран дисплея выводится строка s1. При помощи следующих команд в сегментный регистр DS помещается адрес сегмента данных, указанного директивой .data:

mov АХ, @data

mov DS, AX

Затем строка s1, адресуемая через регистры DS:DX, выводится на экран с использованием прерывания 9h функции 21h MS-DOS. Попробуйте закомментировать проанализированные две строки кода и посмотреть на результат работы программы.

Для 32-разрядных приложений шаблон исходного текста выглядит иначе:

.model flat

.stack

.data

: данные

.code

main:

: команды ассемблера

end main

end

Основное отличие от предыдущего примера – другая модель памяти (flat), предполагающая 32-разрядную линейную адресацию с атрибутом near.

Как видно из примера, «классический» шаблон 32-разрядного приложения содержит область данных (определяемую директивой .data), область стека (директива .stack) и область программного кода (директива .code).

Лекция 7. Основы программирования на языке Ассемблера

7.1. Структура команды языка Ассемблера

Давайте рассмотрим команду «загрузить число 0x1234 в регистр АХ». На языке ассемблера она записывается очень просто:

MOV АХ,0x1234

Для процессора каждая команда представляется в виде двоичного числа (пункт 7 концепции фон Неймана). Ее числовое представление называется машинным кодом. Команда MOV АХ, 0x1234 на машинном языке может быть записана так:

0x1111: 0хВ8, 0x34, 0x12

0x1114: следующие команды

В рассматриваемом примере команда помещена по адресу 0x1111. Следующая команда начинается тремя байтами дальше, значит, под команду MOV с операндами отведено 3 байта. Второй и третий байты содержат операнды команды MOV. А что такое 0хВ8? После преобразования 0хВ8 в двоичную систему мы получим значение 10111000b. Первая часть – 1011 – и есть код команды MOV. Встретив код 1011, контроллер «понимает», что перед ним – именно MOV. Следующий разряд (1) означает, что операнды будут 16-разрядными. Три последние цифры определяют регистр назначения. Три нуля соответствуют регистру АХ (или AL, если предыдущий бит был равен 0, указывая таким образом, что операнды будут 8-разрядными).

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

Общий формат команды языка ассемблера такой:

имя_команды [подсказка] операнды

Необязательная подсказка указывает компилятору требуемый размер операнда. Ее значением может быть слово BYTE (8-битный операнд), WORD (16-битный) или DWORD (32-битный).

Представим инициализацию некоторой «переменной» нулем, то есть запись нулей по адресу переменной. Подсказка сообщит компилятору размер операнда, то есть сколько именно нулевых байтов должно быть записано по этому адресу. Пока мы не изучили команду для записи значения, поэтому будем считать, что записать значение можно так:

mov dword [0x12345678],0 ; записывает 4 нулевых байта,

; начиная с адреса 0x12 345678

mov word [0x12345678],0 ; записывает 2 нулевых байта,

; начиная с адреса 0x12345678

mov byte [0x12345678],0 ; записывает 1 нулевой байт

; по адресу 0x12345 678