Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
124
Добавлен:
02.05.2014
Размер:
136.7 Кб
Скачать

Процедуры

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

Имя_процедуры PROC[[модификатор_языка]язык] [расстояние]

[ARGсписок_аргументов]

[RETURNSсписок_аргументов]

[LOCALсписок_аргументов]

[USESсписок_регистров]

Команды, директивы

Языка макроассемблера

RET

[имя_процедуры] ENDP

Из этого описания видно, что обязательными являются небольшое количество параметров, Хочу обратить Ваше внимание на то, что хотя в конце процедуры имя не является обязательным, рекомендую его обязательно писать, т.к. это облегчает чтение программы и возможную ее модификацию. Разница описания процедуры на языке Ассемблера и на языках высокого уровня только в деталях, которые хорошо усваиваются только на практике. Принципиальных различий немного, среди которых:

  • атрибут расстояние. Он может принимать значения NEARиFAR. 1-ый вариант – для обращения к процедуре, описанной в текущем сегменте кода, 2-ой вариант – для обращения к процедуре из другого сегмента кода (внешней по отношению к текущему сегменту кода). По умолчанию предполагаетсяNEAR. В этой связи следует обратить внимание, что основная процедура программы на ассемблере должна всегда иметь атрибут расстоянияFAR, т.к. для программы-загрузчика она является внешней;

  • процедуру можно помещать в любом месте программы, но таким образом, чтобы управление передавалось процедуре только в нужное время. Учитывая это, процедуру можно размещать в начале программы (до первой исполняемой команды) или в конце программы (после возвращения управления операционной системе) или в другом модуле. Если Вы все же решите поместить процедуру внутри другой процедуры или основной программы, то не забудьте предусмотреть обход процедуры, поставив перед началом процедуры команду JMP;

  • Обращение к процедуре происходит по команде

  • CALL[модификатор] имя_процедуры

  • Модификатор принимает такие же значения, как и в команде JMP, за исключениемSHORTPTR.

Организация циклов

При организации циклов широко используются команды INC(инкремент) иDEC(декремент), что означает добавление или вычитание единицы из целого числа, помещенного в ячейку памяти, РОН или индексный регистр. Команды имеют формат:

INCоперанд или

DECоперанд

В листинге 10.2 на стр.223 (учебник Юрова “Ассемблер”) приведен пример программы, в которой цикл организован за счет использования команд декремента и условного и безусловного перехода.

Программа подсчета количества нулевых элементов в одномерном массиве (векторе)

TITLE prg_10_2

STACK SEGMENT PARA STACK ‘STACK’

DB 64 DUP(‘STACK’) ; Область стека

STACK ENDS

DSEG SEGMENT PARA PUBLIC ‘DATA’

Mas db 1,0,9,8,0,7,8,0,2,0 ; это заданный одномерный массив байт

Len_mas equ 10 ; количество элементов в массиве, это же количество

;можно получить как len_mas=$ - mas

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 СX, LEN_MAS ; в сх – счетчик элементов массива

XOR AX,AX

XOR SI,SI

CYC1: JCXZ EXIT ; проверка сх на 0, если 0, то выход

CMP MAS[SI],0 ;сравнить очередной элемент задан. массива с 0

JNE M1 ; если не равно 0, то на m1

INC AL ; увеличение счетчика нулевых элементов

M1: INC SI ; перейти к следующему элементу

DEC CX ; уменьшить счетчик элементов на 1

JMP CYC1

EXIT: MOV AX, 4C00H

INT 21H ; возврат управления операционной системе

END START

да

нет

нет

да

Нет Да

Но, учитывая важность такого алгоритмического элемента, как цикл, разработчики предусмотрели специальные команды цикла

LOOPметка_перехода,

которая означает ’повторить цикл’. Выполнение команды заключается в следующем:

  • вычитании 1 из регистра СХ;

  • сравнении регистра СХ с нулем;

  • если СХ=0, то управление передается на следующую после LOOPкоманду, иначе перейти на метку_перехода.

LOOPE/LOOPZметка_перехода,

которая означает “повторить цикл, пока СХ<>0 или ZF=0”. Обе команды совершенно идентичны, поэтому используйте, при необходимости, любую по Вашему вкусу. Отличаются эти команды от предыдущей пунктом 3 или анализом окончания цикла:

  • если СХ>0 и ZF=1, управление передается на метку перехода, иначе если СХ=0 илиZF=0, то выполняется следующая после командыLOOPE/LOOPZоперация.

LOOPNE/LOOPNZметка_перехода,

которая означает, “повторить цикл, пока СХ<>0 или ZF=1”. Обе команды совершенно идентичны, поэтому используйте, при необходимости, любую по Вашему вкусу. В ней пункт 3 выполняется по следующему правилу:

  • если СХ>0 и ZF=0, управление передается на метку перехода, иначе если СХ=0 илиZF=1, то выполняется следующая после командыLOOPNE/LOOPNZоперация.

Общая особенность команд цикла в том, что они используют РОН СХ как счетчик числа циклов, поэтому при их использовании не забудьте до метки_перехода послать в этот регистр нужное число!

Недостаток всех команд цикла в том, что они реализуют только короткие переходы, Для работы с длинными циклами используются команды условного перехода и безусловного перехода. Вот когда у Вас цикл чуть-чуть больше существующих ограничений, есть смысл пересмотреть команды в цикле с целью минимизации их длины!

Для изучения команд цикла на 3-ей лабораторной работе Вам нужно будет разработать программы, близкие к тем, что приведены в листингах 10.3-10.5 (учебник Юрова “Ассемблер)”. Листинг 10.5 показывает, как используются команды засылки счетчика циклов в стек PUSHи восстановления из стекаPOPдля организации вложенных циклов.

TITLE prg_10_3

STACK SEGMENT PARA STACK ‘STACK’

DB 64 DUP(‘STACK’) ; Область стека

STACK ENDS

DSEG SEGMENT PARA PUBLIC ‘DATA’

Mas db 1,0,9,8,0,7,8,0,2,0 ; это заданный одномерный массив байт

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

MOV СX, LEN_MAS ; в сх – счетчик элементов массива

XOR AX,AX

XOR SI,SI

JCXZ EXIT ; проверка сх на 0, если 0, то выход

CYC1: CMP MAS[SI],0 ;сравнить очередной элемент задан. массива с 0

JNE M1 ; если не равно 0, то на m1

INC AL ; увеличение счетчика нулевых элементов

M1: INC SI ; перейти к следующему элементу

LOOP CYC1

EXIT: MOV AX, 4C00H

INT 21H ; возврат управления операционной системе

END START

TITLE prg_10_4

STACK SEGMENT PARA STACK ‘STACK’

DB 64 DUP(‘STACK’) ; Область стека

STACK ENDS

DSEG SEGMENT PARA PUBLIC ‘DATA’

Mas db 1,0,9,8,0,7,8,0,2,0 ; это заданный одномерный массив байт

Len_mas equ 10 ; количество элементов в массиве

MESS1 DB ‘в массиве нет нулевых элементов, $’

MESS2 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 СX, LEN_MAS ; в сх – счетчик элементов массива

XOR AX,AX

XOR SI,SI

JCXZ EXIT ; проверка сх на 0, если 0, то выход

MOV SI, -1 ; готовим SI к адресации элементов MAS

CYC1: INC SI

CMP MAS[SI],0 ;сравнить очередной элемент задан. массива с 0

LOOPNZ CYC1 ; цикл перебора элементов массива

JZ EXIT ; на эту команду попадем, если весь массив просмотрен

и нулевой элемент не обнаружен, либо, если нулевой элемент найден

. . . . .здесь поместить команды выдачи сообщения MESS1

INC SI ; определить номер первого нулевого элемента

EXIT:

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

MOV AX, 4C00H

INT 21H ; возврат управления операционной системе

END START

TITLE prg_10_5

STACK SEGMENT PARA STACK ‘STACK’

DB 64 DUP(‘STACK’) ; Область стека

STACK ENDS

DSEG SEGMENT PARA PUBLIC ‘DATA’

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 10,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 СX, LEN_MAS ; в сх – счетчик элементов строки

CYC2: CMP BYTE PTR [BX+SI],0 ; очередной элемент 0?

JNE NO-ZERO ; если не 0, перейти на метку

MOV BYTE PTR [BX+SI],0FFH ;заменить нулевой элемент

заданным значением

NO_ZERO:

INC SI ; перейти к следующему элементу строки

LOOP CYC2

POP CX ; восстановить счетчик внешнего цикла (номера строки)

ADD BX, LEN_MAS ; перейти к следующей строке

LOOP CYC1

EXIT: MOV AX, 4C00H

INT 21H ; возврат управления операционной системе

END START

Соседние файлы в папке Лекции по ассемблеру