Программирование на Ассемблере для IBM PC 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Программирование на Ассемблере для IBM PC



Программирование на Ассемблере для IBM PC

Литература:

1. Д.Бредли. Программирование на языке ассемблера для персональной ЭВМ фирмы IBM. М.: Р. и С.1988

2. Л. Скэнлон. Персональные ЭВМ IBM PC и XT. Программирование на языке ассемблера. М.: РиС. 1989

3. Р. Джордейн. Справочник программиста персональных компьютеров типа IBM PC, XT и АТ. М.: ФиС. 1992.

4. П. Нортон. Программно-аппаратная организация IBM PC. РиС

5. П. Нортон. Персональный компьютер фирмы IBM и операционная система MS DOS. М.: РиС, 1991.

6. Ю.-Чжен Ли, Г.Гибсон. Микропроцессоры семейства 8086/8088. М.: РиС, 1987

7. П.И.Рудяков, У.Г.Финотенов. Программируем на языке ассемблера IBM PC в 2х частях. Москва ЭНТРОП, 1995 г.

8. Абель. Язык ассемблера для IBM PC. 1994 г.

9. Нортон. Программирование на языке ассемблера для IBM PC.


Программная модель 8086

AX AH AL   группа HL аккумулятор
BX BH BL   базовый регистр
CX CH CL   регистр счетчик
DX DH DL   регистр данных

 

  SI   группа PI индекс источника
  DI   индекс приемника
  BP   указатель базы

 

  SP указатель стека
  IP указатель команд
  FLAG регистр флагов

 

  CS сегментные регистры
  DS
  ES
  SS

 

МП 8086 – 16 разрядный МП (выпуск 1979 год)

8088 – 8 разрядный вариант 8086 (8 линий данных), но имеет все функциональные возможности 8086.

Отечественный аналог 8086 – КР1810ВМ86.

В 8086 имеется определенная совместимость с 8080. 8086 – базовый МП в семействе 80х86.

Число линий адреса возросло с 16 до 20, то есть мы можем адресовать 1Мб.

 

Программная модель МП

 

набор РОН AX AH AL аккумулятор
BX BH BL базовый регистр
CX CH CL регистр счетчик
DX DH DL регистр данных
  8 разр. 8 разр.  
  SI индекс источника
  DI индекс приемника
  BP указатель базы
  SP указатель стека
  16 разр.  

 

  CS   сегмент кода
  DS   сегмент данных
  ES   дополнительный сегмент
  SS   сегмент стека
  16 разр 4 разр  

 

 

  IP указатель команд
  FLAGH FLAGL регистр флагов
       

 

SI, DI, BP, SP – могут использоваться и в разных целях (в частности для сравнения 16-разрядных адресов), но чаще по названию.

 

Регистры АX, BX, CX, DX – 16 разрядные. Имеют старшую и младшую половину, которые могут быть использованы самостоятельно. В этом случае эти 8-битные регистры обозначаются AH, AL, BH, BL, CH, CL, DH, DL. Буквы A, B, C, D являются начальными буквами слов А ккумулятор, Б аза, С четчик, Д анные.

 

С точки зрения программной совместимости с МП 8080 имеется следующее соответствие:

МП 8086 МП 8080
AL A
BH H
BL L
CH B
CL C
DH D
DL E

 

Cлово состояния МП имеет 16 бит, но 7 из них не используются.

Флажки разделены на условные (флажки условий) – отражают результат предыдущих операций,

и управляющие (флажки управления), от которых зависит выполнение специальных функций.

 

Младший байт PSW соответствует 8-битному PSW МП 8080 и содержит все флажки кроме OF.

 

                               
        OF DF IF TF SF ZF   AF   PF   СF
  флажки 8080

 

  флажок  
SF знак  
ZF ноль  
PF паритет 1, если младшие 8 бит результата содержит четное число единиц
CF перенос при сложении/вычитании происходит перенос (заем) из старшего бита.
AF полуперенос перенос-заем из 4 бита
OF переполнение  
    флажки управления  
DF флажок направления применяется в командах манипуляции с цепочками. если сброшен – цепочка обрабатывается с 1-го элемента если установлен – от наибольшего элемента к меньшему
IF разрешение прерываний если установлен, МП распознает маскируемые прерывания, в противном случае они игнорируются.
TF трассировка после каждой команды генерируется внутреннее прерывание
         

 

Регистры SS, DS, ES и BS – сегментные регистры – они содержат неявные адреса сегментов. Эти регистры 16-разрядные, но они смещены на 4 разряда влево по отношению к другим. Физический адрес, выдаваемый на шину адреса, определяется следующим образом:

 

смещение   16 бит
  +  
сегментный адрес 16 бит  
  ¯ ¯
физический адрес 20 бит  
       

 

Применение сегментных регистров разделяет пространство памяти на неперекрывающиеся сегменты, каждый из которых имеет размер 64 Кбайт и начинается на 16-байтной границе, то есть на физическом адресе, кратном 16-ти.

Далее будем называть содержимое сегментного регистра – сегментным адресом. Сегментный адрес ´ 16 – начальным сегментным адресом.

 
 


Пример

 

}341B - смещение
Смещение 341B

Нач. адрес + 123А0

сегмента 157ВВ

 


Сегментная память

 

 
 

 


Программный код, данные и стек можно, например, распределить следующим образом:

 
 

 

 


В общем случае любой МП (в том числе и 8086) выполняет следующие шаги:

1).Выборка следующей команды по адресу и РС;

2).Загрузка в регистр команды и дешифрация с одновременным инкриментом РС для адресации следующей команды;

3).Выполнение команды, а в случае перехода загрузка в РС адреса перехода;

4). Повторение шагов 1-3.

 

Однако в МП 808 имеются некоторые отличия и совмещения нескольких операций.

Адрес следующей команды равен (IP)+(CS)´16.

Регистр команды представлен 6-байтной очередью FIFO, которая непрерывно заполняется, когда системная шина не требуется для других операций. Такое «опережение» значительно повышает производительность МП, так как к моменту завершения текущей команды, следующая чаще всего уже находится в конвейере. В случае перехода очередь сбрасывается и не дает экономии времени, но в среднем это происходит нечасто.

Длина команды от 1 до 6 байт. Если слово находится по четному адресу, то оно считывается уеликом, если по нечетному, то за два раза.

Рассмотрим заполнение ковейера последовательно: 1-байтная команда, 2-байтная команда и 3-байтная команда. Предположим, что эта последовательность начинается по четному адресу:

 

  Загрузка ¯  
3-я выборка   3-я команда
 
2-я выборка  
  2-я команда
1-я выборка  
  1-я команда
  Очередь команд (конвейер)  

 

Эта же последовательность, но начинается с нечетного адреса:

 

    Загрузка ¯  
4-я выборка не начинается до освобождения в очереди слова     3-я команда
3-я выборка  
 
2-я выборка   2-я команда
 
1-я выборка   1-я команда
    Очередь  

 

Последний байт не передается, пока в очереди не образуется пустого слова.

code_seg segment

org 100h

start:

mov AH, 2h

mov DL, 2Ah

int 21h

int 20h

code_seg ends

end start

 

 

code_seg segment

assume cs:code_seg, ds:code_seg, ss:code_seg

org 100h

start:

jmp begin

mes: DB 13, 10, ‘Привет, я печатаю HEX содержимое регистра BL’, 13, 10, ‘$’

begin:

mov AH, 9h

lea DX, mes

int 21h

int 20h

code_seg ends

end start

 

 


code_seg segment

assume cs:code_seg, ds:code_seg, ss:code_seg

org 100h

start:

jmp begin

mes: DB 13, 10, ‘Привет, я печатаю HEX содержимое регистра BL’, 13, 10, ‘$’

begin:

mov Ah, 9h; Функция DOS для вывода строки символов

; $ - ограничитель строки

lea DX, mes

int 21h; print string

;

mov BL, 0Fh

mov AH, 02

mov DL, BL

add DL, 30h

cmp DL, 3Ah

jl print

add DL, 07h

print:

int 21h

int 0h

code_seg ends

end start

 

 

code_seg segment

assume cs:code_seg, ds:code_seg, ss:code_seg

org 100h

start:

jmp begin

mes: DB 13, 10, ‘Привет, я печатаю HEX содержимое регистра BL’, 13, 10, ‘$’

begin:

mov Ah, 9h; Функция DOS для вывода строки символов

; $ - ограничитель строки

lea DX, mes

int 21h; print string

;

mov BL, 0AFh

mov AH, 02

mov DL, BL

call print_hex

mov DL, BL

call print_hex

int 20h

print_hex:

and DL, 0Fh

add DL, 30h

cmp DL, 3Ah

jl print

add DL, 07h

print:

int 21h

code_seg ends

end start

 

 

code_seg segment

assume cs:code_seg, ds:code_seg, ss:code_seg

org 100h

start:

jmp begin

mes: DB 13, 10, ‘Привет, я печатаю HEX содержимое регистра BL’, 13, 10, ‘$’

begin:

mov Ah, 9h; Функция DOS для вывода строки символов

; $ - ограничитель строки

lea DX, mes

int 21h; print string

;

mov BL, 0Fh

mov AH, 02

mov DL, BL

add DL, 30h

cmp DL, 3Ah

jl print

add DL, 07h

print:

int 21h

int 20h

code_seg ends

end start

 

 

Вывод на экран

Инструкция INT - interrupt – прерывание.

20H ® AX INT 21H – вызов функции DOS

41H ® DX код символа

 

Значение 02h в регистре AH – номер функции.

 

INT 20H – выход из программы.

 

MOV AH, 02H; загружаем в AH число 02h

 

MOV AH, 02H MOV DL, 2AH INT 21H INT 20H   Печать * на экране

 

Вывод строки символов

INT 21H, но с другим номером функции.

Для 02Н – 1 символ

09Н – печатает целую строку, пока не встретит символ ‘$’

 

MOV AH, 09

MOV DX, 0200H

INT 21H

INT 20H

 


Процедуры

 

Это список инструкций, который можно вызвать из различных мест программы. Аналог функции в С и подпрограммы.

Процедуру можно вызвать с помощью CALL имя, и выход с помощью REТ. Адрес возврата запоминается в стеке.

САLL имя

…….

имя: …

процедура
…….

….

….

RET

……

 

Теперь напишем программу распечатки содержимого регистра BL.

 

MOV DL, BL

RCR DL, 4; сдвиг вправо на 4 бита

MOV DL, BL

CALL PRINT_HEX

INT 20H

PRINT_HEX:

AND DL, 0FH

ADD DL, 030H

CMP DL, 03AH

JL PRINT

ADD DL, 07H

PRINT: INT 21H

RET

 

Ввод символов

Вызов DOS через INT 21H, предварительно загрузив в AH единицу, обеспечив ввод одного символа.

Решим следующую задачу – сформировать байт из шестнадцатеричного числа (из 2-х шестнадцатиричных цифр). Если вводится символ, который нельзя преобразовать в шестнадцатеричную цифру, то – звонок.

 

CALL INP_HEX

MOV AL, DL

RCL DL, 4

CALL INP_HEX

ADD DL, AL

MOV AH, 02

INT 21H

INT 20H

INP_HEX:

PUSH DX

MOV AH, 08; считать символ, но не выводить его на экран

LOOP: INT 21H

CMP AL, 030H

JB BEEP

CMP AL, 046H

JA BEEP

CMP AL, 039H

JA CONT

MOV AH, 02

MOV DL, AL

SUB AL, 030H

POP DX

RET

BEEP: INT 21H

CONT: CMP AL, 041H

JB LOOP

MOV AH, 02

MOV DL, AL

INT 21H

SUB AL,037H

POP DX

RET

 

 

РАБОТА С ДИСКОВЫМИ ФАЙЛАМИ

 

В DOS доступны следующие функции работы с файлами:

 

39h – создать каталог файлов (аналогично функции MKDIR DOS)

перед использованием

DS:DX – адрес ASCIIZ – строки –имя пути для нового каталога.

Ошибки в АХ: 3 - путь не найден

5 – ошибка в доступе

 

3Аh – удалить каталог

DS:DX – адрес ASCIIZ – строки –имя пути для нового каталога.

Ошибки в АХ те же.

 

3Вh – сменить текущий каталог

DS:DX – то же

АХ – 3

 

3Сh – создать файл (CREATE)

открывает существующий или создает новый файл.

DS:DX – адрес ASCIIZ строки.

СХ – аттрибут файла

АХ – возвращается логический номер файла.

 

Логический номер файла или дескриптор – это 16-битовое число, используемое DOS как указатель на систему таблиц. Логический номер освобождается после закрытия файла и может быть использован повторно.

Существует пять стандартных логических номеров 0-4, которые автоматически предоставляются любой программе. Остальные номера с большими логическими номерами DOS предоставляет по требованию.

 

Логический номер Использование Устройство по умолчанию
  Стандартный ввод (клавиатура) CON:
  Стандартный вывод (экран) CON:
  Стандартное устройство вывода при ошибке CON:
  Стандартное вспомогательное устройство AUX:
  Стандартное устройство печати PRN:

 

АSCIIZ-строка

Функции DOS, работающие с файлами, требуют задания имени и пути к файлу в виде ASCIIZ строки. ASCIIZ строка состоит из обычных ASCII символов, за которыми следует нулевой байт. Типичная строка выглядит наподобие:

C:\DIRECTORY1\DIRECTORY2\FILENAME.EXT

В качестве разделителя может быть как прямая, так и обратная косая черта. (имя дисковода может быть опущено)

Eh – закрытие файла

Логический номер в ВХ.

Код ошибки 6 – ошибочный логический номер.

 

H – удалить файл.

DS:DX – адрес строки, определяющей имя файла.

Заполнители? и * в имени файла использовать нельзя.

 

Пример

 

; создание файла

MOV AH, 3Ch; Функция CREATE

MOV CX, 0; Без аттрибутов

MOV DX, OFFSET Filename; Адрес имени Файла

INT 21h; ВЫзов DOS

Jc error1; ошибка

Mov Handler, AX; сохраним дескриптор

; запись строки в файл

MOV AH, 40h; Функция записи

MOV BX, Handler; Дескриптор

MOV CX, BufLen; Число записываемых байтов

MOV DX, OFFSET Buf; Адрес буфера

INT 21h

Jc error2

; закрытие файла

MOV AH, 3Eh;

MOV BX, Handler

INT 21h

Jc error3

; завершение программы

MOV AX, 4C00h; Функция завершения

INT 21h

error1: …

error2: …

error3: …

 

; данные

Buf DB ‘0123456789’; Данные, записываемые в файл

BufLen EQU $ - Buf; Длина данных. $ - текущее значение счетчика

Handler DW?; Ячейка для дескриптора

Filename DB ‘D:\test\myfile.001’,0; ASCIIZ строка спецификации файла

В простых программах файлы можно не закрывать, так как функция завершения 4Ch закрывает все открытые файлы программы.

 

Рассмотрим пример программы с имеющимся файлом:

; Открыть файл

MOV AH, 3Dh; функция OPEN

MOV AL, 2; Доступ для чтения/записи

MOV DX, OFFSET Filename; Адрес имени файла

INT 21h

Jc error1

MOV Handler, AX; Сохранение дескриптора

; Пытаемся прочитать 65535 байт

MOV AH, 3Fh; Функция READ

MOV BX, Handler; Дескриптор

MOV CX, 65535; Сколько читать

MOV DX, OFFSET BufIn; Сюда читать

INT 21h

Jc error2

MOV CX, AX; сколько реально прочитано

; Вывод прочитанного на экран

MOV AH, 40h; функция WRITE

MOV BX, 1; Дескриптор стандартного вывода

MOV DX, OFFSET BufIn; отсюда выводить (СХ байт)

Int 21h

; завершение программы

MOV AX, 4C00h; Функция завершения

INT 21h

error1: …

error2: …

error3: …

; Данные

BufIn DB 256 dup (‘ ‘); буфер ввода

Handler DW?

Filename DB ‘D:\test\myf.001’,0; спецификация файла

 

В данном случае на экран.

Удобнее вывести с помощью 40h, так какмы не занем длину выводимого сообщения, то есть не знаем, куда поставить ‘$’ для функции 9h.

 

Анализ системных ошибок

MOV AH, Function; Номер функции

; Заполнение регистров параметрами, необходимыми для

; выполнения данной функции

INT 21h

JC Error; флаг СF установлен

; Нет, нормальное продолжение программы

…………..

Error: ….

; Да, анализ ошибок в АХ

CMP AX, 1

JE Error1

CMP AX, 2

JE Error2

…..


43h – получить, установить аттрибуты файла

56h – переименовать файл

57h – получить/установить дату и время последнего изменения файла

 

В DOS 3.00

5Ah – создать временный файл

CX - аттрибут

DS:DX – имя пути, должно заканчиваться ‘ \’

Строка должна иметь длину на 12 байт больше длины имени пути, чтобы DOS могла бы дополнить уникальным именем файла.

5Bh – создать новый файл

В отличие от 3Сh, если файл уже существует, то 5Bh сообщает об ошибке.

 

5Сh – блокировать/разблокировать доступ к файлу.


ПРЕРЫВАНИЯ.

 

Прерывание (interrupt) – это аппаратная функция, вызывающая приостановку операций CPU, запоминание его состояния и выполнение специальной программы, которая называется программой обработки прерывания (interrupt service routine - ISR) или обработчиком прерывания (interrupt handler).

Существует три класса прерываний:

- внутренние

- внешние (аппаратные)

- программные

 

Внутренние прерывания инициируются состоянием самого процессора (например, деление на ноль)

Внешние – сигналом, подаваемым в CPU другими компонентами вычислительной системы (например, при любом нажатии на клавишу).

Программные прерывания – специальной командой INT.

 

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

Микропроцессоры семейства 8086 способны обрабатывать 256 типов прерываний. Каждое прерывание имеет номер от 0 до 255.

Начало оперативной памяти от адреса 0000h до 03FFh отводится под векторы прерываний. Вектор прерывания – это 2 слова памяти (4 Байта), в которых хранятся адреса программ обработки прерываний (ISR). В старшее слово записывается сегментный адрес ISR, в младшее слово – сещение ISR, то етсь относительный адрес точки входа ISR в сегменте. Вектор 0 располагается, начиная с адреса 0, вектор 1 – с адреса 4, вектор 2 – с адреса 8 и т.д. Вектор с номером N занимает, таким образом, байты с N*4 до N*4+3.

 
 

 

 


Получив сигнал на выполнение процедуры прерывания с определенным номером, CPU сохраняет в стеке выполняемой программы текущее содержимое трех регистров процессора: регистра флагов, CS и IP. Два последних образуют полный адрем возврата в прерванную программу. Далее процессор загружает CS и IP из соответствующеговектора прерывания, осуществляя тем самым переход на ISR.

Программа ISR обычно заканчивается командой возврата из прерывания iret (interrupt return - возврат из прерывания), которая выполняет обратные действия - загрузку IP, CS и регистра флагов из стека, что приводит к возврату в основную программу.

Большая часть векторов прерывания предназначена для выполнения определенных действий и автоматически заменяется адресами системных программ при загрузке системы; часть векторов зарезервирована для будущих применений, а часть (конкретно с номерами 60h...66h) свободна и может использоваться в прикладных программах.

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

 


code_seg segment

assume cs:code_seg, ds:code_seg, ss:code_seg

org 100h

start:

jmp begin

line db 2

column db 10

sym db 01h

;

begin:

mov ah,25h;функция заполнения вектора прерывания

mov al,65h;номер вектора

mov dx,offset new_65h;смещение обработчика

int 21h

;

gogo:

int 65h

mov ah,02h;функция позиционирования

mov bh,0;видеостраница

mov dh,line;строка

mov dl,column;столбец

int 10h

;

mov ah,0ah;функция вывода символа без атрибута

mov al,sym;символ

mov bh,0;видеостраница

mov cx,60;коэффициент повторения

int 10h

;

inc sym;следующий символ

inc line;следующая строка

mov ah,08h;функция вывода без эха,

; чувствительна на Ctrl+C

int 21h

;

jmp gogo

;

new_65h proc near

mov ah,06h;функция задания окна

mov al,0;режим создания (нет прокрутки)

mov bh,1bh;атрибут всех символов в окне

;(светло-бирюзовые символы, синий фон)

mov cx,0;левый верхний угол 0,0

mov dh,24;нижняя Y-координата

mov dl,79;правая X-координата

int 10h

iret

new_65h endp

code_seg ends

end start


Макрокоманды.

 

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

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

Использование макрокоманд (макросов) позволяет:

· упростить и сократить исходный текст.

· сделать программу более понятной.

· уменьшить число ошибок, т.е. увеличить скорость отладки.

 

Макроопределения.

 

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

 

Формат макроопределения.

имя macro;начало макроопределения

.

.;тело макроопределения

..

endm;конец макроопределения

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

Например:

_print_ macro;Вывод сообщения на экран

mov ah, 09h

lea dx, mes

int 21h

endm


Использование параметров в макроопределениях.

 

В предыдущем примере макрокоманда всегда выводит на экран сообщение, находящееся в mes.

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

Например:

_print_ macro msg;Вывод сообщения на экран

mov ah, 09h

lea dx, msg

int 21h

endm

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

_print_ msg1

_print_ msg2

Макроопределение может содержать ссылку на другое макроопределение.

Рассмотрим пример:

dos21 macro dosfunc

mov ah, dosfunc

int 21h

endm

Для использования данной макрокоманды при вводе с клавиатуры необходимо:

lea dx,namepar

dos21 0ah

Предполагается, что имеется другое макроопределение, использующее функцию 02 в регистре ah для ввода символа.

disp macro char

mov ah,02

mov dl,char

int 21h

endm

Можно изменить макроопределение disp, воспользовавшись макрокомандой dos21:

 

disp macro char

mov dl,char

dos21 02

endm

Для вывода ‘*’ достаточно просто написать:

disp ‘*’

Директива LOCAL

 

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

Для обеспечения уникальности генерируемых в каждом макрорасширении имен используется директива LOCAL, которая должна быть непосредственно после macro.

Общий формат:

local метка1, метка2

Например:

prim_ macro

local compar,exit

...

compar:...

...

exit:...

и макрокоманда prim_ два раза встречается в контексте нашей программы:

...

prim_

...

prim_

В первом макрорасширении генерируются метки??0000 и??0001 соответственно для compar и exit. Во втором макрорасширении - метки??0002 и?0003 и т.д.


Директивы повторения.

 

rept, irp, irpc

 

Директивы повторения заставляют ассемблер повторить блок операторов, завершаемых директивой endm. Эти директивы не обязательно должны находится в макроопределении, но если они там находятся, то одна директива endm требуется для завершения повторяющего блока, а вторая - для завершения макроопределения.

 

rept: Повторение.

 

Операция rept приводит к повторению блока операторов до директивы endm в соответствии с числом повторений, указанных в выражении:

Формат:

rept выражение

endm

 

Пример:

n=0

rept 5

n=n+1

db n

endm

 

В результате будет сгенерировано пять операторов db от db 1 до db 5. Т.о. директива rept может использоваться для определения таблицы или части таблицы.

 

irp: Неопределенное повторение

Irp приводит к повторению блока команд до директивы endm.

 

Формат:

irp метка, <аргументы>

<Блок кода>

endm

Аргументы, заключенные в угловые скобки - это любое число правильных символов, чисел или строк.

Ассемблер генерирует блок кода для каждого аргумента.

 

Пример:

 

irp n, <3,9,17,25,28>

db n

endm

 

В результате будет сгенерировано пять операторов db от db 1 до db 5.

 

irpc: Неопределенное повторение символов.

 

Операция irpc приводит к повторению блока операторов до директивы endm.

 

Формат:

irpc метка, строка

<блок кода>

endm

 

Ассемблер генерирует блок кода для каждого символа в строке ‘строка’.

 

Пример:

 

irpc n, 34567

dw n

endm

 

В результате будет сгенерировано пять операторов db от db 3 до db 7.

 

Условные директивы.

 

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

Формат:

ifxx условие;Начало if структуры

...

else

...

endif;Конец if структуры

 

Директива else может отсутствовать.

Если условие - истинно, то ассемблер выполняет условный блок до директивы endif. Если условие ложно, то ассемблер выполняет условный блок после else, а при его отсутствии вообще обходит условный блок.

 


Пример использования ifnb.

 

dos21 macro dosfunc, dxaddres

mov ah,dosfunc

ifnb <dxaddres>

mov dx,offset dxaddres

endif

entif

int 21h

endm

Команда для ввода символа с клавиатуры можно использовать макрокоманду:

dos21 01

Тогда макрорасширение будет:

mov ah,01

int 21h

Для ввода строки в dx необходимо занести адрес строки:

dos21 0ah,field

В результате

mov ah,0ah

mov dx,offset field

int 21h

 

Пример использования макроопределений.

 

Использование макроопределений делает ассемблерную программу легко читаемой. Предположим нам нужна процедура позволяющая определить является ли некоторый символ цифрой в ASCII-коде или нет. Символ передается в эту процедуру через al. Процедура должна возвратить значение true, если содержимое al находится в диапазоне 0...9 и false в обратном случае.

 

a_digit proc

cmp al,’0’

jb _false

cmp al,’9’

ja _false

clc

ret

_false: stc

ret

endp

Эта программа очень проста, однако команды cmp, jb и ja делают её непонятной с первого взгляда.

Используя соответствующее макроопределение эта процедура м.б. такой:

a_digit proc

if_al {,’0’ _false

if_al },’9’ _false

ret_true

_false: ret_false

endp

Это транслируется точно в такой же код:

ret_false macro

stc

ret

endm

ret_true macro

clc

ret

endm

Если необходимо написать:

if_al < 12, goto_label

С помощью макроопределения можно сделать так:

if_al {,12,_label

можно использовать:

{ - меньше

{= - меньше или равно

= - равно

{} - не равно

} - больше

}= - больше или равно

 

Обработчиков прерываний

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

При инициализации прикладного обработчика, сцепляемого с системным, следует сохранить адрес системного обработчика (или прикладного, который уже перехватил системный). Адрес запоминается в 2-х словной ячейке old-int. В вектор заносится адрес нового обработчика new-int. Если прикладная обработка д.б. после системной, то структура прикладного обработчика следующая:

 

Old_int DD?

.

.

.

new_int proc far

pushf

call cs:old_int; в систем. обр. с возвратом

.

.

; прикладная обработка

.

iret

new_int endp

 

 

Рассмотрим структуру стека при выполнении процедуры прерывания и вызове new_int

 

Это для iret системного обработчика IP2 От команды call cs:old_int
CS2
Флаги От pushf
Это для iret прикладного обработчика IP1 отновит. Адрес точки возврата в прерванный процесс
CS1 сегментный адрес прерванного процесса
Флаги  
     

 

 

Т.о. в результате команд pushf и call в стеке формируется трехсловная структура, необходимая команде iret – системного обработчика, чтобы вернуться в new_int. Команда call CS:old_int – формирует дальний вызов процедуры точно также как call dword PTR CS:[old_int] за счет того, что old_int объявлено двойным словом.

Если прикладная обработка должна вестить до системной, то структура обработчика должна иметь вид:

 

new_int proc far

; прикладная обработка

jmp CS:old_int;В системный обработчик без возврата

new_int endp

 

Команда jmp передает управление в системный обработчик (не затрагивая стек), который далее работает обычным образом.

Иногда прикладной обработчик должен выполнить некоторые действия до передачи упр. в системный, а некоторые после. В этом случае структура обработчика следующая:

 

new_int proc far

; прикладная обработка до системной

pushf

call cs:old_int; в системный обработчик с возвратом

; прикладная обработка после системной

iret

new_int endp

 

В некоторых случаях обработчик, получив управление, анализирует ситуацию и либо выполняет обработку сам, полностью исключив системный обработчик, либо отдает управление системному:

 

 

new_int proc far

; анализ ситуации

 

jmp cs:old_int; в системный обработчик с возвратом

; прикладная обработка, системная исключается

iret

new_int endp


Режимы дисплея

 

Номер Тип Макс. цветов Формат текста Макс. Страниц Нач. адрес
  Т   40х25   В8000
  Т   40х25   В8000
  Т   80х25   4 8 8 В8000
  Т   80х25 4 8 8 В8000
  Г   320х200 40х25   В8000
  Г   320х200 40х25   В8000
  Г   640х200 80х25   В8000
  Т Моно 80х25 1 8 В0000
  Г   160х200 20х25   В0000
  Г   320х200 40х25   В0000
А Г   640х200 80х25   В0000
D Г   320х100 40х25   А0000
Е Г   640х200 80х25  
F Г Моно 640х350 80х25  
  Г   640х350 80х25  

 

 

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

Информация флагов оборудования определяет какой из адресов буфера будет использовать видеопрограмма BIOS.

 

5 | 4 биты

40:10 01 - цв. 40х25

10 - цв. 80х25

11 – моно?

 

Для монохромных в ЕS загружается 0В000h, а для цветных ОВ800h – это позволяет остальным программам BIOS работать без информации о том, какой адаптер работает в системе. Все ссылки к буферу делаются ЕS.

В DOS практически нет для работы с цветным адаптером. Такие есть в BIOS. Все следующие функции запрашиваются посредством int 10h

 


Номер функции в АН Описание

00H уст. видео режим
01H уст. размер и форму курсора
02H уст. позицию курсора
03H читать позицию курсора
04H читать световое перо
05H выбрать активную страницу дисплея
06H листать окно вверх (или очистить)
07H листать окно вниз
08H читать символ/атрибут
09H писать символ/атрибут
0aH писать символ
0bH выбрать палитру/цвет бордюра
0cH писать графическую точку
0dH читать графическую точку
0eH писать символ в режиме TTY
0fH читать видео режим
10H EGA уст. палитру
11H EGA генератор символов
12H EGA специальные функции
13H писать строку (только AT + EGA)

 

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



Поделиться:


Последнее изменение этой страницы: 2017-02-07; просмотров: 617; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.118.0.240 (0.571 с.)