Разработать и отладить программу расчета выражения

Разработать и отладить программу расчета выражения

  1. Задание с выбором варианта коэффициентов
  2. Описание алгоритма задачи
  3. Описание отдельных процедур
  4. Листинг программы с комментариями
  5. Листинг результатов выполнения работы
  6. Список литературы

Для любого обращения к памяти в процессорах Intel используется логический адрес, состоящий из 16-битного селектора, определяющего сегмент, и 32- или 16-битного смещения — адреса внутри сегмента. Отдельный сегмент памяти — это независимое защищенное адресное пространство, для которого определены размер, разрешенные способы доступа (чтение/запись/исполнение кода) и уровень привилегий. Если доступ к памяти удовлетворяет всем условиям защиты, процессор преобразует логический адрес в 32- или 36-битный линейный. Линейный адрес — это адрес в несегментированном непрерывном адресном пространстве, который совпадает с физическим адресом в памяти, если отключен режим страничной адресации. Чтобы получить линейный адрес из логического, процессор добавляет к смещению линейный адрес начала сегмента, который хранится в поле базы в сегментном дескрипторе. Сегментный дескриптор — это восьмибайтная структура данных, расположенная в таблице GDT или LDT; адрес таблицы находится в регистре GDTR или LDTR, а номер дескриптора в таблице определяется из значения селектора.

Задание на курсовую работу

Разработать и отладить программу расчета выражения вида:

для значений Х от Xmin до Xmax с шагом 1 при а=2; В=1; С=4; Хмин=2; Хмах=6.

Оформить вывод фамилии и инициалов автора, уникального идентификационного номера, а также текущей даты.

Результаты вычислений вывести в виде таблицы значений X и Y на экране дисплея.

  1. Описание алгоритма задачи
    • Организация сегмента данных.

Программа на Ассемблере состоит из логически самостоятельных частей, называемых сегментами. Для исполнения сегменты программы заносятся в отдельные участки оперативной памяти. Модуль программы может содержать от одного до трех типов сегментов – сегмент данных, стека и кода. Сегмент кода является обязательным, остальные могут отсутствовать (например, сегмент данных или стека) или быть объединены (сегмент кода и данных). Директиву ASSUME назначения сегментных регистров сегментам данных, стека, кода можно разместить перед сегментом кода или в первой его строке.

assume CS:Code, DS:Data, SS:Stackg

Начало и конец программного модуля обозначается с помощью связанных директив NAME и END.

Псевдокоманда — это директива ассемблера, которая приводит к включению данных или кода в программу, хотя сама она никакой команде процессора не соответствует. Псевдокоманды определения переменных указывают ассемблеру, что в соответствующем месте программы располагается переменная, определяют тип переменной (байт, слово, вещественное число и т.д.), задают ее начальное значение и ставят в соответствие переменной метку, которая будет использоваться для обращения к этим данным. Псевдокоманды определения данных записываются в общем виде следующим образом:

имя_переменной d* значение

где D* — одна из нижеприведенных псевдокоманд:

DB — определить байт;

DW — определить слово (2 байта);

DD — определить двойное слово (4 байта);

DF — определить 6 байт (адрес в формате 16-битный селектор: 32- битное смещение);

DQ — определить учетверенное слово (8 байт);

DT — определить 10 байт (80-битные типы данных, используемые FPU).

Поле значения может содержать одно или несколько чисел, строк символов (взятых в одиночные или двойные кавычки), операторов ? и DUP, разделенных запятыми. Все установленные таким образом данные окажутся в выходном файле, а имя переменной будет соответствовать адресу первого из указанных значений. Например, набор директив

Data SEGMENT

KR_RAB DB 'Контрольная работа № 1',13,10,' ------------------------',13,10,'$' Family DB ' Сердюк Владимир Леонидович',13,10,' -------------',10,13,'$' MESS DB ' Уникальный идентификационный номер 09',13,10,'------- ',13,10,'$'

ZAD DB ' Задание: Решить уравнение Y=A*(X*X)+B*X+C',13,10,'',13,10,'$' ZAD1 DB 'при А=2; В=1; С=4; Хмин=2; Хмах=6; Шаг=1.',13,10,' ',13,10,'$'

MES DB ,13,10,' $'

MESSS DB ,13,10, ' Сегодня: ','$'

MESSSS DB ,13,10, ' ','$'

Y DB 2D

X DB 2D

DAT DB 10 DUP(?)

DATT DB 10 DUP(?)

REZ_SHOW DB 10 DUP(?)

Data ends

заполняет данными 78 байта. Первые 22 байт содержат ASCII-коды символов строки «Контрольная работа № 1» и переменная KR_RAB DB указывает на первую букву в этой строке, так что команда

mov al,text_string

считает в регистр AL число 8Аh (код русской буквы К). Если вместо точного значения указан знак ?, переменная считается неинициализированной и ее значение на момент запуска программы может оказаться любым. Если нужно заполнить участок памяти повторяющимися данными, используется специальный оператор DUP, имеющий формат счетчик DUP (значение). Например, вот такое определение:

DAT DB 10 DUP(?)

table_512w dw 512 dup(?)

создает массив из 10 неинициализированных слов, на первое из которых указывает переменная DAT. В качестве аргумента в операторе DUP могут выступать несколько значений, разделенных запятыми, и даже дополнительные вложенные операторы DUP.

  • Организация сегмента стека для временного сохранения и восстановления промежуточных результатов

Stackg segment Stack

DB 100H DUP(?) стек размером 256 байт.

Stackg ENDS

  • Организация сегмента кода в виде основной программы, и набора вспомогательных подпрограмм-процедур.

Объявление сегмента кода.

Code segment

Обработка значений Х

MOV AX,DATA DATA в AX

MOV DS,AX AX в DX

XOR AX,AX обнуляем ax

MOV CX,6D заносим значение счетчика цикла в cx т.е до 6-и.

MOV SI,1 индекс начального элемента в cx т.е. 1.

MOV DAT[Si],028H Y в si

inc Si увеличиваем SI на 1

MOV DAT[Si],083H | в si

inc Si SI +1

GOO:

mov BH,X значение X в bh

mov DAT[Si],BH х в si

Переход к следующей ячейки памяти

inc Si

Увеличиваем число Х на еденицу.

inc X инкремент X т.е. х+1

Записываем значение в SI

MOV DAT[Si],0CFH значение | в si

inc Si инкремент si

MOV DAT[Si],083H значение | в si

inc Si инкремент si

loop GOO повторять цикл пока х не равен 6

Обработка значений Y

MOV AX,DATA DATA в AX

MOV DS,AX AX в CX

XOR AX,AX обнуляем AX

MOV CX,5D количество элементов Y

MOV SI,1 первый элемент =1

MOV REZ_SHOW[si],029H Y в SI

inc si

MOV REZ_SHOW[si],083H | в SI

inc si

Calculate:

Считаем

MOV AL,Y Хмин=1 в AL

умножение целочисленное без учета знака. 

MUL AL X*X

MOV BL,2D A в BL

Умножение целочисленное без учета знака. 

MUL BL A*X*X

Сложение т.к. В=1, умножение не выполняем.

ADD AL,Y A*X*X+B*X

Прибавляем С.

ADD AL,4D A*X*X+B*X+C

L1: Сравнение и счет после 10

Сравниваем результат с 10 если больше то на метку L2 иначе продолжаем программу дальше

CMP AL,10

JB L2

MOV BL,10 10 в BL

Деление на 10

DIV BL

Результат деления в SI.

MOV REZ_SHOW[si],AL

Переход к следующей ячейки памяти.

INC SI

AH в SI

MOV REZ_SHOW[si],AH

Переход к следующей ячейки памяти.

INC SI

Разделительная черта в SI

MOV REZ_SHOW[SI],083H

Переход к следующей ячейки памяти.

INC SI

Сравниваем с 10 если больше то на L3

CMP AL,10

JB L3

L2: Счет до 10

Результат до 10 в SI

MOV REZ_SHOW[si],AL

Переход к следующей ячейки памяти.

INC SI

Разделительная черта в SI.

MOV REZ_SHOW[SI],083H

Переход к следующей ячейки памяти.

INC SI

Повторение цикла

L3:

Х увеличиваем на 1

INC Y

Повторить цикл Calculate

LOOP Calculate

Обработка вида таблицы выполнена по подобию обработки значений Х.

  1. Описание отдельных процедур.

Вывод системной даты основан на использовании недокументированного прерывания 29H то есть быстрого вывода значения на экран.

Рассмотрим вывод системной даты.

CMOS 0Bh – управляющий регистр В

mov AL,0Bh

Порт 70h – индекс CMOS

out 70h,al

Порт 71h – данные CMOS.

in al,71h

Обнулить бит 2 (форма чисел - BCD).

and al,11111011b

Записать обратно.

out 71h,al

Затем выводим на экран день, месяц и год .

CMOS 07h – день.

mov al,7

Обращение к процедуре cmoss.

call cmoss

Вывод тире.

mov al,'-'

Прерывание быстрого вывода на экран.

int 29h

CMOS 08h – месяц.

mov al,8

Обращение к процедуре cmoss.

call cmoss

Вывод тире.

mov al,'-'

Прерывание быстрого вывода на экран.

int 29h

CMOS 32h – две старшие цифры года.

mov al,32h

Обращение к процедуре cmoss.

call cmoss

CMOS 09h – две младшие цифры года

mov al,9

Обращение к процедуре cmoss.

call cmoss

Выводим букву г.

mov al,'г'

Прерывание быстрого вывода на экран.

int 29h

Объявление процедуры CMOSS

cmoss proc near

Послать в AL в индексный порт CMOSS.

out 70h,al

Считать данные в AL

in al,71h

Отправить в стек.

push ax

Выделить старшие 4 – байта.

shr al,4

Добавляем ASCII цифру 0

add al,'0'

Выводим на экран

int 29h

Считываем из стека.

pop ax

Выделяем младшие 4 – байта.

and al,0Fh

Добавляем ASCII цифру 0

add al,30h;al

Вывод на экран

int 29h

ret 7

Конец процедуры.

cmoss endp

  1. Листинг программы с комментариями.

Data SEGMENT

KR_RAB DB ' Контрольная работа № 1',13,10,'-----------',13,10,'$'

Family DB ' Сердюк Владимир Леонидович',13,10,' ---',10,13,’$’

MESS DB ' Уникальный идентификационный номер',13,10,'---',13,10,'$'

ZAD DB 'Задание: Решить уравнение Y=A*(X*X)+B*X+C',13,10,' ',13,10,'$'

ZAD1 DB ' при А=2; В=1; С=4; Хмин=2; Хмах=6; Шаг=1.',13,10,' ',13,10,'$'

MES DB ,13,10,' $'

MESSS DB ,13,10, ' Сегодня: ','$'

MESSSS DB ,13,10, ' ','$'

Y DB 2D ;резервируем память под переменную Y

X DB 2D ; резервируем память под переменную Х

DAT DB 10 DUP(?) ; 10 DUP результат в символьном формате

DATT DB 10 DUP(?) ; 10 DUP результат в символьном формате

REZ_SHOW DB 10 DUP(?) ; результат в символьном формате

Data ends

;-------------------------------------------------------------------

Stackg segment Stack

DB 100H DUP(?) стек размером 256 байт.

Stackg ENDS

assume CS:Code, DS:Data, SS:Stackg

;------------------------------------------------------------------

Code segment

Start:

MOV AH, 00H функция задания режима экрана

MOV AL, 03H ЦВ текстовый, 25 строк по 80 знаков

INT 10H

;------------------------------------------------------------------------;

;------------------------------------------------------------------------;

ОБРАБОТКА И ВЫВОД ЗНАЧЕНИЯ X

MOV AX,DATA

MOV DS,AX AX в DX

XOR AX,AX обнуляем ax

MOV CX,6D значение счетчика цикла в cx

MOV SI,1 индекс начального элемента в cx

MOV DAT[Si],028H значение Y

inc Si инкремент SI

MOV DAT[Si],083H значение |

inc Si инкремент SI

GOO:

mov BH,X X в bh

mov DAT[Si],BH записываем в массив i

inc Si следующая ячейка памяти

inc X инкремент X

MOV DAT[Si],0CFH значение |

inc Si следующая ячейка памяти 

MOV DAT[Si],083H значение |

inc Si следующая ячейка памяти 

loop GOO повторить цикл

;------------------------------------------------------------------

mov ah,09h функция вывода на экран

lea dx,KR_RAB

INT 21H вывод строки

mov ah,09h функция вывода на экран

lea dx,Family

INT 21H вывод строки

mov ah,09h

lea dx,MESS

INT 21H

mov ah,09h

lea dx,ZAD загрузка ZAD в DX

INT 21H

mov ah,09h

lea dx,ZAD1 загрузка ZAD1 в DX

INT 21H

mov ah,09h

lea dx,MES загрузка MES в DX

INT 21H прерывание №21

;------------------------------------------------------------------

MOV CX,17 резервируем память

MOV SI,1 1 в SI

showW:

mov AH,02h функция вывода значения из al на экран

mov dl,DAT[Si] запись в массив i

add dl,30h преобразуем число в символ

int 21h

inc SI инкремент SI

loop showW повтор цикла

mov ah,09h вывод на экран MES

lea dx,MES

INT 21H

;--------------------------------------------------------------------;

;--------------------------------------------------------------------;

ОБРАБОТКА ТАБЛИЦЫ

MOV AX,DATA

MOV DS,AX

XOR AX,AX обнуляем ax

MOV CX,6D значение счетчика цикла в cx

MOV SI,1 начальное значение в si

MOV DATT[Si],094H значение Y

inc Si инкремент SI

MOV DATT[Si],083H значение |

inc Si инкремент SI

GOOO:

mov BH,094H X в bh

mov DATT[Si],BH запись в массив i

inc Si инкремент SI

MOV DATT[Si],094H значение --

inc Si инкремент si

MOV DATT[Si],083H значение |

inc Si инкремент si

loop GOOO повторить цикл

;--------------------------------------------

MOV CX,17

MOV SI,1

showWW:

mov AH,02h вывод на экран

mov dl,DATT[Si] запись в массив i

add dl,30h преобразуем число в символ

int 21h

inc SI инкремент si

loop showWW повторить цикл

mov ah,09h вывод на экран MES

lea dx,MES

INT 21H

;----------------------------------------------

;--------------------------------------------------------------------;

;--------------------------------------------------------------------;

ОБРАБОТКА И ВЫВОД ЗНАЧЕНИЯ Y

MOV AX,DATA

MOV DS,AX

XOR AX,AX обнуляем ax

MOV CX,5D максимум в цикле cx

MOV SI,1 начальный элемент цикла в cx

MOV REZ_SHOW[si],029H значение Y

inc si

MOV REZ_SHOW[si],083H значение |

inc si

Calculate: Считаем 

MOV AL,Y Хмин=1 в AL

MUL AL X*X  

MOV BL,2D A в BL

MUL BL A*X*X 

ADD AL,Y A*X*X+B*X прибавили В*Х

ADD AL,4D A*X*X+B*X+C плюс С

L1: сравнение и счет после 10

CMP AL,10 сравниваем результат с 10

JB L2 если больше, то на  L2 иначе дальше

MOV BL,10 10 в BL

DIV BL делим на 10

MOV REZ_SHOW[si],AL результат деления в si

INC SI следующая ячейка

MOV REZ_SHOW[si],AH AH в старший разряд AX

INC SI следующая ячейка

MOV REZ_SHOW[SI],083H вертикальная черта

INC SI следующая ячейка

CMP AL,10 если больше то на  L3

JB L3

L2:

MOV REZ_SHOW[si],AL AL в SI

INC SI следующая ячейка

MOV REZ_SHOW[SI],083H | в следующую ячейку

INC SI новая ячейка памяти

L3:

INC Y Х увеличиваем на  1

LOOP Calculate повторить цикл Calculate

;------------------------------------------------------------------

Вывод на экран полученного массива

MOV SI,1 в SI 1

mov cx,17D размер буфера  CX

show:

mov ah,02h вывод на экран

mov dl,REZ_SHOW[si] SI в DL

add dl,30h символ в число

int 21h прерывание 21h

inc si следующая ячейка

loop show повторить цикл

;----------------------------------------------------------------------;

;----------------------------------------------------------------------;

mov ah,09h

lea dx,MES вывод MES на экран

INT 21H

mov ah,09h

lea dx,MESSS вывод MESSS на экран

INT 21H

mov ah,09h

lea dx,MESSSS вывод MESSSS на экран

INT 21H

;------------ВЫВОД СИСТЕМНОЙ ДАТЫ------------------------------

;--------------------------------------------------------------------------

mov AL,0Bh CMOS 0Bh –управляющий регистр B

out 70h,al порт 70h - индекс CMOS

in al,71h порт 71h – данные CMOS

and al,11111011b обнулить бит 2 (форма чисел- BCD)

out 71h,al и записать обратно

;--------------------------------------------------------------------------

mov al,7 CMOS 07h - день

call cmoss вызов процедуры

mov al,'-' тире

int 29h быстрый вывод

;----------------------------------------------------------------------

mov al,8 CMOS 08h – текущий месяц

call cmoss вызов процедуры

mov al,'-' тире

int 29h быстрый вывод

;-----------------------------------------------------------------------

mov al,32h CMOS 32h – две старшие цифры года

call cmoss вызов процедуры

mov al,9 CMOS 09h – две младшие цифры года 

call cmoss вызов процедуры

mov al,'Ј' символ г

int 29h прерывание 29h

JMP EXIT безусловный переход на ВЫХОД

cmoss proc near процедура

out 70h,al послать AL в индексный порт CMOS

in al,71h прочитать данные

push ax в стек

shr al,4 выделить старшие 4 бита

add al,'0' добавить 0

int 29h быстрый вывод

pop ax из стека

and al,0Fh выделить младшие 4 бита

add al,30h добавить ASCII-код цифры 0

int 29h быстрый вывод символа на экран

ret 7

cmoss endp

;-------------------------------------------------------------

exit:

mov ax,00h

int 16h ждем нажатие любой клавиши

;-------------------------------------------------------------

MOV AX,4C00H символьная функция возврата  

INT 21H в диспетчер MS DOS.

Code ENDS

END Start адрес начала программы

  1. Листинг результатов выполнения работы

  1. Абель П. Язык Ассемблера для IBM PC и программирования. – М.: Высшая школа, 1992 г.
  2. Нортон П, Уилтон. IBM PC и PS/2.– Руководство по программированию. М.: Радио и связь, 1994 г.
  3. Пильщиков В.Н. Программирование на языке АСС IBM PC .–М.: Диалог- МИФИ, 1996 г.
  4. Скэнлон Л. Персональные ЭВМ PC и XT. Программирование на языке Ассемблера.– М.: Радио и связь, 1989 г.
  5. Юров В.И. Assembler.– С-Пб: Питер, 2006.