
- •Битовые операции Булевские команды
- •Команды сдвигов
- •Средства Ассемблера для битовых операций
- •Int 21h
- •Задание a5 Пример программы, включающей битовые операции Формулировка задания
- •Тексты программ
- •If not (ta eq TypeByte or ta eq TypeWord)
- •If pattern gt 111b
- •Выполнение задания на машине.
- •Inspecting treat_array
- •6356:0000 D5 75
- •6356:0002 80D5 00f5
Задание a5 Пример программы, включающей битовые операции Формулировка задания
Общее задание. Написать подпрограмму, обрабатывающую массив, и макрос для ее вызова. Подпрограмма обработки массива вызывает подпрограмму обработки элемента массива. В программе привести примеры вызова макроса. Программу, макрос и подпрограммы разместить в отдельных файлах.
В Turbo Debugger записать в файл протокола окна данных до и после выполнения программы. Записать туда же состояние стека в момент выполнения подпрограммы обработки элемента и интерпретировать его.
Отчет должен содержать:
1) распечатки файлов с программами и макросом,
2) распечатка окон с данными до и после выполнения программы,
3) окно стека с комментариями,
4) адрес подпрограммы обработки массива:
из листингов программ,
из карты памяти,
из отладчика.
5) размер кода и данных программы.
Задание. Дан массив слов (байтов) указанного размера. Над каждым элементом массива выполнить операцию: если битовое поле 6:4 совпадает с битовым полем 2:0 и с заданным образцом, то установить старший бит элемента, иначе — сбросить его.
Тексты программ
При выполнении задания вам придется как бы раздвоиться: на разработчика программы и ее пользователя. Разработчик пишет подпрограмму обработки массива и макрос, который дает возможность ее удобного использования. Пользователь пишет главную программу и испытывает подпрограмму на различных входных данных.
По условию задачи следует разместить программу и подпрограммы в разных файлах. Сначала напишем подпрограммы. Разместим их в файле sub6v0.asm. Сконструируем шаблон (рис.6.1) для слова и байта одновременно (можно, конечно, использовать и несколько шаблонов).
15 |
14 |
13 |
12 |
11 |
10 |
9 |
8 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
b15 |
d2 |
b7 |
f6_4 |
d1 |
f2_0 |
Рис.6.1.
Фактически для нас представляют интерес только интерес только поля f6_4 и f2_0, из которых берутся исходные данные, и поля b15 и b7, которые (возможно) претерпевают изменения. Но приходится вводить названия и для неиспользуемых полей d1 и d2, в соответствии с синтаксисом описания RECORD.
sub5v0.asm
JUMPS ; Оптимизация переходов
.286 ; Разрешены инструкции 286-го процессора
TypeByte EQU 1
TypeWord EQU 2
PUBLIC treat_array
.MODEL small
.CODE
;--------------------------------------------------------------------
; Подпрограмма обработки элемента массива
; Вход: AX(AL) — элемент массива
; BP — образец
; DX — тип элементов (1 - байты, 2 - слова)
; Выход: AX(AL) - измененный элемент массива
;--------------------------------------------------------------------
treat_elem PROC
template RECORD b15:1, d2:7, b7:1, f6_4:3, \
d1:1, f2_0:3
push ax bx ; Сохранить рабочие регистры
mov bx,ax ; Дублировать элемент в bx
and ax,MASK f6_4 ; Выделить битовое поле 6:4
shr ax,f6_4 ; Прижать его к правому краю
and bx,MASK f2_0 ; Выделить битовое поле 2:0
cmp ax,bx ; Сравнить битовые поля
jne clear ; Если не совпадают, сбросить старший бит
cmp ax,bp ; Сравнить битовое поле с образцом
jne clear ; Если не совпадают, сбросить старший бит
; Установка старшего бита
pop bx ax ; Восстановить регистры
cmp dx,TypeWord ; Если тип операнда слово –
je set_b15 ; на set_b15
or al, MASK b7 ; Иначе — установить старший бит байта
jmp ret_elem ; На выход
set_b15:
or ax, MASK b15 ; Установить старший бит слова
jmp ret_elem
; Сброс старшего бита
clear: pop bx ax
cmp dx, TypeWord
je clear_b15
and al, NOT MASK b7 ; Сбросить старший бит байта
jmp ret_elem
clear_b15:
and ax, NOT MASK b15 ; Сбросить старший бит слова
ret_elem:
ret
treat_elem ENDP
;-------------------------------------------------------------------
; Подпрограмма обработки массива
; Вход: SI — адрес массива
; CX — количество элементов
; BP — образец
; DX — тип элементов (1 - байты, 2 - слова)
; Выход: CF = 1, если входной массив пуст
; CF = 0, если входной массив непуст
; Результат: измененный массив
;-------------------------------------------------------------------
treat_array PROC
jcxz error ; Если массив нулевой длины — на error
m: mov ax,[si] ; Загрузить очередной элемент в AX (в AL)
call treat_elem ; Обработать элемент
mov [si],ax ; Вернуть элемент в массив
add si,dx ; Переместить указатель на следующий элемент
loop m
clc ; Нормальное завершение
ret
error: stc; Сообщение об ошибке, если массив пустой
ret
treat_array ENDP
END
Обратим внимание на следующие моменты.
1) Мы сообщаем компилятору директивой
PUBLIC treat_array
что treat_array — это глобальное имя, т.е. оно будет использоваться программами, расположенными в других файлах. Спецификатор PROCозначает, что это имя некоторой процедуры. Компилятор разместит это имя в таблице глобальных имен. Ей впоследствии воспользуется компоновщик.
2) Директива ENDне содержит метки стартового адреса, т.к. в файле нет главной программы — только подпрограммы.
3) Вместо того чтобы записывать команды
push ax
push bx
мы записываем эти команды одной строкой. Такую возможность предоставляет Turbo Assembler.
4) В начале каждой процедуры мы помещаем ее краткое описание и перечень входных и выходных параметров (если они есть). В нашем примере параметры передаются через регистры.
Файл с макросом для вызова подпрограммы treat_array.
macr5v0.inc
TypeByte EQU 1
TypeWord EQU 2
;---------------------------------------------------------------------
; Макрос вызова подпрограммы обработки массива
; array — имя массива
; len_of_array — количество элементов массива
; pattern — образец
; error_label — метка для перехода по ошибке
;---------------------------------------------------------------------
treat MACRO array, len_of_array, pattern, error_label
TA = TYPE array