ПЕРЕДАЧА ПАРАМЕТРОВ В ПРОЦЕДУРУ

Команды возврата

СТРУКТУРА ПОДПРОГРАММЫ

КОМАНДЫ ВЫЗОВА ПОДПРОГРАММ CALL

КОМАНДЫ ПЕРЕХОДОВ LOOPZ, LOOPE

КОМАНДА ЦИКЛА LOOP

Loop met

┌─────┐

│CX:=n│

└──┬──┘

┌──────>х met:

│ ┌──┴──┐

│ │тело │

│ │цикла│

│ └──┬──┘

│ ┌────┴────┐

│ │CX:=CX-1 │

│ └────┬────┘

│ нет / ^\ да

└────/CX=0\────┐

\ / │

\/ │

v

 

Команда Loop не проверяет и не изменяет значения флагов, она только уменьшает регистр СХ на единицу и сравнивает последний с нулём.

 

Пример: подсчитать сумму элементов массива.

 

x db 10 dup(?)

n dw ?

 

sub ax,ax

lea bx,x

mov cx,n

m:

add al,[bx]

inc bx

loop m

 

 

 

Мнемоники различны, но команда одна и та же:

Loopz met ( Loope met)

 

┌──────────────┤ MET:

│ ┌──────┴──────┐

│ │тело цикла с │

│ │формированием│

│ │ ZF │

│ └──────┬──────┘

│ ┌──────┴──────┐

│ │ CX := CX-1 │

│ └──────┬──────┘

│ / \ да

│ /ZF=1 \──────────┐

│ \ / │

│ \/ │

│ │ │

│ нет / \ да │

└───────────/CX=0 \─────┬────┘

\ / │

\/ v

 

Команда имеет дополнительный выход из цикла, по значению ZF=1.

 

В массиве Х определить первый элемент, значение которого = 5.

X DW 10 DUP (?)

N DW ?

NOM DW ?

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

 

X ┌─────┬─────┬─────┬───────────┬─────┐

│X1=-1│ X2=2│ X3=5│ ......... │ Xn │

└──┴──┴──┴──┴──┴──┴───────────┴──┴──┘

 

Просмотр массива будет завершен после определения X3 = 5

mov cx,n

mov si,-2

met:

inc si

inc si

cmp [si],5

loopz met

jnz m1 ;в массиве нет элементов равных 5

;SI := (nom-1)*size(x)

;nom:= SI/2 +1

;после выхода из цикла

;SI указывает на исходный элемент

shr si,1

inc si

mov nom,si

jmp kon

m1: ;выдача сообщения 'в массиве нет элементов, равных 5'

 

КОМАНДЫ ПЕРЕХОДОВ LOOPNZ, LOOPNE содержат дополнительный выход из цикла при ZF=0. С помощью этой команды можно найти первый элемент массива, который <> заданному.

Команд цикла, которые проверяют условия >= и <= нет, для этого случая требуется самостоятельно организовывать доп. выход из тела цикла.

 

 

 

CALL < имя подпрограммы >

 

7 0 7 0 7 0

┌───────┐ ┌───────┐ ┌───────┐

│ KOP │ │dispL │ │ dispH │

└───────┘ └───────┘ └───────┘

\ /

смещение адреса относительно текущей команды

 

CALL OP ;OP определяет адрес входа в п/п

ALL disp ;прямой внутрисегментный вызов п/п

 

1) SP:= SP – 2

2) IP:= [SP]

3) disp --> IP

 

 

 

N_proc proc near

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

; имя директива внутрисегментная

; любая последовательность команд

; к-во push & pop должно быть одинаковым

ret

N_proc endp

 

 

 

RET – внутресегментный возврат

 

KOP = C3

1) [SP]--> IP

2) SP:= SP-2

 

RET – внешнесегментный возврат

 

1) [SP]--> IP

2) SP:= SP+2

3) [SP]--> CS

4) SP:=SP+2

 

 

1) Через общее поле памяти

DSEG SEGMENT

A DB 10 DUP (?)

N DW ?

DSEG ENDS

CSEG SEGMENT

MAIN PROC FAR

.........................

MAIN ENDP

P1 PROC NEAR

.........................

P1 ENDP

CSEG ENDS

END MAIN

Данные, описанные в DSEG доступны из любой точки программы ассемблера, отсюда и название – «передача данных в процедуру через общее поле памяти». В нашей программе обработка массива А может осуществляться с одинаковым успехом в процедурах MAIN и P1. На Паскале такой способ называют «передача параметров в процедуру через аппарат глобальных переменных», а именно: в описанной процедуре параметры отсутствуют.

На Паскале используют вложенные процедуры. Переменные внутри процедуры локальные, т.е. не доступные для других процедур.

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

 

MAIN PROC FAR

.............

CALL P1

.............

JMP OBHOD

P1 PROC NEAR

; тело процедуры

P1 ENDP

OBHOD: .............

MAIN ENDP

 

2) Передача параметров через регистры.

 

Пусть процедура выполняет операцию: С = А + В

 

MOV AX,A

MOV BX,B

CALL PSUM

MOV C,AX

 

PSUM PROC NEAR

ADD AX,BX

RET

PSUM ENDP

Параметры процедуры делят на входные и выходные. В данном примере входные параметры: регистры AX и BX, выходные – регистр AX.

Данный способ является самым быстрым, однако не основным, т. к. регистров в МП не очень много.

 

3) Передача параметров через стек.

 

A¤-B¤-3

x = ────── A,B – слова

(A-B)*5

 

А,В – входные параметры

АХ – результат

 

В процедуре для промежуточных результатов обычно используются свободные регистры, например нам потребовались регистры AX,BX,CX,DX,SI. В процедуре все используемые регистры, кроме регистра, через который передаются параметры, целесообразнее сохранять на стек, т. к. эти же регистры могли быть использованы в вызывающей программе.

 

SP────┐ ┌────BP

├────┤

+0 │ SI │ ...........................

├────┤ PUSH A

+2 │ DX │ PUSH B

├────┤ CALL P2 ;вызов

+4 │ CX │ MOV X,AX ;процедуры

├────┤ ...........................

+6 │ BX │

├────┤

+8 │ IP │

├────┤

+10 │ A │

├────┤

+12 │ B │

├────┤

│ │

└────┘

P2 PROC NEAR

PUSH BX

PUSH CX

PUSH DX

PUSH SI

MOV BP,SP ;прямой доступ к стеку

MOV AX,[BP+12] ;AX:=A

MOV BX,[BP+10] ;BX:=B

;вычисление формулы

;результат в AX

;восстановление регистров

POP SI

POP DX

POP CX

POP BX

; после этих действий SP указывает на адрес возврата

RET 4

; команда RET с параметром работает аналогично обычной

; команде RET, т.е. выполняет операцию POP IP, одна-

; ко в стеке остаются 2 параметра А и В, которые необ-

; ходимо удалить со стека. Дополнительное действие

; команды состоит в следущем: SP := SP + 4.

; После выхода из процедуры SP будет указывать на

; ячейку, лежащую ниже А

P2 ENDP

Если не использовать параметры в команде RET, то вызов процедуры будет иметь вид:

 

PUSH A

PUSH B

CALL P2

MOV X,AX

; в стеке лишние 2 слова

POP AX

POP AX

В одномерном массиве поменять местами 1-й положительный и последний отрицательный.

┌───┬───┬───┬───┬───┬───┐

│ 0 │ 2 │ 4 │-8 │-16│ 3 │

└───┴───┴───┴───┴───┴───┘

SI = 0 – начальное значение

DI:= (N-1) size X

MOV CX,N

MOV SI,0

M1: CMP X[SI],0

JG M2

INC SI

INC SI

LOOP M1

GCXZ N_P_E ;переход, если CX = 0

;найден положительный элемент

MOV CX,N

MOV DI,N

DEC DI

SHL DI,1 ;DI:=DI*2

M4: CMP X[DI],0

JL M5

DEC DI

DEC DI

LOOP M4

M5: JCXZ N_NEG_E

MOV AX,[SI]

MOV BX,[DI]

MOV [SI],BX

MOV [DI],AX

JMP KON

N_P_E: LEA DX,MSG1

MOV AH,9

INT 21h

JMP KON

N_NEG_E: LEA DX,MSG2

MOV AH,9

INT 21h

KON: RET