Сист. прогр. Ч1 (1085770), страница 10
Текст из файла (страница 10)
DS и ES: Адрес префикса программного сегмента - область в 256 (100Н) байт, которая предшествует выполняемому программному модулю в памяти.
CS: Адрес точки входа в программу (адрес первой выполняемой команды)-
IP: Нуль.
SS: Адрес сегмента стека.
SP: Относительный адрес, указывающий на вершину стека. Например, для стека в 32 слова (64 байт), определенного как
DW 32 DUP(7),
SP содержит 64, или 40Н.
При возврате из процедуры С10 команда RET извлекает 000В из стека (4В00 + 38), помещает его в указатель команд IP и увеличивает значение SP на 2. При этом происходит автоматический возврат по относительному адресу 000В в кодовом сегменте, т.е. в процедуру В10.
Команда RET в конце процедуры В10 извлекает адрес 0007 из стека (4В00 + ЗА), помещает его в IP и увеличивает значение SP на 2. При этом происходит автоматический возврат по относительному адресу 0007 в кодовом сегменте. Команда RET по адресу 0007 завершает выполнение программы, осуществляя возврат типа FAR.
7. ПРОГРАММА: РАСШИРЕННЫЕ ОПЕРАЦИИ ПЕРЕСЫЛКИ
В предыдущих программах были показаны команды пересылки непосредственных данных в регистр, пересылки данных из памяти в регистр, пересылки содержимого регистра в память и пересылки содержимого одного регистра в другой. Во всех случаях длина данных была ограничена одним или двумя байтами и не предусмотрена пересылка данных из одной области памяти непосредственно в другую область. В данном разделе объясняется процесс пересылки данных, которые имеют длину более двух байт. Далее будет показано использование операций над строками для пересылки данных из одной области памяти непосредственно в другую область.
page 65,132
TITLE MOVE (EXE) ;Расширенная пересылка
STACKSG SEGMENT PARA STACK 'Stack'
DW 32DUP(?)
STACKSG ENDS
DATASG SEGMENT PARA 'Data'
NAME1 DB 'ABCDEFGHI'
NAME2 DB ‘JKLMNOPQR'
NAHE3 DB 'STUVWXYZ*'
DATASG ENDS
CODESG SEGMENT PARA ‘Code’
BEGIN PROC FAR
ASSUME CS:CODESG, DS:DATASG, SS: STACKSG, ES:DATASG
PUSH DS
SUB AX, AX
PUSH AX
MOV AX, DATASG
MOV DS.AX
MOV ES.AX
CALL B10MOVE
CALL C10MOVE
RET
BEGIN ENDP
B10MOVE PROC
LEA SI, NAME1
LEA DI, NAME2
MOV CX , 09
B20:
MOV AL,[SI]
MOV [D1], AL
INC SI
INC DI
DEC CX
JNZ B20
RET
B10MOVE ENDP
LEA SI,NAME1
LEA DI,NAME2
MOV CX, 09
C20:
MOV AL,[SI]
MOV [DI], AL
INC DI
INC SI
LOOP C20
RET
C10MOVE ENDP
CQDESG ENDS
END BEGIN
Рис.7.1
Процедура С10MOVE аналогична процедуре В10MOVE с двумя исключениями: она пересылает данные из поля NAME2 в none NAME3 и использует команду LOOP вместо DEC и JNZ.
Обратите внимание на изменения в регистрах, командном указателе и стеке. Для просмотра изменений и полях NAME2 и NAME3 используйте команду D DS:0.
КОМАНДЫ ЛОГИЧЕСКИХ ОПЕРАЦИЙ: OR, XOR, TEST, NOT
Логические операции являются важным элементом в проектировании микросхем и имеют много общего с логикой программирования. Команды AND, OR, XOR и TEST являются командами логических операций. Эти команды используются для сброса и установки битов и для арифметических операций в коде ASCII . Все эти команды обрабатывают один байт или одно слово в регистре или в памяти и устанавливают флаги CF, OF, PF, SF, ZF. (Флаг AF не определен.)
XOR: Если один из сравниваемых битов равен 0, а другой равен 1, то результат равен 1; если сравниваемые биты одинаковы (оба - 0 или оба - 1), то результат - 0.
TEST: действует как AND - устанавливает флаги, но не изменяет биты.
ПРОГРАММА: ЗАМЕНА СТРОЧНЫХ БУКВ НА ЗАГЛАВНЫЕ
Существуют различные причины для преобразований между строчными и заглавными буквами. Например, вы могли получить файл данных, созданный на компьютере, который работает только с заглавными буквами. Или некая программа должна позволить пользователям вводить команды как заглавными, так и строчными буквами (например, YES или yes) и преобразовать их в заглавные для проверки. Заглавные буквы от А до Z имеют коды от 41Н до 5АН, а строчные буквы от а до z имеют коды от 61Н до 7АН. Единственная разница в том, что пятый бит равен 0 для заглавных букв и 1 для строчных:
TITLE CASE (COM)
0000 CODESG SEGMENT PARA ‘CODE’
ASSUME CS:CODESG,DS:CODESG,SS:CODESG
0001 ORG 100H
0001 ЕВ 1C 90 BEGIN: JMP MAIN
0003 43 68 61 бE 67 65 TITLEX DB 'Change to uppercase letters'
20 74 6F 20 75 70
70 65 72 63 61 73
65 20 BС 65 74 74
65 72 73
011Е main proc near
011Е 8D 1E 0104 R LEA BX,TITLEX+1
0122 В9 001F MOV CX,31
0125 B20:
0125 8A 27 MOV AH,[BX]
0127 80 FC 61 CMP AH,61H
012А 72 0А JB B30
012C 80 FC 7A CMP AH,7AH ; буква
012F 77 05 JA B30 ; ?
0131 80 Е4 DF AND AH,llOlll1B ;Да - Преобразовать
0134 88 27 MOV [BX],AH ;3аписать в TITLEX
0136 B30:
0136 43 INC BX ; Следующий символ
0137 Е2 ЕС LOOP В20 ; Повторить цикл 31 раз
0139 СЗ RET
013А MAIN ENDP
013А CODESG ENDS
END BEGIN
Рис.7.2. Замена строчных букв на прописные
Биты: 76543210 Биты: 76543210
Буква А: Буква а:
01000001 01100001
СОМ-програма, приведенная на рис.7.2, преобразует данные в поле TITLEX из строчных букв в прописные начиная с адреса TITLEX + 1. Программа инициализирует регистр ВХ адресом TITLEX + 1 и использует его для пересылки символов в регистр АН начиная с TITLEX + 1. Если полученное значение лежит в пределах от 61Н и до 7АН, то команда AND устанавливает бит 5 в 0:
AND АН,11011111В
Все символы, отличные от строчных букв (от а до z), не изменяются. Измененные символы засылаются обратно в область TITLEX, значение в регистре ВХ увеличивается для очередного символа и осуществляется переход на следующий цикл.
Используемый таким образом регистр ВХ действует как индексный регистр для адресации в памяти. Для этих целей можно использовать также регистры SI и DI.
КОМАНДЫ СДВИГА И ЦИКЛИЧЕСКОГО СДВИГА
Команды сдвига и циклического сдвига, представляющие собой часть логических возможностей компьютера, обладают следующими свойствами:
- обрабатывают байт или слово;
- имеют доступ к регистру или к памяти;
- сдвигают влево или вправо;
- сдвигают на величину до 8 бит (для байта) и 16 бит (для
слова); - сдвигают логически (без знака) или арифметически (со знаком).
Значение сдвига на 1 может быть закодировано как непосредственный операнд; значение больше 1 должно находиться в регистре CL.
Команды сдвига
При выполнении команд сдвига флаг CF всегда содержит значение последнего выдвинутого бита. Существуют следующие команды сдвига:
SHR Логический (беззнаковый) сдвиг вправо
SHL Логический (беззнаковый) сдвиг влево
SAR Арифметический сдвиг вправо
SAL ;Арифметический сдвиг влево
Следующий фрагмент иллюстрирует выполнение команды
SHR:
MOV СL, 03 ;АХ:
MOV АХ,10110111В ;10110111
SHR AX,1 ;01011011 ;Сдвиг вправо на 1
SHR AX,CL ;00001011 ;Сдвиг вправо на 3
Первая команда SHR сдвигает содержимое регистра АХ вправо на 1 бит. Выдвинутый в результате один бит попадает в флаг CF, a самый левый бит регистра АХ заполняется нулем. Вторая команда сдвигает содержимое регистра АХ еще на три бита. При этом флаг CF последовательно принимает значения 1, 1, 0, а в три левых бита в регистре АХ заносятся нули.
Рассмотрим действие команд арифметического сдвига вправо SAR:
MOV CL,03
MOV АХ,10110111В
SAR АХ,1 ; 11011011 ;Сдвиг вправо на 1
SAR AX,CL ; 11111011 ;Сдвиг вправо на 3
SAR имеет важное отличие от команды SHR: для заполнения левого бита используется знаковый бит. Таким образом, положительные и отрицательные величины сохраняют свой знак. В приведенном примере знаковый бит содержит единицу.
При сдвигах влево правые биты заполняются нулями. Таким образом, результат команд сдвига SHL и SAL идентичен.
Сдвиг влево часто применяется для удваивания чисел, а сдвиг вправо - для деления на 2. Эти операции выполняются значительно быстрее, чем команды умножения или деления. Деление пополам нечетных чисел (например, 5 или 7) образует меньшие значения (2 или 3 соответственно) и устанавливает флаг CF в 1. Кроме того, если необходимо выполнить сдвиг на 2 бит, то использование двух команд сдвига более эффективно, чем использование одной команды с загрузкой регистра CL значением 2.
Для проверки бита, занесенного в флаг CF, используется команда JC (переход, если есть перенос).
Команды циклического сдвига
Циклический сдвиг представляет собой операцию сдвига, при которой выдвинутый бит занимает освободившийся разряд. Существуют следующие команды циклического сдвига:
ROR Циклический сдвиг вправо
ROL Циклический сдвиг влево
RCR Циклический сдвиг вправо с переносом
RCL Циклический сдвиг влево с переносом
Следующий порядок команд иллюстрирует операцию циклического сдвига ROR.
MOV CL,03
MOV BX,1011011
MOV BX,1 ; 11011011
MOV BX, CL ; 011111011
Первая команда ROR при выполнении циклического сдвига переносит правый единичный бит регистра ВХ в освободившуюся левую позицию. Вторая команда ROR переносит таким образом три правых бита.
В командах RCR и RCL в сдвиге участвует флаг CF. Выдвигаемый из регистра бит заносится в флаг CF, а значение CF при этом поступает в освободившуюся позицию.
Рассмотрим пример, в котором используются команды циклического и простого сдвига. Предположим, что 32-битовое значение находится в регистровой паре DX:AX так, что левые 16 бит лежат в регистре DX, а правые - в АХ. Для умножения на 2 этого значения возможны следующие две команды:
SHL АХ,1 ;Умножение пары регистров
RCL DX,1 ; DХ:АХ на 2
Здесь команда SHL сдвигает все биты регистра АХ влево, причем самый левый бит попадает в флаг CF. Затем команда RCL сдвигает все биты регистра DX влево и в освободившийся правый бит заносит значение из флага CF.
ОРГАНИЗАЦИЯ ПРОГРАММ
Ниже даны основные рекомендации для написания ассемблерных программ:
1. Четко представляйте себе задачу, которую должна решить программа.
2. Сделайте эскиз задачи в общих чертах и спланируйте общую логику программы. Например, если необходимо проверить операции пересылки нескольких байтов, начните с определения полей с пересылаемыми данными. Затем спланируйте общую стратегию для инициализации, условных переходов и команд LOOP. Приведем основную логику, которую используют многие программисты в таком случае: инициализация стека и сегментных регистров вызов подпрограммы JMP-цикла вызов подпрограммы LOOP-цикла возврат
Подпрограмма JMP-цикла может быть спланирована следующим образом: инициализация регистров значениями адресов
и числом циклов. Метка: пересылка одного байта увеличение адресов на 1 уменьшение счетчика на 1: если счетчик не 0, то идти на метку если ноль, возврат аналогичным образом может быть организована подпрограмма LOOP-цикла.
3. Представьте программу в виде логических блоков, следующих Друг за другом. Процедуры, не превышающие 25 строк (размер экрана), удобнее для отладки.
4. Пользуйтесь тестовыми примерами программ. Попытки запомнить все технические детали и программирование сложных программ "из головы" часто приводят к многочисленным ошибкам.
5. Используйте комментарии для описания того, что должна делать процедура, какие арифметические действия или операции сравнения будут выполняться и что делают редко используемые команды. (Например, команда XLAT, не имеющая операндов).
6. Дня кодирования программы используйте заготовку программы, скопированной в файл с новым именем.
В следующих программах данной книги важным является использование команды LEA, индексных регистров SI и DI, вызываемых процедур. Получив базовые знания по языку Ассемблер, можно перейти к более развитому и полезному программированию.
ОСНОВНЫЕ ПОЛОЖЕНИЯ НА ПАМЯТЬ
Метки процедур (например, B20:) должны завершаться двоеточием для указания типа NEAR. Отсутствие двоеточия приводит к ассемблерной ошибке.
Метки для команд условного перехода и LOOP должны лежать в границах от -128 до +127 байт. Операнд таких команд генерирует один байт объектного кода. Шестнадцатеричные значения от 01 до 7F соответствуют десятичным от +1 до + 127, а шестнадцатеричные значения от FF до 80 соответствуют десятичным значениям от -1 до -128. Так как длина машинной команды может быть от 1 до 4 байт, то соблюдать границы не просто. Практически можно ориентироваться на размер в два экрана исходного текста (примерно 50 строк).