могут выглядеть cледующим образом:
Данные: |123|035Excavators|038Lifters |049Presses | ...
| | | | | | |
Адрес: 00 03 06 16 19 29 32
Программа на рис.14.3 определяет таблицу STOKTAB, включая последний
элемент '999' для индикации конца таблицы при поиске. Программа поиска
сравнивает содержимое каждого элемента таблицы с содержимым поля STOKNIN:
Элемент таблицы STOKNIN Результат сравнения
035 123 Меньше: проверить след.эл-т
038 123 Меньше: проверить след.эл-т
049 123 Меньше: проверить след.эл-т
102 123 Меньше: проверить след.эл-т
123 123 Равно: элемент найден
Заметим, что команда CMPSB на рис.14.3 сравнивает байт за байтом,
пока байты не будут равны и автоматически увеличивает регистpы SI и DI.
Регистр CX инициализируется значением 03, а начальные относительные
адреса в регистрах SI и DI устанавливаются равными 03 и 00 соответственно.
Сравнение с первым элементом таблицы (035:123) завершается на первом
байте, после этого регистр SI содержит 04, DI: 01, CX: 02. Для следующего
сравнения регистр SI должен иметь значение 16, а DI: 00. Корректировка
регистра DI сводится к простой перезагрузке адреса STOKNIN. Увеличение
адреса следующего элемента таблицы, который должен быть в регистре SI,
зависит от того, на каком байте (первом, втором или третьем) закончилось
предыдущее сравнение. Регистр CX содержит число байт, не участвующих в
сравнении, в данном случае - 02. Прибавив к содержимому регистра SI
значение в регистре CX и длину наименования, получим относительный адрес
следующего элемента:
Адрес в SI после CMPSB 04
Прибавить CX 02
Прибавить длину наименования 10
--
Относительный адрес след.элемента 16
Так как регистр CX всегда содержит число байт, не участвующих в
сравнении (если такие есть), то расчет справедлив для всех случаев:
прекращение сравнения после 1, 2 или 3 байта. Если сравниваются одинаковые
элементы, то регистр CX получит значение 00, а адрес в pегистре SI укажет
на требуемое наименование.
__________________________________________________________________________
page 60,132
TITLE TABSRCH (COM) Табличный поиск, использующий CMPSB
CODESG SEGMENT PARA 'Code'
ASSUME CS:CODESG,DS:CODESG,ES:CODESG
ORG 100H
BEGIN: JMP SHORT MAIN
; ----------------------------------------------------
STOKNIN DW '123'
STOKTAB DB '035','Excavators' ;Начало таблицы
DB '038','Lifters '
DB '049','Presses '
DB '102','Valves '
DB '123','Processors'
DB '127','Pumps '
DB '999', 10 DUP(' ') ;Конец таблицы
DESCRN 10 DUP(?)
; ----------------------------------------------------
MAIN PROC NEAR
CLD
LEA SI,STOKTAB ;Начальный адрес таблицы
A20:
MOV CX,03 ;Сравнивать по 3 байта
LEA DI,STOKNIN ;Адрес искомого элемента
REPE CMPSB ;Сравнение
JE A30 ;Если равно - выйти,
JA A40 ;если больше - нет в таблице
ADD SI,CX ;Прибавить CX к адресу
JMP A20 ;Следующий элемент таблицы
A30:
MOV CX,05 ;Пересылать 5 слов
LEA DI,DESCRN ;Адрес описания
REP MOVSV ;Переслать из таблицы
RET
A40:
CALL R10ERR ;элемент в таблице не найден
RET
MAIN ENDP
R10ERR PROC
; <Вывод на экран сообщения об ошибке>
RET
R10ERR ENDP
CODESG ENDS
END BEGIN
__________________________________________________________________________
Рис.14.3. Табличный поиск с использованием команды CMPSB
Таблицы с элементами переменной длины
---------------------------------------
Существуют таблицы, в которых элементы имеют переменную длину. Каждый
элемент такой таблицы может завершаться специальным символом
ограничителем, например, шест.00; конец таблицы можно обозначить
огpаничителем шест.FF. В этом случае необходимо гарантировать, чтобы
внутри элементов таблицы не встречались указанные ограничители. Помните,
что двоичные числа могут выражаться любыми битовыми комбинациями. Для
поиска можно использовать команду SCAS.
ТРАНСЛИРУЮЩАЯ КОМАНДА XLAT
________________________________________________________________
Команда XLAT транслирует содержимое одного байта в другое
предопределенное значение. С помощью команды XLAT можно проверить
корректность содержимого элементов данных. При передаче данных между
персональным компьютером и ЕС ЭВМ (IBM) с помощью команды XLAT можно
выполнить перекодировку данных между форматами ASCII и EBCDIC.
В следующем примере происходит преобразование цифр от 0 до 9 из кода
ASCII в код EBCDIC. Так как представление цифр в ASCII выглядит как
шест.30-39, а в EBCDIC - шест.F0-F9, то замену можно выполнить командой
OR. Однако, дополнительно преобразуем все остальные коды ASCII в пробел
(шест.40) в коде EBCDIC. Для команды XLAT необходимо определить таблицу
перекодировки, которая учитывает все 256 возможных символов, с кодами
EBCDIC в ASCII позициях:
XLTBL DB 47 DUP(40H) ;Пробелы в коде EBCDIC
DB 0F0H,0F1H,0F2H,0F3H,...,0F9H ;0-9 (EBCDIC)
DB 199 DUP(40H) ;Пробелы в коде EBCDIC
Команда XLAT предполагает адрес таблицы в регистре BX, а транслируемый
байт (например, поля ASCNO) в регистре AL. Следующие команды выполняют
подготовку и трансляцию байта:
LEA BX,XLTBL
MOV AL,ASCNO
XLAT
Команда XLAT использует значение в регистре AL в качестве относительного
aдреса в таблице, т.е. складывает адрес в BX и смещение в AL. Если,
например, ASCNO содержит 00, то адрес байта в таблице будет XLTBL+00 и
команда XLAT заменит 00 на шест.40 из таблицы. Если поле ASCNO cодержит
шест.32, то адрес соответствующего байта в таблице будет XLTBL+50. Этот
байт содержит шест.F2 (2 в коде EBCDIC), который команда XLAT загружает в
регистр AL.
В программе на рис.14.4 добавлено преобразование десятичной точки
(2E) и знака минус (2D) из кода ASCII в код EBCDIC (4B и 60
соответственно). В программе организован цикл для обработки шестибайтового
поля. Поле ASCNO в начале выполнения программы содержит значение 31.5 с
последующим пробелом, или шест.2D33312E3520. В конце выполнения программы
в поле EBCNO должно быть шест.60F3F14BF540.
__________________________________________________________________________
page 60,132
TITLE XLATE (COM) Перевод кода ASCII в код EBCDIC
CODESG SEGMENT PARA 'Code'
ASSUME CS:CODESG,DS:CODESG,ES:CODESG
ORG 100H
BEGIN: JMP MAIN
; ----------------------------------------------------
ASCNO DB '-31.5'
EBCNO DB 6 DUP(' ')
XLTAB DB 45 DUP(40H)
DB 60H, 2DH
DB 5CH
DB 0F0H,0F1H,0F2H,0F3H,0F4H
DB 0F5H,0F6H,0F7H,0F8H,0F9H
DB 199 DUP(40H)
; ----------------------------------------------------
MAIN PROC NEAR ;Основная процедура
LEA SI,ASCNO ;Адрес символов ASCNO
LEA DI,EBCNO ;Адрес поля EBCNO
MOV CX,06 ;Длина
LEA BX,XLTAB ;Адрес таблицы
A20:
MOV AL,[SI] ;Получить ASCII символ
XLAT ;Перекодировка
MOV [DI],AL ;Записать в поле EBCNO
INC DI
INC SI
LOOP A20 ;Повторить 6 раз
RET
MAIN ENDP
CODESG ENDS
END BEGIN
__________________________________________________________________________
Рис.14.4. Преобразование ASCII в EBCDIC.
ПРОГРАММА: ОТОБРАЖЕНИЕ ШЕСТ. И ASCII-КОДОВ
________________________________________________________________
__________________________________________________________________________
page 60,132
TITLE ASCHEX (COM) Преобразование ASCII в шест.
CODESG SEGMENT PARA 'Code'
ASSUME CS:CODESG,DS:CODESG,ES:CODESG
ORG 100H
BEGIN: JMP MAIN
; -----------------------------------------------
DISPROW DB 16 DUP(' '), 13
HEXSTR DB 00
XLATAB DB 30H,31H,32H,33H,34H,35H,36H,37H,38H,39H
DB 41H,42H,43H,44H,45H,46H
; -----------------------------------------------
MAIN PROC NEAR ;Основная процедура
CALL Q10CLR ;Очистить экран
LEA SI,DISPROW
A20LOOP:
CALL C10HEX ;Перекодировать
CALL D10DISP ; и вывести на экран
CMP HEXCTR,0FFH ;Последнее значение (FF)?
JE A50 ; да - завершить
INC HEXCTR ; нет - перейти к следующему
JMP A20LOOP
A50: RET
MAIN ENDP
C10HEX PROC NEAR ;Перекодировка в шест.
MOV AH,00
MOV AL,HEXCTR ;Получить шест.пару
SHR AX,CL ;Сдвиг правой шест.цифры
LEA BX,XLATAB ;Установить адрес таблицы
MOV CL,04 ;Установить величину сдвига
XLAT ;Перекодировка в шест.
MOV [SI],AL ;Записать левый символ
MOV AL,HEXCTR
SHL AX,CL ;Сдвиг левой цифры
XLAT
MOV [SI]+1,AL ;Перекодировка в шест.
RET ;Записать правый символ
C10HEX ENDP
D10DISP PROC NEAR ;Вывод на экран
MOV AL,HEXCTR
MOV [SI]+3,AL
CMP AL,1AH ;Символ EOF?
JE D20 ; да - обойти
CMP AL,07H ;Меньше/равно 08?
JB D30 ; да - OK
CMP AL,10H ;Больше/равно 0F?
JAE D30 ; да - OK
D20:
MOV BYTE PTR [SI]+3,20H
D30:
ADD SI,05 ;Следующий элемент в строке
LEA DI,DISPROW+80
CMP DI,SI
JNE D40
MOV AH,40H ;Функция вывода на экран
MOV BX,01 ;Номер устройства
MOV CX,81 ;Вся строка
LEA DX,DISPROW
INT 21H
LEA SI,DISPROW ;Начальный адрес строки
D40: RET
D10DISP ENDP
Q10CLR PROC NEAR ;Очистка экрана
MOV AX,0600H
MOV BH,03 ;Цвет (07 для ч/б)
MOV CX,0000
MOV DX,184FH
INT 10H
RET
Q10CLR ENDP
CODESG ENDS
END BEGIN
__________________________________________________________________________
Рис.14.5. Отображение шест. и ASCII-кодов
Программа, приведенная на рис.14.5, отображает на экране почти все
ASCII-символы, а также их шест. значения. Например, ASCII-символ для
шест.53 - это буква S, эти данные программа выводит в виде 53 S. Полное
изображение на экране выглядит в виде матрицы 16х16:
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .