воскресенье, 22 сентября 2019 г.

Отчет по учебной практике ОМТ (Основы микропроцессорной техники)

2.1. Трансляция, компоновка и отладка программ

2.1.2. Выполнение работы

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

2.2. Режимы адресации

2.2.2. Выполнение работы

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. Программирование ветвлений и циклов

2.3.2. Выполнение работы

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. Арифметические операции целочисленной обработки информации

2.4.2. Выполнение работы

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. Программирование операций ввода-вывода

2.5.2. Выполнение работы

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. Провести отладку программы и проверить получаемые результаты.

Комментариев нет:

Отправить комментарий