Prezent61

реклама
Работа со стеком. Стековые передачи
•
•
•
PUSH op
; (E)SP - 2 (4) в зависимости от атрибута размера адреса use16 или use32,
op – mem, reg, 16, 32 разряда ; op  [ SS: SP (ESP) ], помещает операнд в вершину стека.
Непосредств. оп. 8,16,32 бита ; 8 –ми битовый операнд расширяется до 16 (32) бит.
Пр.
PUSH AX
push word ptr MEM
push esp
; включает в стек то значение ESP (SP), которое было до
выполнения команды ( для i8086 push sp – новое- (SP-2).
PUSH A ; включает в стек содержимое регистров AX, CX, DX, BX, SP, BP, SI, DI
PUSHAD ; “------” EAX, EBX, ……., EDI
PUSHF ; SP – 2: FLAGS  [SS: SP]
PUSHFD ; ESP – 4 ; EFLAGS  [ SS: ESP ]
Выполнение команды PUSH и её разновидностей не влияет на флаги в FLAGS.
Команды извлечения из стека
•
•
•
•
•
•
•
POP op ; [ SS: SP (ESP) ]  op , SP (ESP) + 2 (4).
op – mem, reg 16, 32 бита ; содержимое из вершины стека помещается в операнд (16, 32) ,
указатель стека увеличивается на 2 ( 4 ).
POPA
; извлечение из стека в DI, SI, BP, SP, BX, DX, CX, AX (обратно PUSHA )
POPAD ; извлече6ние из стека в EDI, ESI, ……, ECX, EAX ( обратно PUSHAD )
POPF
; [ SS: SP(ESP) ]  FLAGS , SP(ESP) +2; ( обратно ком. PUSHF )
POPFD
; [ SS: ESP]  EFLAGS , ESP + 4; ( обратно ком. PUSHFD )
•
Поскольку стек работает в режиме LIFO ( last input – first output ) , то при записи и выборке
из стека это необходимо учитывать:
•
•
•
•
•
•
•
•
P1
PROC
push ax
push ds
…..
……
pop ds
pop ax
P1 ENDP
Атрибутные операторы, возвращающие значение
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
LENGTH <имя переменной> ; возвращает число единиц переменных в конструкции DUP,
если она является первым операндом после DB, DW, DD и
1 в остальных случаях.
SIZE < имя переменной > ; возвращает число байт, соответствующих массиву.
OFFSET < метка или переменная > ; Возвращает эффективный адрес (полное смещение в
сегменте).
SEG < метка или переменная > ; Возвращает соответствующий сегментный адрес.
Пример:
data segment para public ‘d1’
A dw 125
B dw 100 DUP (?)
data ends
code segment ‘c1’
…………….
mov cx, LENGTH B ; cx = 100
mov dx, SIZE B
; dx = 200
mov bx , offset B
; bx = 2 ( lea bx, B )
mov ax , seg B
; ax = data ( адрес сегмента из ds )
…………….
Процедуры
• Это некоторая последовательность действий, которая может быть выделена как
самостоятельная программа, и к которой можно обращаться из любого места программы
любое число раз ( аналог п/п или функций в ЯВУ).
• В основной программе процедуры обычно размещают либо в начале сегмента кода перед
командой, с которой начинается программа ( точка входа), либо в конце сегмента команд.
• Описание процедур: имя PROC < дистанция >
•
< тело процедуры >
•
имя ENDP
• Имя процедуры ассемблер как метку на первую команду процедуры. Процедура может
быть описана как ближняя ( NEAR ) в поле дистанции или дальняя ( FAR ). К процедурам
типа NEAR можно обращаться только из того сегмента кода, где она описана, а к процедурам
типа FAR из любого сегмента кода. По умолчанию процедура считается ближней ( NEAR ) .
Имена и метки, описанные в процедуре не локализуются внутри её, т.е. Не должны совпадать
с другими идентификаторами программы. В больших программах процедуры часто
размещают в отдельных сегментах кода и к ним обращение осуществляется через полный
указатель ( CS:IP(EIP) – дальний указатель FAR ).
• Обращение к процедурам можно осуществлять с помощью команды безусловного перехода
(JAMP near ( far)), предварительно предусмотрев передачу параметров и точку возврата в
вызывающую программу. Для упрощения работы с процедурами в систему команд
процессора включены команды вызова ( CALL ) возврата из процедуры ( RET ).
Команды вызова и возврата процедур
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
Относятся к командам безусловной передачи управления. Вызовы выполняются так же как
и командой JAMP, но вначале они запоминают текущее значение указателя команд (IP(EIP),
или CS:IP(EIP) в стеке, что позволяет вернуть управление из процедуры на следующую
команду после CALL. Команды возвратов осуществляют эту передачу управления,
восстанавливая из стека адрес точки возврата в указателе команды. Вызовы и возвраты –
средства организации процедур. Так же, как и команда переходов, вызовы и возвраты
бывают двух видов: внутрисегментные и межсегментные.
Форматы команд:
CALL < метка > ; внутрисегментный прямой вызов, SP=SP-2; IP  [SS:SP]; IP+ met  IP
met – смещение между меткой и командой после CALL.
CALL word ptr MEM ; внутрисегментный косвенный вызов, SP=SP-2; IP  [SS:SP]; в MEM
эффективный адрес (смещение) к имени процедуры. [MEM]  IP.
CALL far <метка> ; межсегментный прямой вызов, SP=SP-2; CSSS:SP; SP=SP-2,
IP  SS:SP; IP  offset <метка>, CS  seg < метка >.
CALL dword ptr MEM1 ; межсегментный косвенный вызов, SP=SP-2; CSSS:SP; SP=SP-2,
IP  SS:SP; IP  [MEM1], CS  [MEM1+2].
RET
; Внутрисегментный возврат, [SS:SP]  IP, SP = SP+2.
RET n
; Внутрисегментный возврат, [SS:SP]  IP, SP = SP+2, SP= SP+n.
RET
; межсегментный возврат, [SS:SP]  IP, SP = SP+2, [SS:SP]  CS, SP = SP+2.
RET n ; межсегментный возврат, [SS:SP]  IP, SP = SP+2; [SS:SP]  CS, SP = SP+2+n.
Передача параметров процедур
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
Можно разделить на две группы:
1) В каком виде их передаём:
- по значению,
- по ссылке ( передача адреса)
2) Через чего передаётся , т.е. Где размещаются параметры перед вызовом процедуры:
- регистры,
- память.
Передача параметров через регистры – самый простой способ, при этом процедура не будет
тратить время на извлечение их из памяти.
Пример: mov ax, A
mov bx, offset mas1
call proc12
Память – чаще всего используется передача параметров через стек, особенно когда
параметров много.
Пример2: push A
push offset mas1
call proc11
В этом случае после передачи управления процедуре proc11 в вершине стека будет
находиться адрес точки возврата (значение IP), по адресу [SP+2]  offset mas1, а по адресу
[SP+4]  значение переменной А.
Локальные переменные процедур
• Если по алгоритму в процедуре требуются локальные переменные, то место под них, как
правило отводятся в стеке.
• Пример: Пусть требуется выделить память в стеке под m переменных длиной WORD
•
pr1 proc
•
push bp
•
mov bp, sp
•
sub sp, m*2
•
mov [bp-2], 100
•
………
•
mov sp, bp
•
pop bp
•
ret
•
pr1 endp
• Таким образом доступ к локальным переменным осуществляется через регистр bp.
• Все действия программы, связанные с подготовкой стека для работы с процедурой
называются прологом, а все действия, которые выполняются по восстановлению регистров и
освобождению стека, называются эпилогом.
Модульное программирование
• Под модулем понимается часть программы, решающая некоторую задачу, и которая может
быть оттранслирована отдельно. Частным случае модуля может служить процедура.
Существует два основных способа объединения модулей:
• 1. Все модули объединяются в одну программу, которая проходит этапы компиляции и
редактирования связей ( т.е. имеют одинаковое имя сегмента кода и тип public).
M1
M2
Компиляция MASM
Редактирование LINK
M.exe
M3
2. Модули пишутся и компилируются раздельно. Объединяются на этапе редактирования
M1
Компиляция MASM
M2
Компиляция MASM
M3
Компиляция MASM
Редактирование LINK
M.exe
Структура любого модуля близка к структуре программы, то есть это последовательность
• предложений, оканчивающаяся директивой END. У головной программы END с именем
точки входа. Все имена в модуле локализуются.
• Для связи переменных и меток из разных модулей существуют две директивы. Для указания
внешних переменных и меток предназначена директива EXTRN:
• Формат:
EXTRN < имя >: < тип >, …, < имя > : < тип >
• Где тип – BYTE, WORD, DWORD – для внешних переменных, NEAR, FAR – для меток и
имен процедур, ABS – стандартная константа со значением 0. Данная директива может
указываться любое число раз в любом месте модуля.
• Например: EXTRN A: WORD, PR1: FAR, K: ABS
• Чтобы имена и метки были доступны из модулей, где они описаны, необходимо
использовать директиву PABLIC < имя >, …, < имя >
• Пример:
Модуль1
Моддуль2
•
extrn A1: WORD, B1: FAR
DATA segment
•
code segment
A1 DW 55
•
……….
DATA ends
•
mov ax, A1
public A1, B1
•
……….
……….
•
call B1
B1 proc far
•
……..
……….
•
code ends
B1 endp
Скачать