}
void swap(void *v[], int i, int j)
{ void *temp;
temp = v[i];
v[i] = v[j];
v[j] = temp;
}
2) Вызов подпрограмм в том числе написанных на разных языках программирования.
Связь между подпрограммами можно осуществить тремя способами:
- через общую зону (EXTERN - C, GLOBAL - Pascal, COMMON - Fortran)/
- через регистры. Используется, если параметров не много, например в программах прерывания.
- через стек.
Для последнего случая необходимо воспользоваться соглашениями о программировании для различных языков.
Языки программирования принято разделять на процедурные (C, Pascal, Fortran, Basic) и непроцедурные (Lisp, Prolog, FORTH). В последних процедуры являются блоками программ, имеющие одну точку входа и одну точку выхода. Ассемблер одинаково легко можно использовать в качестве языка, способного использовать одинаково легко с обоими типами языков программирования.
Процедуры могут получать параметры из вызвавшей процедуры и передовать ей свои результаты с помощью следующих механизмов:
- по назначению , т.е. просто передавать соответствующее значение параметра, которое копируется и таким образом модификация исходного значения становится невозможным. Это используется при передаче иызывающей задаче небольшого чичла параметров, но не массивои.
- По ссылке, тюе передается адрес переменной, по которому процедура читает соответствующий параметр или передает в него некоторый результат, что удобно при передаче массивов.
- По возвращаемому значению, т.е. процедуре передается адрес параметра, а сама процедура делает его копию, что эффективно, если к параметру необходимо обращаться неоднократно, но без модификации его значения.
- По результату, отличается от предыдущего случая тем, что при вызове процедуры предыдущее значение параметра не определяется, а переданный адрес используется только для записи в него результата.
- По имени, т.е. используют макроопределение, например директиву препроцессора C #define.
Для передачи параметров между языками высокого уровня существуют КОНВЕНЦИИ. Большинство языков программирования передают параметры вызывающей программе через СТЕК, а возвращаемое значение получают через определенный регистр. Например, в ПК возвращаемое значение получают через регистр AX (EAX) или через связку регистров DX:AX (EDX:EAX), если результаты не умещаются в одном регистре (например, при передаче адресов). В C значения, хранящиеся в этих регистрах или передаваемые в них устанавливать через макро _AX, _EAX, _DX, _EDX и т.д.
Конвенция PASCAL.
Этот способ применяется также в BASIC, FORTRAN, ADA, MODULA2 и состоит она в том, чтобы параметры помещать в стек в естественном поряде:
Any_proc (int a,int b,int c,int d,int e)
запишется в виде:
push a
push b
push c
push d
push e
call Any_proc
Т.о. по окончании работы процедура Any_proc должна очистить стек до своего завершения. Сами параметры находятся в стеке в обратном порядке:
Any_proc proc
push bp
push bp,sp ; создать описание стека для
; простого доступа к параметрам
a equ [bp+12]
b equ [bp+10]
c equ [bp+8]
d equ [bp+6]
e equ [bp+4]
Завершение процедуры:
pop bp
ret 10
Any_proc endp
Этот код в точности соответствует вызову
Any_proc proc PASCAL a:word,b:word,c:word,d:word,e:word
Главный недостаток данной конвенции в сложности создания функций с переменным числом параметров (например, PRINTF), т.к. для этого сначала надо прочитать первый параметр, что сложно сделать.
Конвенция C.
Эта конвенция используется в языках C, C++, Prolog.
В этой конвенции параметры размещаются в стеке в обратном порядке:
Any_proc (int a,int b,int c,int d,int e)
запишется в виде:
push e
push d
push c
push b
push a
call Any_proc
add sp,10 ; освободить стек
Процедура запишется так:
Any_proc proc
push bp
push bp,sp ; создать описание стека для
; простого доступа к параметрам
a equ [bp+4]
b equ [bp+6]
c equ [bp+8]
d equ [bp+10]
e equ [bp+12]
Завершение процедуры:
pop bp
ret
Any_proc endp
Здесь показан факт, что BP используется для хранения параметров и его нельзя менять.
Преимущество данной конвенции в том, что очичтка стека возлагается на вызывающую процедуру, что обеспечивает оптимизацию программы. Например. Если необходимо вызвать несколько функций подряд, принимающих одни и те же параметры подряд, можно не заполнять стек каждый раз заново:
push param2
push param1
call proc1
call proc2
add sp,4
что эквивалентно
proc1 (param1,param2);
proc2 (param1,param2);
Это и позволяет компилятору C создавать самый компактный и быстрый код.
Известна также смешанная конвенция, когда расположение регистров в стеке аналогично C, но процедуры должны очистить стек по завершению работы сами, как в Pascal. Эта конвенция используется для системных функций WIN32 API.
Очень часто имена процедур изменяют, чтобы подчеркнуть используемую конвенцию. Например,
call _someProc
подчеркивает, что вызов Ассемблера проводится в соответствии с конвенцией C.
Используемую конвенцию программирования можно заказать в Ассемблере, указав соответствующий идентификатор в описании процедур
MODEL
И
PROC.
В языке C можно заказать конвенцию C, PASCAL или передачу параметров через регистры, используя в турбо-языке адрес
OPTION -> COMPILER -> ENTRY/EXIT CODE.
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.