lect_14.ppt
- Количество слайдов: 14
ЛЕКЦИЯ № 12 ПРОЦЕДУРЫ В ЯЗЫКЕ АССЕМБЛЕРА Варианты расположения процедур в одном исходном модуле с основной программой рассмотрены ранее. Когда процедура находится в другом модуле речь уже идет о не об одной программе, а о нескольких. Эти программы должны быть связаны между собой по управлению и по данным. ОРГАНИЗАЦИЯ ИНТЕРФЕЙСА С ПРЦЕДУРОЙ Передача аргументов в модуль • через регистры; • через общую область памяти; • через стек; • с помощью директив extrn и public 1
Передача аргументов через регистры Этот способ прост и удобен при небольшом объеме передаваемых данных. Ограничения: • небольшое число доступных для пользователя регистров; • нужно постоянно помнить о том, какая информация в каком регистре находится; • ограничение размера передаваемых данных (8, 16, 32 бит). При большем размере необходимо передавать не сами данные, а указатели на них. Через регистры часто передаются параметры при вызове функций DOS. 2
; prg_14_3. asm MASM MODEL small ; модель памяти STACK 256 ; размер стека include mac. inc . data ; начало сегмента данных maskd db 71 h ; маска вывода на экран string строка db 'Строка для подсчета $' ; тестовая mes db 'В строке string ' cnt db 2 dup ('*') ; количество символов в строке db ' символов', 10, 13, '$' ; подключение файла с макросами 3
. code main proc ; точка входа в главную процедуру mov ax, @data mov ds, ax ; загрузка адреса строки ; (для передачи смещения в процедуру) lea si, string ; вызов процедуры call Count. Symbol mov cl, bl ; счетчик для lods и stosw lea si, string ; в si - указатель на строку mov ax, 0 b 800 h mov es, ax ; загрузка в es адреса видеопамяти mov ah, maskd ; маска вывода на экран mov di, 160 ; позиция вывода на экран cld ; просмотр вперед - для lodsb и stosw disp: lodsb ; пересылка байта из ds: si в al stosw ; копирование значения ax ; в es: di (видеобуфер) 4 loop disp ; повтор цикла cx раз
; а теперь выведем количество символов в строке mov al, bl aam ; в al две упакованные BCD-цифры ; результата подсчета or ax, 3030 h ; преобразование результата в код ASCII mov cnt, ah mov cnt+1, al Out. Str mes ; вывод строки mes exit: Exit ; макрос выхода main endp ; конец главной процедуры Count. Symbol proc near ; процедура Count. Symbol - подсчёт символов в строке. ; На входе: si - смещение строки ; На выходе: bl - длина в виде упакованного BCD-числа push ax; сохранение используемых регистров push cx cld ; просмотр вперед mov cx, 100 ; максимальная длина строки 5
; блок подсчёта символов go: lodsb ; загрузка символа строки в al cmp al, '$' je endstr jcxz no_end inc bl ; приращение счетчика в bl - количества ; подсчитанных символов в строке loop go ; повтор цикла endstr: ; конец строки pop cx ; восстановление регистров из стека pop ax ret ; возврат из процедуры no_end: ; какие-то действия по обработке ситуации ; отсутствия в строке символа $ ret ; возврат из процедуры Count. Symbol endp ; конец процедуры end main ; конец программы 6
Передача аргументов через общую область памяти Этот способ передачи предполагает, что вызывающая и вызываемая программы «договорились» использовать некоторую область памяти как общую. При этом большое значение имеет атрибут комбинирования сегментов в директивах сегментации. В частности, значение common означает, что все сегменты, имеющие одинаковое имя в объединяемых модулях, будут располагаться компоновщиком, начиная с одного адреса оперативной памяти. Пример: (передача аргументов через общую область памяти) модуль 1 include mac. inc ; подключение файла с макросами stk segment stack db 256 dup (0) stk ends common_data segment para common 'data' ; начало общей области памяти buf 15 DUP (' ') ; буфер для хранения строкиdb temp dw 0 common_data ends 7
extrn Put. Char: far, Put. Char. End: far code segment ; начало сегмента кода assume cs: code, es: common_data main proc mov ax, common_data mov es, ax ; вызов внешних процедур call Put. Char. End push es pop ds _Out. Str buf exit: _Exit ; стандартный выход main endp ; конец главной процедуры code ends end main 8
модуль 2 include mac. inc ; подключение файла с макросами stk segment stack db 256 dup (0) stk ends pdata segment para public 'data' mes db 'Общий сегмент', 0 ah, 0 dh, '$' temp 1 db ? temp 2 dd ? temp 3 dq ? pdata ends public Put. Char, Put. Char. End common_data segment para common 'data' ; начало общей ; области памяти buffer db 15 DUP (' '); буфер для формирования ; строки 9 tmp. SI dw 0 common_data ends
code segment ; начало сегмента кода assume cs: code, es: common_data, ds: pdata Put. Char proc far ; обьявление процедуры cld mov si, 0 mov buffer[si], 'Р' inc si mov buffer[si], 'а' inc si mov buffer[si], 'б' inc si mov buffer[si], 'о' inc si mov buffer[si], 'т' inc si mov buffer[si], 'а' inc si mov buffer[si], 'е' inc si mov buffer[si], 'т' inc si 10 mov buffer[si], '!'
inc mov ret Put. Char. End code ends end si tmp. SI, si ; возврат из процедуры endp ; конец процедуры proc far si, tmp. SI buffer[si], '$' endp Передача аргументов через стек Это самый распространенный способ. Его суть в том, что вызывающая процедура заносит в стек передаваемые данные, после чего производит вызов процедуры. Аргументы располагаются в стеке под адресом возврата. Для осуществления произвольного доступа к данным в стеке предназначен регистр ebp/bp. 11
Перед использованием этого регистра для доступа к данным стека его содержимое необходимо правильно инициализировать, что предполагает формирование в нем адреса, который указывал бы непосредственно на передаваемые данные. Для этого в начало процедуры рекомендуется включить дополнительный фрагмент кода – так называемый пролог процедуры. Пример: ( вызов процедуры с передачей аргументов через стек) masm model small … proc 1 proc near ; начало пролога push bp mov bp, sp ; конец пролога mov ax, [bp+4] ; доступ к последнему аргументу mov ax, [bp+6] ; доступ к предпоследнему аргументу … ; команды процедуры 12
; подготовка к выходу из процедуры ; начало эпилога mov sp, bp ; восстановление sp pop bp ; восстановление старого значения bp ; (до входа в процедуру) ret ; возврат в вызывающую программу ; конец эпилога proc 1 endp. code main proc mov ax, @data ds, ax push arg 1 … ; запись в стек 1 –го аргумента … push argn ; запись в стек последнего аргумента call proc 1 ; действия по очистке стека после возврата из процедуры … 13
exit: _exit main endp end main Способы удаления из стека аргументов после окончания вызова процедуры: • используя последовательность из n команд pop xx. Лучше всего это делать в вызывающей программе сразу после возврата управления из процедуры; • откорректировать регистр sp на величину 2*n, например, командой sp, NN, где NN=2*n, и n – число аргументов; add • используя машинную команду ret n в качестве последней исполняемой команды в процедуре, где n – количество байт, на которое нужно увеличить содержимое регистра esp/sp после того, как с вершины стека будут сняты составляющие адреса возврата. В качестве аргументов могут передаваться сами данные или их адреса (указатели на данные). В языках высокого уровня это называется передачей данных по значению и по адресу. 14
lect_14.ppt