Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

2591

.pdf
Скачиваний:
2
Добавлен:
07.01.2021
Размер:
25.15 Mб
Скачать

второй модуль предназначен для выполнения логических операций (И, ИЛИ, НЕ, ИСКЛЮЧАЮЩЕЕ ИЛИ, т.е. СЛОЖЕНИЕ ПО МОДУЛЮ ДВА; формулы вычислений – индивидуальны; вариант (номер формулы) взять у преподавателя, а при самостоятельном изучении – в

прил. 2.1).

 

 

 

 

 

 

 

Таблица 3.1

Варианты используемых логических операций

 

 

 

 

 

 

 

 

 

 

 

Логическое И

b0&b00

w0&w00

d0&d00

 

b0&w0

b0&d0

w0&d0

 

Логическое

b0 v b00

w0 v w00

d0 v d00

 

ИЛИ

b0 v w0

w0 v b0

b0 v d0

 

 

d0 v b0

w0 v d0

d0 v w0

 

Исключающее

b0 ^ b00

w0 ^ w00

d0 ^ d00

 

ИЛИ

b0 ^ w0

w0 ^ b0

b0 ^ d0

 

 

d0 ^ b0

w0 ^ d0

d0 ^ w0

 

НЕ

 

 

 

 

 

 

 

 

 

 

b0

w0

d0

 

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

Таблица 3.2

Полный текст задания к лабораторной работе №2

Ассемблер для микропроцессора Intel 8086

Операционная система MS-DOS [1, с.127–128]

Режим работы процессора реальный [1, с.20–60]

Тип программы EXE [2,с.37–39; 1, с.130–131]

Назначение программы вычисление по формуле (арифметические и логические операции)

Модель памяти – средняя [1, с.112; 4, с.45–46], т.е. один сегмент стека, один сегмент данных и два сегмента кода, что соответствует директиве определения модели памяти .medium [1, с.112]

Модули l_2_1fio.asm (один сегмент стека, один сегмент данных и один сегмента кода) и l_2_2fio.asm (один сегмент кода). Файл l_2_1fio.asm получается из файла lab1_fio.asm (в нем предусматривается ввод байта и слова с клавиатуры, процедуры перевода из символьного вида в двоичное представление для байта, слова и двойного слова, процедура перевода из двоичного представления в символьный вид и вывод на экран)

Директивы:

(те же, что и в первой лабораторной работе)

определения сегментов стандартные (полные): segment, ends и assume [1,

с.110–112; 4, с.43, 47–51];

-- позже: упрощенные директивы определения сегментов; – в уч. пос., ч. 4;

определения процедур: proc и endp [2, с.43; 1, с.115];

11

завершения программы end [1, с.115];

определение данных: байта (db), слова (dw), двойного слова (dd);

префиксы переопределения типов byte ptr, word ptr [1, с.121]

+и, кроме того, следующие:

определения учетверенного слова (dq) и десяти байт(dt) [2, с.23–24]

объявления внешних ссылок

extrn имя1:proc,имя2:proc,b1:byte,w1:word,d1:dword,rezult:qword (и, если надо, то еще одну или несколько строк extrn)

объявления меток, доступных для других модулей

 

public имя1, имя2, b1, w1, d1, rezult

 

(и, если надо, то еще одну или несколько строк public)

глобальных объявлений меток

 

global [2, с.46–47; 1, с.117–118; 4, с.88–92]

--

позже: директиву comm [1, с.117–118]

Команды – непривилегированные:

е же, что и в первой лабораторной работе)

передачи данных: mov, lea [2, с.15–17]

-- позже: команды lahf, lds, les, sahf, xchg, xlat – в уч. пос., ч. 7;

арифметические (команды двоичной арифметики): сложения (add и adc), вычитания (sub и sbb), увеличения на единицу (inc), уменьшения на единицу (dec), умножения (mul и imul), деления (div и idiv), преобразования байта в слово (cbw) и слова в двойное слово – cwd [1, с.225; 4, с.63–67];

--позже: команды cwde и cdq [1, с.32], в уч. пос., ч. 7;

сравнения cmp [1, с.37; 2, с.19];

безусловного (jmp) и условного (jz, jnz, js, jns) перехода [2, с.27–28];

 

--

позже самостоятельно: jc, jnc, jcxz – в уч. пос., ч. 4; jp, jnp, ja, jna,

 

 

jg, jge, jl, jle, jcxz [2, с.27–28], в уч. пос., ч. 7;

 

организации цикла loop [1, с.47–51; 2, с.28; 4, с.74];

 

--

позже самостоятельно: loopz, loopnz, loope [2, с.28], в уч. пос., ч. 7;

передачи управления (вызова процедур пользователя (call) и функций операционной системы DOS (int) и возврата из процедур – ret [2, с.27–31];

--позже самостоятельно: iret – выход из обработчика прерываний [2, с.29; 1, с.120–121], в уч. пос., ч. 8;

--позже: операторы short (8), small (16), large (32) [1, с.120], в уч.пос.,ч.7;

работы со стеком: push, pop [2, с.27–31];

--позже самостоятельно: pushf, popf [2, с.26], в уч. пос., ч. 6. Предусмотреть сохранение регистра флагов и порчу флага cf, sf, df, zf в процедуре

+и, кроме того, следующие:

логические: and, or, xor, not, test [2, с.23–24]

Адресация

регистр–регистр:

mov ax,bx ; занести (скопировать) в ax содержимое bx [4, с.34]

12

Продолжение табл. 3.2

--позже: mov ax,[bx] ; занести в регистр ax содержимое памяти по адресу из регистра bx [4, с.3440], в уч. пос., ч. 6

mov ax,[25] ; занести (скопировать) в регистр ax содержимое ячейки по смещению 25

mov al,bl ; занести (скопировать) в регистр al содержимое bl

mov bx,cx ; занести (скопировать) в регистр bx содержимое cx

регистр–память:

mov ax,worda ; занести в регистр ax значение переменной (слова) worda

mov al,bytea ; занести в регистр al значение переменной (байта) bytea

mov dx,worda ; занести в регистр dx значение переменной (слова) worda

память–регистр:

mov worda,ax ; занести в ячейку worda содержимое регистра ax (слово)

mov bytea,al ; занести в ячейку bytea содержимое регистра al (байт);

mov worda,cx ; занести в ячейку worda содержимое регистра cx (слово).

регистр–непосредственный операнд:

mov ax,25 ; занести в регистр ax значение 25;

mov bx,2 ; занести в регистр bx значение 2;

mov al,25 ; занести в регистр al значение 25

память–непосредственный операнд:

mov worda,25

; занести в ячейку worda значение 25;

mov bytea,25

; занести в ячейку bytea значение 25

Использование процедур операционной системы:

(те же, что и в первой лабораторной работе)

ввод с клавиатуры [2, с.57–62]

вывод на экран [2, с.63–67]

+и, кроме того, следующие:

ввод\вывод на диск (блок управления файлом – FCB, последовательная запись и чтение; длина записи = 128 байт при открытии и создании файла; создание (16h), открытие (0fh), определение области DTA 1ah), последовательная запись (15h), последовательное чтение (14h), закрытие файла

(10h).

--позже: ввод\вывод на диск через дескрипторы [2, с. 48–52];

вывод на печать

Дополнительная информация (рассматривается на практических занятиях):

(та же, что и в первой лабораторной работе)

процессоры Intel в реальном режиме [1, с.20–60];

последовательность выполнения команд [2, с.12–13];

структура процессора 8086 [2, с.9, рис. 1.1.2];

сегментная адресация [2, с.9, рис.1.1.3];

представление данных в компьютерах [1, с.14–19];

логика и организация программ;

условные и безусловные переходы [6, с. 156, 162];

дисковая память: функции базовой версии DOS [3, гл.16];

13

Продолжение табл. 3.2

+и, кроме того:

логика и организация программ – циклы [1, с.215];

использование стека;

дисковая память I: организация [3, гл.15, с.45–51];

дисковая память II: функции базовой версии DOS [3, гл.16, с.52–70];

переопределение данных: префикс ptr [1, с.121];

компоновка ехе-программы из нескольких объектных модулей (tlink lab2_1fi.obj lab2_2fi.obj)

Примеры программ: zag2_1.asm, zag2_2.asm; l_1a#.asm, l_1b#.asm; l_3a#.asm, l_3b#.asm, l_3c#.asm, lab2_and.asm, lab2_or.asm, lab2_xor.asm, lab2_not.asm lab2_test.asm, lab2pr1.asm в папке l#02#

Используемое ПО: tasm.exe, tlink.exe, td.exe

Формируемые файлы: l_2_1fio.obj, l_2_2fio.obj, l_2_1fio.lst, l_2_2fio.lst,

l_2_1fio.exe

Литература: 1. Зубков С.В. Assembler для DOS, Windows и UNIX. 3-е изд., стер. М.: ДМК Пресс; СПб.: Питер, 2005. 608 с.

2.Бурдаев О.В., Иванов М.А., Тетерин И.И. Ассемблер в задачах защиты информации/ Под ред. И.Ю.Жукова. – М.: КУДИЦ-ОБРАЗ, 2002. – 320 с.

3.Абель Питер. Язык ассемблера для IBM PC и программирования: Пер. с англ. М.: Высшая школа. – 1992. 447 с.

4.Олейник Л.Е. Язык ассемблера для микропроцессора 8086: Курс лекций. Омск: Сибирская региональная школа бизнеса, 2000.

5.Дао Л. Программирование микропроцессора 8088. М.: Мир, 1988. 356 с.

6.Абель Питер. Ассемблер. Язык и программирование для IBM PC: Пер. с англ., изд.5-е, стереот. Киев.: Век; М.: Энтроп; Киев: НТИ, 2003. 736 с.

Задание (З_ЛР_2): Составить EXE–программу для МП Intel 8086 для вычисления по двум формулам:

1)содержащей арифметические операции сложения, вычитания, умножения и деления (формулу взять у преподавателя, а при самостоятельном изучении – в уч.пос., ч. 1, если X1=1;.

2)содержащей логические операции (формулу 2 взять у преподавателя, а при самостоятельном изучении – из прил. 2.1, если X1=2 или 2,3,4 и т.д.

Использовать в качестве аргументов b1,b2,...,w1,w2,...,d1,d2,...– байты, слова и двойные слова

Вари- А. Все данные (b1,b2,b3,...,w1, w2,w3,...d1,d2,d3,....) вводятся c

анты: клавиатуры после запроса (в диалоге и прокрутка снизу–вверх).

Б. Данные (b2, b4,...,w1, w3,...,d2, d4,....) вводятся c клавиатуры после запроса (в диалоге и прокрутка снизу вверх), все остальные – из сегмента данных. Результат выводится на экран (после очистки – в строку №10) для 1<X1<20. Если X1=0 или X1>21, выдавать сообщение об ошибке.

Применяется перевод из ASCII-формата в двоичный код (для данных, введенных с клавиатуры) и перевод из двоичного кода в ASCII-формат (для данных, выдаваемых на экран)

14

Окончание табл. 3.2

В данной программе может быть использована в качестве процедуры программа, реализующая задание на лабораторную работу №1 ( lab1)

Х1 вводится с клавиатуры по запросу

Результат вывести на экран по формату:

Вари- А. "Вычисление по формуле:______(приводится соответствующая cтрока анты: формулы), Y=____ для b1=__;b2=__;b3=__; b4=__;w1=___и т.д."

Б. "Вычисление по формуле:____, Y=__ (после очистки – в строку №10)

Лабораторная считается сданной, если:

полностью выдержаны требования к программе, т.е. создана программа заданного типа для заданного микропроцессора, состоящая из заданного числа модулей и использующая перечисленные директивы, команды (в свою очередь, применяющие соответствующую адресацию), заданные процедуры (функции) заданной операционной системы MS-DOS и сформированы файлы, предусмотренные заданием;

в комментариях к вычислениям указана максимальная длина промежуточных результатов;

при ассемблировании и компоновке не обнаружено ошибок;

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

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

– текст программы прокомментирован (комментарии поясняют последовательность вычисления по формуле, назначение используемых процедур, способ передачи параметров и получение результатов)

Типичные ошибки: (см. подраздел 5)

Задание повышенной сложности (ЗПС_ЛР_2): составить EXE–программу для МП Intel 8086 для вычисления по двум формулам:

1)содержащей арифметические операции сложения, вычитания, умножения и деления (формулу взять у преподавателя, а при самостоятельном изучении – в уч.пос., ч. 1), если X1=1;

2)содержащей логические операции (формулу 2 взять у преподавателя, а при самостоятельном изучении – из прил. 2.1, если X1=2 или 2,3,4 и т.д. Использовать в качестве аргументов b1,b2,...,w1,w2,...,d1,d2,...– байты, слова и двойные слова Пользователь запрашивается о наличии в составе ПК принтера.

Если принтер есть, то выдать на печать сообщение: "Файл _________.___ сфоpмиpован"

Обязательно выводить и отрицательные и положительные значения результата

3.3. Сегмент данных сформировать аналогично примеру из прил. 2.1 (файл lab2_sa_.asm).

15

4. СВЕДЕНИЯ, НЕОБХОДИМЫЕ ДЛЯ ВЫПОЛНЕНИЯ ЛАБОРАТОРНОЙ РАБОТЫ

4.1. Программы, состоящие из нескольких модулей

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

Для создания программы, состоящей из нескольких модулей, ассемблер предусматривает три директивы: public, extrn и global.

Пример программы, состоящей из двух модулей (см. пример 2.1). Основная программа l_1a#.asm имеет следующий вид:

;-------

;EXE-программа. Модуль 1-й "Вызов процедуры умножения" (l_1a#.asm) extrn submul:far

;-----------------------------------------------

stacksg segment para Stack 'Stack' dw 64 dup (?)

stacksg ends ;-----------------------------------------------

datasg segment para 'Data'

qty

dw 0002h

;количество

price

dw 0004h

;стоимость

msg

db '0',0dh,0ah,'$'

 

datasg ends

 

;-----------------------------------------------

 

 

codesg segment para 'Code'

 

assume cs:codesg,ds:datasg,ss:stacksg

begin proc far

 

 

push ds

 

 

xor ax,ax

 

 

push ax

 

 

mov ax,datasg

 

 

mov ds,ax

 

 

mov ax,price

;ax:= стоимость (price)

 

 

16

mov bx,qty

;bx:= количество (qty)

call submul

;вызвать подпрограмму submul (внешнюю)

;результат возвращается в регистрах (dx:ax)

;в частном случае (для заданных данных), т.е. когда получается однораз-

;рядное десятичное число, предусмотрен вывод результата на экран

or al,30h

; преобразование в код ASCII

mov msg,al

 

mov ah,09h

; вывод на экран полученного значения

lea dx,msg

 

int 21h

 

ret

; возврат в DOS

begin endp codesg ends

end begin

;------- Модуль 2-й "Процедура умножения" (l_1b#.asm) codesg segment para 'Code'

submul proc far assume cs:codesg public submul

; параметры процедуре передаются в регистрах ax и bx

mul bx ; результат (произведение) возвращается в (dx:ax) ret

submul endp codesg ends end

;-------

Эти два модуля ассемблируются отдельно с помощью команд: tasm l_1a#.asm

и

tasm l_1b#.asm

а затем компонуются в программу l_1a#.exe с помощью команды: tlink l_1a#.obj+ l_1b#.obj

При запуске программы l_1a#.exe на экран выводится результат совместной работы двух модулей, т.е. произведение price и qty: 8

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

4.2. Директива public

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

17

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

datasg segment para ‘Data’

 

public

MemVar, Array1, array_length

array_length equ

100

MemVar

dw

10

Array1

db

array_length dup (?)

datasg.ends

 

codesg segment para ‘Code’

 

public

NearProc, FarProc

NearProc

proc near

 

...

 

 

NearProc

endp

; ближняя процедура

...

 

 

FarProc

label proc ; дальняя процедура

codesg ends end

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

Однако имеется один тип меток, которые нельзя сделать общедоступными. Это приравненные метки, которые равны значениямконстантам с размерами, отличными от 1 или 2 байт. Например, следующие метки общедоступными сделать нельзя:

long_value equ 1000h text_symbol equ <TextString>

Ассемблер обычно игнорирует регистр буквы, поэтому все общедоступные метки преобразуются в прописные символы (верхний регистр). Если требуется, чтобы в общедоступных метках различались буквы верхнего и нижнего регистров, то при ассемблировании всех модулей, содержащих ссылки на такие метки, нужно использовать в командной строке Турбоассемблера параметр /ml или /mx.

Например, без параметра /mx или /ml в других модулях следующие две метки будут эквивалентными:

public Symbol1, symbol1

При использовании для обеспечения различимости строчных и прописных букв в общедоступных и внешних идентификаторах параметра командной строки /mx нужно внимательно указывать буквы верхнего или нижнего регистра в директивах public или extrn. Ассемблер делает

18

доступным для других модулей тот идентификатор, который указывает в директиве public или extrn, а не тот, на который делается ссылка или который переопределяется внутри модуля. Например, директива:

public Abc abC dw

приводит к тому, что общедоступным будет имя Abc, а не abC.

Для каждого идентификатора в директиве public можно также задать язык: C, FORTRAN, PASCAL, BASIC, PROLOG и notlanguage (нет языка). Это приводит к тому, что к имени идентификатора до того, как одно в объектном файле станет общедоступным, автоматически применяются правила конкретного языка. Например, если вы описали:

public C myprog

то идентификатор myprog в исходном файле станет общедоступным, как _myprog, поскольку по соглашениям языка Си перед именами идентификаторов следует символ подчеркивания. Использование идентификатора языка в директиве public временно отменяет текущее задание языка (используемое по умолчанию или заданное в директиве

.model).

4.3.Директива extrn

Впоследнем разделе, чтобы сделать метки MemVar, Array1, array_length, NearProc и FarProc доступными для других модулей, мы использовали директиву public. Но далее возникает вопрос, каким образом другие модули могут ссылаться на эти метки?

Для того, чтобы сделать метки из другого модуля доступными в данном модуле, используется директива extrn. После того, как директива extrn будет использована, чтобы сделать доступным в данном модуле метку из другого модуля, эту метку можно использовать так же, как если бы она была определена в текущем модуле. Приведем пример другого модуля, в котором директива extern используется для ссылок на общедоступные метки, описанные в последнем разделе:

datasg segment para ‘Data’

extrn MemVar:word,Array1:byte,array_length:abs datasg.ends

codesg segment para ‘Code’

extrn NearProc:near,FarProc:far

...

mov ax,[MemVar] mov bx,offset Array1 mov cx,array_length

...

19

call NearProc

...

call FarProc codesg ends

Заметим, что все пять меток используются, как обычно. Единственное отличие от программы на ассемблере, состоящей из одного модуля, является директива extrn.

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

abs– абсолютное значение;

byte – переменная (данные) размером в байт;

dword – переменная (данные) размером в двойное слово (4 байта); dataptr – указатель на данные ближнего или дальнего типа (зависит от

модели памяти);

far – метка кода с дальним типом обращения (переход – загрузкой регистров cs:ip);

fword – 6-байтовая переменная (данные);

near – метка кода с ближним типом обращения (переход – загрузкой регистра ip);

proc – метка процедуры (near или far, в соответствии с директивой

.model);

qword – переменная (данные) размером в четверное слово (8 байтов); Имя структуры – имя определенного пользователем типа struc;

tbyte – 10-байтовая переменная (данные); unknown – неизвестный тип;

word – переменная (данные) размером в слово (2 байта).

Тип внешних данных abs используется для объявления метки, определенной в ее исходном модуле с помощью директивы equ или =. Другими словами, это метка, которая просто представляет собой имя константы и не связана с адресами кода или данных.

Очень важно, чтобы для внешних меток вы задавали корректный тип данных, так как ассемблер будет генерировать код на основе заданных типов данных и у него нет другого способа определить, что ваша спецификация некорректна. Например, если вы случайно ввели:

codesg segment para ‘Code’ extrn FarProc:near

. . .

call FarProc

20

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]