Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология Образование Политология Производство Психология Стандартизация Технологии |
Лекция №5 Работа с массивами
Основные понятия. Массив. Элемент массива. Массив это совокупность элементов одинакового типа. Массив состоит из фиксированного числа элементов. Размерность массива фиксируется при объявлении его и при исполнении программы не меняется. Объявление массива В языке высокого уровня PASCAL объявление массива имеет вид Имя_массива: array[тип индекса] of тип элемента Например, объявления массива констант и массива переменных могут иметь вид: Const D: array[1..5] of integer=(10, -4, 1234, 0, -5); Var A: array[1..5] of integer; Тип целочисленной переменной может быть задан ключевыми словами: integer/ Byte/Word/Shortint. Все элементы массива располагаются в оперативной памяти. Размер области, отводимой под один элемент массива, зависит от указанного типа: для integer/Word выделяется по 2 байта, а для Byte/Shortint по 1 байту. На ассемблере объявления массива констант и массива переменных могут иметь вид: D DW 10, -4, 1234, 0, -5); массив констант A DW 5 dup(? ); резервировано 5 слов по 2 байта. Как видно из примера, на ассемблере явно указан размер элемента массива, но не указано, числа со знаком (integer/ Shortint) или без знака (Byte/Word). Программист должен сам контролировать предполагаемый диапазон значений элементов. Положение элемента в массиве определяется набором индексов или координат. Доступ к элементу одномерного массива (вектора) указывается с помощью индексной переменной. На Pascal элемент вектора А обозначается A[i] или A[j], адреса соседних элементов массива отличаются на размер поля, занимаемого одним элементом. Если тип Integer/ Word, то разница равна 2, а для типов Byte/ Shortint разница равна 1. Переадресация элементов на языке высокого уровня выполняется «автоматически»( транслятор предусматривает нужные операции), а на ассемблере необходимые действия кодируются программистом. При работе с массивами в Ассемблере используется косвенная адресация полей памяти. косвенная регистровая: [BX], [BP], [DT], [SI] MOV BX, offset A; в BХ заносится смещение переменной А, внутри сегмента. MOV AX, [BX] Эффективный адрес вычисляется: Ea = (DS)*16 + (BX) MOV DI, offset B ADD AX, [DI] По умолчанию DS – регистр сегмента данных. Если имеется другой регистр, то его записываем явно [ES]: [DI] Регистровая базовая [BХ] ± выражение [BХ] + смещение Примеры записи X[BX], X + [BX], [BX] – 2, [BX -2] В случае базового регистра ВХ регистром сегмента считается регистр DS. Ea = (DS) * 16 + (BX) + offset X ± константа выражения. Если данные находятся в стеке, то используемый регистр ВР, который по умолчанию формирует адрес относительно регистра SS ( SS: [ВР] ) Ea = (SS) * 16 +(BP) [BP] + 2; [BP -2]; Обычно регистр ВР используется при извлечении параметров процедуры, передаваемых через стек. регистровая индексная [DI] и [SI] A [SI] Ea =A + [SI] B [DI] Ea =B + [DI] Исполнительный адрес Ea = (DS) * 16 + смещение переменной + содержание регистра индекса. Базовая индексная со смещением. A [BX] [DI] A + [BX] +[DI] A + 4 [BX] [DI] Нельзя одновременно в одном операнде использовать два (2) индексных или базовых регистра. Еа = (DS)* 16 – (Р.И.) + смещение.
Примеры составления программ работы с массивами Пример 1. Дан массив из 10-ти элементов целого типа. Найти: Реализация программы на Паскале: Program p1; Const a: array[1..10] of integer=(-10, 3, 7, 0, 10, 0, -4, -8, 1, 1); Var S: integer; I: integer; Begin {} S: = 0; begin For i: = 1 to 10 do S: = S + a[i] * a[i] end; end.
Реализация программы на Ассемблере: Используются регистры: АX, BX, DX, CX, DI. BX – для накопления суммы AX, DX – для вычисления квадрата. A2j CX – счетчик цикла. Каждый элемент массива типа integer занимает слово или 2 байта. Элемент A1 расположен по адресу A+0, элемент A2 на 2 байта дальше то есть, A+2. Для адресации элемента массива A[i] применим индексную адресацию: A[i] ≈ A[DI] Исполнительный адрес A[DI] будет вычисляться процессором в виде суммы адреса начала массива (адрес A+0] и содержимого DI, который меняется от 0 с шагом 2. В сегменте данных: A DW -10, 3, 7, 0, 10, 0, -6, -8, 1, 1 S DW?
Сегмент кода ………………………………….. ; подготовка к циклу MOV CX, 10; инициализация счетчика циклов MOV BX, 0; очистка суммы MOV DI, 0; i=1 Metka: MOV AX, A [DI]; Ai ® AX Imul AX; AX = A2i Add BX, AX; прибавление к сумме ; переадресация i: = i+ 1. Add DI, 2; или Add DI, type A; ; управление циклом loop metka MOV S, BX
Анализ работы программы: Определить содержимое регистров BX, DX, CX, AX после цикла, DI. DI – 20 ( 0014h) AX – 1 ( 0001h) DX – 0 ( 0000h) CX – 0 ( 0000h) BX – 168h =36010 Пример 2. Дан массив A[10] типа Integer. Ввести элементы массива с клавиатуры. Реализация программы на Паскале: Program p2; Var a: array[1..10] of integer;; I: integer; Begin i: = 1; while (i< =N do begin write(‘введите элемент массива ’); readln(a[i]); i: = i + 1; end; writeln(‘ Масив введен’); readln; End. Реализация программы на Ассемблере: %nolist include mac.lib %list A_Stack segment Stack `стек` DW 256 dup (0) A_STACK ENDS.
A_Data segment A dw 10 dup(? ) Mes1 db 10, 13, ’введите элемент массива $’ Meser db 10, 13, ’ Ошибка ввода. Повторите! ‘, 10, 13, ‘ $’ Mes2 db 10, 13, ’ Массив введен $’
A_Data Ends
A_Code Segment PARA PABLIC Assume DS: A_Data, SS: A_Stack, CS; A_Code START: ; подготовка к циклу mov cx, 10; число элементов массива. mov di, 0; i: = 1 CIKL: lea dx, mes1 mov ah, 9h int 21h ; макрос ввода с клавиатуры Key_$2bin ; ввод числа со знаком в регистр ax. Jnc good Lea dx, meser Mov ah, 9h Int 21h Jmp cikl Good: Mov А[DI], ax; AX-> A[i] ; переадресация ADD DI, 2; i: = i + 1 until: dec cx; cx=cx-1 jz final; при cx=0 на метку final jmp CIKL; если CX не 0, то безусловный переход на метку CIKL final: lea dx, mes2 mov ah, 9h int 21h ; exit; Mov ah, 4ch Int 21h A_Code ends End start
Комментарий В тело цикла включена макрокоманда Key_$2bin. После подстановки ее макрорасширения тело цикла может оказаться по размеру длиннее 128 байт, что превышает возможности команды LOOP, и она в данной программе не использована для управления циклом
Лекция № 6 Прерывания Прерывания(interruption) получили свое название по своей основной функции – приостановить процесс основных вычислений в ЦП для выполнения вспомогательных, технологических и сервисных действий ОС. Процедуры обработки прерываний - это подпрограмма с обязательным обращением через косвенный межсегментный адрес, размещенный в фиксированной области памяти. Прерывания принято классифицировать по трем типам: Ø программные Ø аппаратные Ø отладочные Если возникает прерывание, то оно не может остановить микропроцессор во время выполнения им команды. Микропроцессор 8088 прежде всего, завершает выполнение текущей команды, затем, не обращая внимания на следующую команду, действует как в случае вызова подпрограммы. То есть он записывает адрес следующей команды в стек и переходит к специальной подпрограмме, которая называется обработчиком прерывания. Эта подпрограмма содержит команды, которые требуются для обслуживания устройства, вызвавшего прерывание. После того, как подпрограмма обработки прерывания закончила свою работу с устройством она возвращает управление в точку программы, где произошло прерывание. Векторы прерываний. Важная составная часть микропроцессора 8088 – это механизм прерывания. Эта компонента встроена в микропроцессор и обеспечивает эффективное обслуживание прерываний. Когда МП 8088 получает сигнал о необходимости прерывания, он определяет какое из устройств требует обслуживания посредством аппаратной процедуры, известной как цикл подтверждения прерывания. Контроллер 8259 фирмы Intel Контроллер прерываний программируется так, чтобы выдавать 1-байтовое число в ответ на цикл подтверждения прерывания микропроцессора 8088. Это число лежит в диапазоне от 0 до 255 и показывает номер прерывания внешнего прерывающего устройства. В ПЭЦМ контроллер прерывания обслуживает восемь внешних прерываний, которым соответствуют номера от 8 до 15. Первые 1024=256*4 байт памяти МП8088 зарезервированы для векторов прерывания, где каждому из прерываний отводится 4-байтовая область:
Каждая 4-байтовая ячейка содержит указатель на обработчик прерывания с номером N. к + 0, к + 1 - смещение к + 2, к + 3 - сегмент DS_VEC SEGMENT PARA AT 0h VECTOR DD 256 dup(? ) DS_VEC ENDS Как только МП8088 получает номер прерывания, он передает управление соответствующему обработчику. Обработчик прерывания должен обслужить прерывание как вызов дальнего типа FAR, поэтому прежде чем передать управление обработчику прерывания, он должен сохранить как сегмент, так и смещение текущей команды. Возврат из программы обработки прерывания должен произойти так, чтобы машина вернулась в то же состояние, в котором она была в тот момент, когда возникло прерывание. Поэтому МП сохраняет также регистр флагов. Обработчик прерываний не будет производить эти действия. При сохранении регистра флагов сохраняется также и текущее состояние флага разрешения прерываний. Программа обработки не может быть прервана другим прерыванием. Команда возврата из прерывания восстанавливает регистр флагов, то есть возвращает предыдущее состояние флагу прерывания. Итак, возникло прерывание- выполняется следующая цепочка действий: 1) регистр флагов заносится в стек 2) CS: IP ® стек 3) № прерывания = VECTN 4) адрес подпрограммы = VECT(N * 4) 5) CS: = VECT(N * 4) IP: = VECT(N * 4) + 2 6) подпрограмма сохраняет регистры в стеке 7) обработка 8) восстановление регистров 9) возврат IRET: IP, CS, регистр флагов
Популярное:
|
Последнее изменение этой страницы: 2016-04-11; Просмотров: 1569; Нарушение авторского права страницы