2.1. Трансляция, компоновка и отладка программ
1.Набрать приведенную в тексте программу на ассемблере с использованием редактора текста.
2. Оттранслировать программу в объектный код.
Трансляция выполнялась макроассемблером MASM.EXE, для чего в командной строке она вызывалась с параметром – ассемблируемой программой EXAM.ASM:
3. Скомпоновать программу (получить исполнимый файл). Изучить листинг программы.
Компоновка выполнялась компоновщиком LINK.EXE, для чего в командной строке она вызывалась с параметром – объектный модуль EXAM.OBJ:
4. Провести отладку программы и проверить получаемые результаты.
Запуск отладчика TD.EXE c отлаживаемой программой EXAM.EXE, выполнялся из командной строки:
После запуска открылось окно отладчика:
5. Внести в программу следующие изменения: задать исходную таблицу SOURCE из 5 двухбайтовых шестнадцатеричных переменных и скопировать эту новую таблицу в DEST.
В результате выполнения данного задания получена следующая программа на Ассемблере:
TITLE Prac011
PAGE ,132
STACK SEGMENT PARA STACK 'STACK'
DB 64 DUP('STACK') ; Область стека
STACK ENDS
DSEG SEGMENT PARA PUBLIC 'DATA'
SOURCE DW 0AAAAh,0BBBBh,0CCCCh,0DDDDh,0EEEEh ; эта таблица будет скопирована
DEST DW 5 DUP(?) ; в эту таблицу в обратном порядке
DSEG ENDS
SUBTTL ОСНОВНАЯ ПРОГРАММА
PAGE
CSEG SEGMENT PARA PUBLIC 'CODE'
ASSUME CS:CSEG, DS:DSEG, SS:STACK
OUR_PROG PROC FAR
; занести в стек такие начальные значения, чтобы программа
; могла возвратить управление отладчику
PUSH DS ; поместить в стек номер блока адреса возврата
SUB AX,AX ; обнулить регистр АХ, тоже можно сделать командой MOV AX,0
PUSH AX ; поместить в стек значение адреса возврата=0
; инициировать адрес сегмента данных
MOV AX,DSEG
MOV DS,AX
; присвоить элементам таблицы DEST нулевые начальные значения
MOV DEST,00000h ; обнуление 1-ого байта
MOV DEST+2,00000h ; обнуление 2-ого байта
MOV DEST+4,00000h ; обнуление 3-его байта
MOV DEST+6,00000h ; обнуление 4-ого байта
MOV DEST+8,00000h ; обнуление 5-ого байта
; скопировать таблицу SOURCE в таблицу DEST в обратном порядке,
; в качестве промежуточной ячейки пересылки использовать регистр AL
MOV AX, SOURCE
MOV DEST+8,AX
MOV AX, SOURCE+2
MOV DEST+6,AX
MOV AX, SOURCE+4
MOV DEST+4,AX
MOV AX, SOURCE+6
MOV DEST+2,AX
MOV AX, SOURCE+8
MOV DEST,AX
RET ; возврат управления отладчику
OUR_PROG ENDP
CSEG ENDS
END OUR_PROG
6. В сегменте данных определить переменные, заполнив их следующими значениями:
- 5 байтов A, B, C, D, E;
- 5 двухбайтовых слов AA, BB, CC, DD, EE;
- 5 двойных слов AAAA, BBBB, CCCC, DDDD, EEEE;
В результате выполнения данного задания получен следующий программный код описания сегменты данных:
DSEG SEGMENT PARA PUBLIC 'DATA'
VAR1 DB 0Ah,0Bh,0Ch,0Dh,0Eh
VAR2 DW 0AAh,0BBh,0CCh,0DDh,0EEh
VAR3 DD 0AAAAh,0BBBBh,0CCCCh,0DDDDh,0EEEEh
DSEG ENDS
7. Получить исполнимый файл программы с данными пункта 6 и изучить дамп памяти данных с целью уяснения механизма выравнивания.
После ассемблирования и компоновки программы получили исполняемую программу. Затем открыли ее в отладчике.
Изучив дамп памяти сегмента данных можно сделать вывод, что в памяти старший байт следует за младшим, а не предшествует ему, что объясняется тем, что в памяти ЭВМ старшая часть располагается в ячейках памяти со старшими адресами
Рисунок 2.6. Дамп памяти полученной программы в отладчике TD.EXE
1. Изучить приведенный теоретический материал к лабораторной работе.
2. Используя прямую (первый вариант) и косвенную (второй вариант) адресацию, написать программы на ассемблере, выполняющие следующие алгоритмы преобразований:
Задать одномерный массив, состоящий из 8 элементов. Заполнить массив константами. Переместить заданный массив в другую область памяти, поменяв местами элементы с четными и нечетными номерами (поставив каждый элемент с четным номером на место нечетного элемента и каждый элемент с нечетным номером – на место четного). Элементы массива – однобайтовые.
Примечания к кодированию программ:
- программа с использованием прямой адресации будет похожа на приведенную в предыдущей лабораторной работе программу, только непосредственные значения смещений в командах должны измениться в соответствии с заданным алгоритмом;
- для варианта косвенной адресации зашлите адреса начала массивов в базовый и индексный регистры, например командами:
MOV BX, OFFSET SOURCE
и
MOV DI, OFFSET DEST
и далее используйте регистры BX и DI для адресации элементов массивов.
Текст программы:
TITLE Prac021
PAGE ,132
STACK SEGMENT PARA STACK 'STACK'
DB 64 DUP('STACK') ; Область стека
STACK ENDS
DSEG SEGMENT PARA PUBLIC 'DATA'
SOURCE DB 8 DUP(?) ; исходный массив
DEST DB 8 DUP(?) ; полученный массив
DSEG ENDS
SUBTTL ОСНОВНАЯ ПРОГРАММА
PAGE
CSEG SEGMENT PARA PUBLIC 'CODE'
ASSUME CS:CSEG, DS:DSEG, SS:STACK
OUR_PROG PROC FAR
; занести в стек такие начальные значения, чтобы программа
; могла возвратить управление отладчику
PUSH DS ; поместить в стек номер блока адреса возврата
SUB AX,AX ; обнулить регистр АХ, тоже можно сделать командой MOV AX,0
PUSH AX ; поместить в стек значение адреса возврата=0
; инициировать адрес сегмента данных
MOV AX,DSEG
MOV DS,AX
; Заполнить массив константами.
MOV SOURCE,011h ; 1 элемент
MOV SOURCE+1,022h ; 2 элемент
MOV SOURCE+2,033h ; 3 элемент
MOV SOURCE+3,044h ; 4 элемент
MOV SOURCE+4,055h ; 5 элемент
MOV SOURCE+5,066h ; 6 элемент
MOV SOURCE+6,077h ; 7 элемент
MOV SOURCE+7,088h ; 8 элемент
; Переместить заданный массив в другую область памяти,
; поменяв местами элементы с четными и нечетными номерами
; в качестве промежуточной ячейки пересылки использовать регистр AL
MOV AL, SOURCE
MOV DEST+1,AL
MOV AL, SOURCE+1
MOV DEST,AL
MOV AL, SOURCE+2
MOV DEST+3,AL
MOV AL, SOURCE+3
MOV DEST+2,AL
MOV AL, SOURCE+4
MOV DEST+5,AL
MOV AL, SOURCE+5
MOV DEST+4,AL
MOV AL, SOURCE+6
MOV DEST+7,AL
MOV AL, SOURCE+7
MOV DEST+6,AL
RET ; возврат управления отладчику db
OUR_PROG ENDP
CSEG ENDS
END OUR_PROG
3. Оттранслировать программу в объектный код.
4. Провести отладку программы и проверить получаемые результаты.
2.3. Программирование ветвлений и циклов
1. Изучить приведенный теоретический материал к лабораторной работе.
2. Написать программы:
1) Подсчитать количество нулевых, положительных и отрицательных элементов вектора (одномерного массива), состоящего из однобайтовых чисел.
Описания переменных в сегменте данных могут быть следующими:
Mas DB -1, 0, 3,-8,0,9,-6,1,2,-5 ; заданный вектор
Len_mas = $-mas ; количество элементов в векторе
Sch_0 DB 0 ; счетчик нулевых элементов вектора
Sch_pol DB 0 ; счетчик положительных элементов вектора
Sch_otr DB 0 ; счетчик отрицательных элементов вектора
Фрагмент сегмента кода для подсчета элементов может быть следующим:
MOV CX, Len_mas ; инициализация счетчика цикла
XOR SI,SI ; инициализация индексного регистра
Cycl: CMP Mas[SI],0 ; сравниваем элемент вектора с 0
JZ Zero ; нуль-элементы считаем в блоке zero
JG Pol ; элементы>0 считаем в блоке pol
INC Sch_otr ; увеличиваем счетчик элементов <0
JMP Kon_cycl
Zero: INC Sch_0 ; увеличиваем счетчик нулевых элементов
JMP Kon_cycl
Pol: INC Sch_pol ; увеличиваем счетчик элементов >0
Kon_cycl: INC SI ; переходим к следующему элементу вектора
LOOP Cycl ; завершаем цикл.
Код программы:
; Подсчитать количество нулевых, положительных и
; отрицательных элементов вектора (одномерного массива),
; состоящего из однобайтовых чисел.
STACK SEGMENT PARA STACK 'STACK'
DB 64 DUP('STACK') ; Область стека
STACK ENDS
DSEG SEGMENT PARA PUBLIC 'DATA'
Mas DB -1,0,3,-8,0,9,-6,1,2,-5 ; заданный вектор
Len_mas =$-Mas ; количество элементов в векторе
Sch_0 DB 0 ; счетчик нулевых элементов вектора
Sch_pol DB 0 ; счетчик положительных элементов вектора
Sch_otr DB 0 ; счетчик отрицательных элементов вектора
DSEG ENDS
CSEG SEGMENT PARA PUBLIC 'CODE'
ASSUME CS:CSEG, DS:DSEG, SS:STACK
START: PUSH DS
SUB AX,AX
PUSH AX
MOV AX,DSEG ; инициировать адрес сегмента данных
MOV DS,AX
; Подсчет количества 0,+,- элементов
MOV CX, Len_mas ; инициализация счетчика цикла
XOR SI,SI ; инициализация индексного регистра
Cycl: Cmp Mas[SI],0 ; сравниваем элемент вектора с 0
JZ Zero ; нуль-элементы считаем в блоке zero
JG Pol ; элементы>0 считаем в блоке pol
INC Sch_otr ; увеличиваем счетчик элементов <0
JMP Kon_cycl
Zero: INC Sch_0 ; увеличиваем счетчик нулевых элементов
JMP Kon_cycl
Pol: INC Sch_pol ; увеличиваем счетчик элементов >0
Kon_cycl: Inc SI ; переходим к следующему элементу вектора
LOOP Cycl ; завершаем цикл.
EXIT: MOV AX,4C00h
INT 21h ; возврат управления операционной системе
CSEG ENDS
END START
2) Определить, сколько цифровых и нецифровых символов присутствует в заданной символьной строке.
Примечание к кодированию задания: при написании алгоритмов преобразований необходимо использовать таблицу кодов ASCII (0 – код 48 … 9 – код 57).
Описания строки в сегменте данных могут быть следующим:
DSEG SEGMENT PARA PUBLIC 'DATA'
Str DB '0a1s2s3e4m5b6l7e8r9' ; заданная строка
...
Код программы:
; Определить, сколько цифровых и нецифровых символов
; присутствует в заданной символьной строке.
STACK SEGMENT PARA STACK 'STACK'
DB 64 DUP('STACK') ; Область стека
STACK ENDS
DSEG SEGMENT PARA PUBLIC 'DATA'
Mas DB '0a1s2s3e4m5b6l7e8r9' ; заданная строка
Leng =$-mas ; количество элементов в строке
K123 DB 0 ; счетчик цифр
Kabc DB 0 ; счетчик не цифр
DSEG ENDS
CSEG SEGMENT PARA PUBLIC 'CODE'
ASSUME CS:CSEG, DS:DSEG, SS:STACK
START: PUSH DS
SUB AX,AX
PUSH AX
MOV AX,DSEG ; инициировать адрес сегмента данных
MOV DS,AX
; Подсчет количества цифр строки
MOV CX, Leng ; инициализация счетчика цикла
XOR SI,SI ; инициализация индексного регистра
Cycl: Cmp Mas[SI],48 ; сравниваем элемент вектора с 0
JL Next ; код < 48 - то есть < 0
Cmp Mas[SI],57 ; сравниваем элемент вектора с 0
JG Next ; код > 57 - то есть > 9
INC K123 ; считаем цифры
JMP Kon_cycl
Next: INC Kabc ; считаем не цифры
Kon_cycl: INC SI ; переходим к следующему элементу строки
LOOP Cycl ; завершаем цикл.
EXIT: MOV AX,4C00h
INT 21h ; возврат управления операционной системе
CSEG ENDS
END START
3) Подсчитать количество нулевых, положительных и отрицательных элементов в заданном двумерном массиве. Элементы двумерного массива однобайтовые.
Примечание к кодированию: в программе необходимо реализовать такую конструкцию, как “вложенные циклы”. Кроме того, понятие массива и индексации массива весьма условны, ибо в памяти ЭВМ элементы массива располагаются последовательно, строка за строкой, в результате чего физическая структура двумерного массива и вектора (одномерного массива) оказываются одинаковыми. Отличие двумерного массива и вектора заключается в интерпретации области памяти, отведенной этим структурам. Наращивание индекса элемента структуры определяется алгоритмом обработки.
Код программы:
; Подсчитать количество нулевых, положительных и
; отрицательных элементов в заданном двумерном массиве.
; Элементы двумерного массива однобайтовые.
STACK SEGMENT PARA STACK 'STACK'
DB 64 DUP('STACK') ; Область стека
STACK ENDS
DSEG SEGMENT PARA PUBLIC 'DATA'
Kzer DB 0 ; количество нулевых
Kotr DB 0 ; количество отрицательных
Kpol DB 0 ; количество положительных
Mas DB 1,0,-9,8,0,7,8,0,-2,0 ; это заданный двумерный массив байт
DB -1,0,9,8,6,7,-8,0,-5,4
DB 0,-1,9,8,0,7,-8,0,2,0
DB 1,2,-9,8,0,-7,8,0,2,3
DB 8,0,0,-9,8,0,0,8,0,-2
Len_mas EQU 10 ; количество элементов в строке
DSEG ENDS
CSEG SEGMENT PARA PUBLIC 'CODE'
ASSUME CS:CSEG, DS:DSEG, SS:STACK
START: PUSH DS
SUB AX,AX
PUSH AX
MOV AX,DSEG ; инициировать адрес сегмента данных
MOV DS,AX
XOR AX,AX
MOV CX,5 ; число строк массива
LEA BX,Mas ; смещение начала массива занести в ВХ
Cyc1: PUSH CX ; сохранить в стеке текущее значение счетчика строк
XOR SI,SI ; начать обработку очередной строки
MOV CX,Len_mas ; счетчик элементов строки
Cyc2: CMP BYTE PTR [BX+SI],0 ; очередной элемент 0
JZ Zero ; нуль-элементы считаем в блоке zero
JG Pol ; элементы > 0 считаем в блоке pol
INC Kotr ; подсчитали отрицательный
JMP Cyce
Zero: INC Kzer ; подсчитали нулевой
JMP Cyce
Pol: INC Kpol ; подсчитали положительный
Cyce: INC SI
LOOP Cyc2
POP CX ; восстановить счетчик внешнего цикла (номера строки)
ADD BX,Len_mas ; перейти к следующей строке
LOOP Cyc1
EXIT: MOV AX, 4C00H
INT 21H ; возврат управления операционной системе
CSEG ENDS
END START
3. Оттранслировать программы в объектный код.
4. Провести отладку программ и проверить получаемые результаты. Для отладки и проверки программ использовать эмулятор микропроцессора 8086 (8086 microprocessor emulator) (Soft\emu8086v408\).
2.4. Арифметические операции целочисленной обработки информации
1. Изучить приведенный теоретический материал к лабораторной работе.
2. Написать программы на ассемблере:
1) Подсчитать количество четных элементов двухмерного массива. Элементы массива однобайтовые.
В контексте определения четности-нечетности могут быть использованы различные команды ассемблера:
- команда логического умножения (конъюнкции). При этом учитывается то обстоятельство, что четные положительные числа имеют значение младшего двоичного разряда равное 0, а нечетные – 1. То есть, если результат выполнения команд
MOV AL, Mas[SI]
AND AL, 1B
равен 0, то число четное, иначе – нечетное;
- команда арифметического сдвига вправо – SHR на одну позицию. При этом число уменьшается в 2 раза, а младший разряд числа выталкивается во флаг переноса CF. Далее значение флага анализируется командой JC (переход, если есть перенос) или JNC (переход, если нет переноса);
- команда деления DIV или IDIV, например:
MOV AL, mas[SI] ; если исходные элементы однобайтовые
CBW ; преобразуем байт в полное слово
;если исходные элементы – двухбайтовые слова, то вместо предыдущих команд записываем команду MOV AХ, Mas[SI]
DIV BYTE PTR c ; константа с объявлена в сегменте данных как c EQU 2
Следует отметить, что такая реализация обнаружения четности-нечетности самая неудачная, потому что операция деления относится к “длинным” операциям и занимает значительно больше процессорного времени, чем предыдущие команды. Кроме того, необходимо учитывать наличие или отсутствие знака у элементов массива. Приведенный пример предполагает, что элементы массива – беззнаковые.
Для отрицательных целых чисел признаки четности-нечетности будут иными.
Код программы:
; Подсчитать количество четных элементов двухмерного массива.
; Элементы массива однобайтовые.
STACK SEGMENT PARA STACK 'STACK'
DB 64 DUP('STACK') ; Область стека
STACK ENDS
DSEG SEGMENT PARA PUBLIC 'DATA'
Mas DB 1,3,5,7,9,11,13,15,17,19 ; это заданный двумерный массив байт
DB 18,16,14,12,10,8,6,4,2,0
DB 0,1,2,3,4,5,6,7,8,9
DB 0,2,4,6,8,10,12,14,16,18
DB 19,17,15,13,11,9,7,5,3,1
Len_mas EQU 10 ; количество элементов в строке
Chet DB 0 ; количество четных
Nech DB 0 ; количество нечетных
DSEG ENDS
CSEG SEGMENT PARA PUBLIC 'CODE'
ASSUME CS:CSEG, DS:DSEG, SS:STACK
START: PUSH DS
SUB AX,AX
PUSH AX
MOV AX,DSEG ; инициировать адрес сегмента данных
MOV DS,AX
XOR AX,AX
MOV CX,5 ; число строк массива
LEA BX,Mas ; смещение начала массива занести в ВХ
Cyc1: PUSH CX ; сохранить в стеке текущее значение счетчика строк
XOR SI,SI ; начать обработку очередной строки
MOV CX,Len_mas ; счетчик элементов строки
Cyc2: MOV AL, Mas[BX+SI] ; очередной элемент в AL
AND AL, 1B ; логическое умножение на 1
CMP AL,0 ; результат 0 - четный
JNE Net ; если не 0 - нечетный
INC Chet ; считаем четный
JMP Konc
Net: INC Nech ; считаем не четный
Konc: INC SI ; перейти к следующему элементу строки
LOOP Cyc2
POP CX ; восстановить счетчик внешнего цикла (номера строки)
ADD BX,Len_mas ; перейти к следующей строке
LOOP Cyc1
EXIT: MOV AX, 4C00H
INT 21H ; возврат управления операционной системе
CSEG ENDS
END START
2) Подсчитать суммы положительных и отрицательных элементов вектора. Элементы массива двухбайтовые.
Код программы:
; Подсчитать суммы положительных и отрицательных элементов вектора.
; Элементы массива двухбайтовые.
STACK SEGMENT PARA STACK 'STACK'
DB 64 DUP('STACK') ; Область стека
STACK ENDS
DSEG SEGMENT PARA PUBLIC 'DATA'
Mas DW -1,0,3,-8,0,9,-6,1,2,-5 ; заданный вектор
Len_mas EQU 10 ; количество элементов в векторе
SPol DW 0 ; сумма положительных элементов вектора
SOtr DW 0 ; сумма отрицательных элементов вектора
DSEG ENDS
CSEG SEGMENT PARA PUBLIC 'CODE'
ASSUME CS:CSEG, DS:DSEG, SS:STACK
START: PUSH DS
SUB AX,AX
PUSH AX
MOV AX,DSEG ; инициировать адрес сегмента данных
MOV DS,AX
; Подсчет суммы + и - элементов
MOV AX,0
MOV BX,0
MOV CX, Len_mas ; инициализация счетчика цикла
XOR SI,SI ; инициализация индексного регистра
Cycl: Cmp Mas[SI],0 ; сравниваем элемент вектора с 0
JZ Kon_cycl ; нуль-элементы не учитываем
JG Pol ; элементы > 0 считаем в блоке pol
ADD AX, Mas[SI] ; суммируем < 0
JMP Kon_cycl
Pol: ADD BX, Mas[SI] ; суммируем > 0
Kon_cycl: ADD SI,2 ; переходим к следующему элементу вектора
LOOP Cycl ; завершаем цикл.
MOV SPol,BX
MOV SOtr,AX
EXIT: MOV AX,4C00h
INT 21h ; возврат управления операционной системе
CSEG ENDS
END START
3) Подсчитать сумму всех элементов двухмерного массива и найти медиану (среднее арифметическое). Элементы массива положительные однобайтовые.
Примечание к кодированию: Понятие массива и индексации массива весьма условны, ибо в памяти ЭВМ элементы массива располагаются последовательно, строка за строкой. Поэтому физическая структура двумерного массива и вектора (одномерного массива) оказываются одинаковыми. Отличие двумерного массива и вектора заключается в интерпретации области памяти, отведенной этим структурам. Наращивание индекса элемента структуры определяется алгоритмом обработки структуры данных).
Код программы:
; Подсчитать сумму всех элементов двухмерного массива и
; найти медиану (среднее арифметическое).
; Элементы массива положительные однобайтовые.
STACK SEGMENT PARA STACK 'STACK'
DB 64 DUP('STACK') ; Область стека
STACK ENDS
DSEG SEGMENT PARA PUBLIC 'DATA'
Mas DB 1,2,3,4,5,6,7,8,9,10 ; это заданный двумерный массив байт
DB 10,9,8,7,6,5,4,3,2,1
DB 1,2,3,4,5,6,7,8,9,10
DB 10,9,8,7,6,5,4,3,2,1
DB 1,2,3,4,5,6,7,8,9,10
Len_s EQU 10 ; количество элементов в строке
Len_m DB 50 ; количество элементов в массиве
Summ DW 0 ; сумма
Sred DB 0 ; среднее
Osta DB 0 ; остаток
DSEG ENDS
CSEG SEGMENT PARA PUBLIC 'CODE'
ASSUME CS:CSEG, DS:DSEG, SS:STACK
START: PUSH DS
SUB AX,AX
PUSH AX
MOV AX,DSEG ; инициировать адрес сегмента данных
MOV DS,AX
XOR AX,AX
MOV CX,5 ; число строк массива
LEA BX,Mas ; смещение начала массива занести в ВХ
Cyc1: PUSH CX ; сохранить в стеке текущее значение счетчика строк
XOR SI,SI ; начать обработку очередной строки
MOV CX,Len_s ; счетчик элементов строки
Cyc2: ADD AL, Mas[BX+SI] ; сумма очередного элемента в AL
ADC AH, 0 ; перенос в AH
INC SI ; перейти к следующему элементу строки
LOOP Cyc2
POP CX ; восстановить счетчик внешнего цикла (номера строки)
ADD BX,Len_s ; перейти к следующей строке
LOOP Cyc1
MOV Summ,AX ; сумма
DIV Len_m ; делим на количество
MOV Sred, AL ; частное
MOV Osta, AH ; остаток
EXIT: MOV AX, 4C00H
INT 21H ; возврат управления операционной системе
CSEG ENDS
END START
3. Оттранслировать программу в объектный код.
4. Провести отладку программы и проверить получаемые результаты. Для отладки и проверки программ использовать эмулятор микропроцессора 8086 (8086 microprocessor emulator) (Soft\emu8086v408\).
2.5. Программирование операций ввода-вывода
1. Изучить приведенный теоретический материал к лабораторной работе.
2. В соответствии с вариантом задания написать программы на ассемблере, предусмотрев вывод результатов работы программы на экран дисплея.
1) Найти первый максимальный элемент вектора и указать его местоположение. Элементы вектора однобайтовые.
Код программы:
; Найти первый максимальный элемент вектора и указать
; его местоположение. Элементы вектора однобайтовые.
STACK SEGMENT PARA STACK 'STACK'
DB 64 DUP('STACK') ; Область стека
STACK ENDS
DSEG SEGMENT PARA PUBLIC 'DATA'
Mes1 DB 'Max element: $'
Mes2 DB 'Number: $'
Ent DB 0Dh, 0Ah, '$'
Mas DB -1,20,13,-44,0,9,-6,1,77,-54 ; заданный вектор
Len_mas EQU 10 ; количество элементов в векторе
Maxe DB 0 ; максимальный элемент
Inde DB 0 ; индекс максимального элемента
C DB 10
R DB ?
DSEG ENDS
CSEG SEGMENT PARA PUBLIC 'CODE'
ASSUME CS:CSEG, DS:DSEG, SS:STACK
START: PUSH DS
SUB AX,AX
PUSH AX
MOV AX,DSEG ; инициировать адрес сегмента данных
MOV DS,AX
; Поиск максимального
MOV CX, Len_mas ; инициализация счетчика цикла
XOR SI,SI ; инициализация индексного регистра
MOV AL, Mas[SI] ; взяли первый элемент за max
MOV Maxe, AL ; запомнили его в переменной
INC SI ; переходим ко второму элементу
MOV BL, 1 ; индекс без учета первого 1
Cycl: MOV AL, Maxe ; взяли очередной элемент
Cmp Mas[SI], AL ; сравниваем элемент
JLE Kon_cycl ; элемент <= max
MOV AL, Mas[SI] ; копируем в AX
MOV Maxe, AL ; копируем в Maxe
MOV Inde, BL ; запоминаем индекс
Kon_cycl: INC SI ; переходим к следующему элементу вектора
INC BL ; считаем индекс
LOOP Cycl ; завершаем цикл.
; Вывод максимального значения
LEA DX, Mes1
MOV AH, 09h
INT 21h ; вывод строки
CMP Maxe, 10 ; сравниваем значение Max с 10
JL TCifr ; если меньше, то одна цифра
Dwe_TCifr: MOV AL, Maxe
CBW ; преобразуем байт в полное слово
DIV BYTE PTR C ; константа с объявлена в сегменте данных как C DB 10
MOV R, AH ; запоминаем младшую цифру в R,
MOV DL, AL ; старшую цифру помещаем в DL
ADD DL, 30h ; и выводим ее на экран
MOV AH, 02h
INT 21h
MOV DL, R ; младшую цифру помещаем в DL
ADD DL, 30h ; и выводим ее на экран
INT 21h
JMP Next
TCifr: MOV DL, Maxe
ADD DL, 30h
MOV AH, 02h
INT 21h
; Вывод индекса
Next: LEA DX, Ent
MOV AH, 09h
INT 21h ; вывод Enter
LEA DX, Mes2
MOV AH, 09h
INT 21h ; вывод строки
CMP Inde, 10 ; сравниваем значение Max с 10
JL TCifr0 ; если меньше, то одна цифра
Dwe_TCifr0: MOV AL, Inde
CBW ; преобразуем байт в полное слово
DIV BYTE PTR C ; константа с объявлена в сегменте данных как C DB 10
MOV R, AH ; запоминаем младшую цифру в R,
MOV DL, AL ; старшую цифру помещаем в DL
ADD DL, 30h ; и выводим ее на экран
MOV AH, 02h
INT 21h
MOV DL, R ; младшую цифру помещаем в DL
ADD DL, 30h ; и выводим ее на экран
INT 21h
JMP EXIT
TCifr0: MOV DL, Inde
ADD DL, 30h
MOV AH, 02h
INT 21h
EXIT: MOV AX,4C00h
INT 21h ; возврат управления операционной системе
CSEG ENDS
END START
2) Найти первый минимальный элемент вектора и указать его местоположение. Элементы вектора однобайтовые.
Примечания к реализации вывода значений элементов и их индексов на экран дисплея:
- десятичная цифра отличается от символа этой цифры на 30h, в чем легко убедиться, изучив таблицу кодов ASCII. Например, если искомый максимальный элемент записан в переменную Max, то фрагмент программы для его вывода на экран дисплея может быть следующим:
TCifra: MOV DL, Max
ADD DL, 30h
MOV AH, 02h
INT 21h
- предыдущий фрагмент применим в случае, если максимальное значение элемента является однозначным. Если элементы массива двухзначные (лежат в диапазоне от 10 до 99), то сначала необходимо выделить отдельные цифры, а затем их последовательно их распечатать:
Dwe_TCifr: MOV AL, Max
CBW ; преобразуем байт в полное слово
DIV BYTE PTR c ; константа с объявлена в сегменте данных как c DB 10
MOV r, AH ; запоминаем младшую цифру в r,
; переменная r объявлена в сегменте данных как r DB ?
MOV DL, AL ; старшую цифру помещаем в DL
ADD DL, 30h ; и выводим ее на экран
MOV AH, 02h
INT 21h
MOV DL, r ; младшую цифру помещаем в DL
ADD DL, 30h ; и выводим ее на экран
INT 21h
При реализации вывода следует учесть, что обращение к прерыванию INT 21h изменяет содержание регистра АХ (“портит” регистр АХ), поэтому значения из этого регистра, которые будут обрабатываться далее в программе, необходимо сохранить в другом регистре или ячейке памяти.
Желательно включить в программу оба вышеприведенных фрагмента совместно с анализом результата, как показано ниже:
СMP Max, c ; сравниваем значение Max с 10
JL TCifra ; если меньше, то одна цифра
Dwe_TCifr: MOV AL, Max ; иначе две цифры
далее по тексту фрагмент программы для вывода двух цифр
...
JMP Kon_wyw
TCifra: MOV DL, Max
При реализации заданий данной лабораторной работы возможно получение результата в виде отрицательного числа. Вывод на экран дисплея такого числа по вышеприведенным фрагментам программы возможен после преобразования отрицательного числа в положительное число командой NEG. Не забывайте в таком случае вывести на экран дисплея перед значением числа знак минус (-).
Код программы:
; Найти первый минимальный элемент вектора и указать
; его местоположение. Элементы вектора однобайтовые.
STACK SEGMENT PARA STACK 'STACK'
DB 64 DUP('STACK') ; Область стека
STACK ENDS
DSEG SEGMENT PARA PUBLIC 'DATA'
Mes1 DB 'Min element: $'
Mes2 DB 'Number: $'
Ent DB 0Dh, 0Ah, '$'
Mas DB -1,20,13,-14,0,9,-6,1,77,-44 ; заданный вектор
Len_mas EQU 10 ; количество элементов в векторе
Mine DB 0 ; минимальный элемент
Inde DB 0 ; индекс минимального элемент
C DB 10
R DB ?
DSEG ENDS
CSEG SEGMENT PARA PUBLIC 'CODE'
ASSUME CS:CSEG, DS:DSEG, SS:STACK
START: PUSH DS
SUB AX,AX
PUSH AX
MOV AX,DSEG ; инициировать адрес сегмента данных
MOV DS,AX
; Поиск минимального
MOV CX, Len_mas ; инициализация счетчика цикла
XOR SI,SI ; инициализация индексного регистра
MOV AL, Mas[SI] ; взяли первый элемент за min
MOV Mine, AL ; запомнили его в переменной
INC SI ; переходим ко второму элементу
MOV BL, 1 ; индекс без учета первого 1
Cycl: MOV AL, Mine ; взяли очередной элемент
Cmp Mas[SI], AL ; сравниваем элемент
JGE Kon_cycl ; элемент => min
MOV AL, Mas[SI] ; копируем в AX
MOV Mine, AL ; копируем в Mine
MOV Inde, BL ; запоминаем индекс
Kon_cycl: INC SI ; переходим к следующему элементу вектора
INC BL ; считаем индекс
LOOP Cycl ; завершаем цикл
; Вывод минимального значения
LEA DX, Mes1
MOV AH, 09h
INT 21h ; вывод строки
; если отрицательное
CMP Mine,0 ; сравниваем с 0
JGE Next1 ; минимальное > 0
MOV DL, 45 ; минус помещаем в DL
MOV AH, 02h ; и выводим на экран
INT 21h
NEG Mine ; оборачиваем число
Next1: CMP Mine, 10 ; сравниваем значение Mine с 10
JL TCifr ; если меньше, то одна цифра
Dwe_TCifr: MOV AL, Mine
CBW ; преобразуем байт в полное слово
DIV BYTE PTR C ; константа с объявлена в сегменте данных как C DB 10
MOV R, AH ; запоминаем младшую цифру в R,
MOV DL, AL ; старшую цифру помещаем в DL
ADD DL, 30h ; и выводим ее на экран
MOV AH, 02h
INT 21h
MOV DL, R ; младшую цифру помещаем в DL
ADD DL, 30h ; и выводим ее на экран
INT 21h
JMP Next2
TCifr: MOV DL, Mine
ADD DL, 30h
MOV AH, 02h
INT 21h
; Вывод индекса
Next2: LEA DX, Ent
MOV AH, 09h
INT 21h ; вывод Enter
LEA DX, Mes2
MOV AH, 09h
INT 21h ; вывод строки
CMP Inde, 10 ; сравниваем значение Max с 10
JL TCifr0 ; если меньше, то одна цифра
Dwe_TCifr0: MOV AL, Inde
CBW ; преобразуем байт в полное слово
DIV BYTE PTR C ; константа с объявлена в сегменте данных как C DB 10
MOV R, AH ; запоминаем младшую цифру в R,
MOV DL, AL ; старшую цифру помещаем в DL
ADD DL, 30h ; и выводим ее на экран
MOV AH, 02h
INT 21h
MOV DL, R ; младшую цифру помещаем в DL
ADD DL, 30h ; и выводим ее на экран
INT 21h
JMP EXIT
TCifr0: MOV DL, Inde
ADD DL, 30h
MOV AH, 02h
INT 21h
EXIT: MOV AX,4C00h
INT 21h ; возврат управления операционной системе
CSEG ENDS
END START
3) Найти сумму элементов строк двухмерного массива. Элементы массива положительные однобайтовые.
Примечания: Для вывода значения десятичного числа можно использовать процедуру описанную ниже. Разобрать работу процедуры и прокомментировать код.
WRITE_DEC PROC
PUSH AX
PUSH CX
PUSH DX
PUSH BX
MOV AX,DX
MOV BX,10d
XOR CX,CX
Non_Zero: XOR DX,DX
DIV BX
PUSH DX
INC CX
CMP AX,0
JNE Non_Zero
Write: POP DX
ADD DL, 30h
MOV AH, 02h
INT 21h
LOOP Write
POP BX
POP DX
POP CX
POP AX
RET
WRITE_DEC ENDP
Перед вызовом процедуры, выводимое значение необходимо разместить в DX:
MOV DX, Summ ; перед вызовом процедуры - значение суммы в DX
CALL WRITE_DEC ; вызов процедцры вывода числа
Код программы:
; Найти сумму элементов строк двухмерного массива.
; Элементы массива положительные однобайтовые
STACK SEGMENT PARA STACK 'STACK'
DB 64 DUP('STACK') ; Область стека
STACK ENDS
DSEG SEGMENT PARA PUBLIC 'DATA'
Mas DB 1,2,3,4,5,6,7,8,9,10
DB 100,9,8,7,6,5,4,3,2,100
DB 1,2,3,44,5,6,77,8,9,10
DB 10,9,8,7,6,5,44,3,2,11
DB 11,2,3,4,5,6,77,8,9,10
Len_s EQU 10 ; количество элементов в строке
Summ DW 0 ; сумма
Mes DB 'Sum = $' ; строка-сообщение сумма
Ent DB 0Dh, 0Ah, '$' ; строка Enter
DSEG ENDS
CSEG SEGMENT PARA PUBLIC 'CODE'
ASSUME CS:CSEG, DS:DSEG, SS:STACK
WRITE_DEC PROC
PUSH AX
PUSH CX
PUSH DX
PUSH BX
MOV AX,DX
MOV BX,10d
XOR CX,CX
Non_Zero: XOR DX,DX
DIV BX
PUSH DX
INC CX
CMP AX,0
JNE Non_Zero
Write: POP DX
ADD DL, 30h
MOV AH, 02h
INT 21h
LOOP Write
POP BX
POP DX
POP CX
POP AX
RET
WRITE_DEC ENDP
START: PUSH DS
SUB AX,AX
PUSH AX
MOV AX,DSEG ; инициировать адрес сегмента данных
MOV DS,AX
XOR AX,AX
MOV CX,5 ; число строк массива
LEA BX,Mas ; смещение начала массива занести в ВХ
Cyc1: PUSH CX ; сохранить в стеке текущее значение счетчика строк
XOR SI,SI ; начать обработку очередной строки
MOV CX,Len_s ; счетчик элементов строки
MOV AX, 0 ; обнуляем AX - для суммирования
Cyc2: ADD AL, Mas[BX+SI] ; сумма очередного элемента в AL
ADC AH, 0 ; перенос в AH
INC SI ; перейти к следующему элементу строки
LOOP Cyc2
MOV Summ, AX ; сумма строки
; Вывод суммы
LEA DX, Mes
MOV AH, 09h
INT 21h ; вывод строки-сообщения
MOV DX, Summ ; перед вызовом процедуры - значение суммы в DX
CALL WRITE_DEC ; вызов процедцры вывода числа
LEA DX, Ent
MOV AH, 09h
INT 21h ; вывод Enter
POP CX ; восстановить счетчик внешнего цикла (номера строки)
ADD BX, Len_s ; перейти к следующей строке
LOOP Cyc1
EXIT: MOV AX, 4C00H
INT 21H ; возврат управления операционной системе
CSEG ENDS
END START
3. Оттранслировать программу в объектный код.
4. Провести отладку программы и проверить получаемые результаты.
Комментариев нет:
Отправить комментарий