8.1.2. Конвенция С

Данный способ передачи параметров используется в первую очередь в языках С и C++, а также в PROLOG и др. Параметры помещаются в стек в обратном по­рядке, а удаление параметров из стека (в противоположность PASCAL-конвен-ции) выполняет вызывающая процедура:

запись

some_proc(a,b,с,d,е)

превращается в: push e push d

push с

push       b У

push a

call someproc

add        sp, 10      ;   Освободить стек.

Вызванная процедура может инициализироваться следующим образом:

some_proc

proc

 

push

bp

 

mov

bp, sp

;  Создать стековый кадр.

a

equ

Cbp+4]    ;  Определения для

b

equ

[bp+6]

с

equ

[bp+8]

d

equ

[bp+10]

e

equ

[Ьр+12]

[текст процедуры,   использующей параметры а,   Ь,   с,   d, е]

pop bp ret

some_proc endp

Ассемблеры поддерживают и такой формат вызова посредством усложненной формы директивы ргос с указанием языка С:

some_proc proc      С,a:word,b:word,c:word,d:word,e:word

[текст процедуры с параметрами а, Ь, с, d, e. Так как 8Р применяется как ука­затель стекового кадра,   его использовать нельзя! ]

ret

some_proc endp

До сих пор этими формами записи процедур в ассемблере мы не пользовались потому, что они скрывают от нас следующий факт: регистр ВР служит для хране­ния параметров и его ни в коем случае нельзя изменять, а в случае PASCAL ко­манда ret на самом деле - N.

Преимущество по сравнению с PASCAL-конвенцией заключается в том, что освобождение стека от параметров в С возлагается на вызывающую процедуру, а это позволяет лучше оптимизировать код программы. Например, если мы долж­ны вызвать несколько функций, принимающих одни и те же параметры подряд, можно не заполнять стек каждый раз заново:

push param2

push paraml

call prod

call proc2

add sp,4

эквивалентно

prod (parami, param2); proc2(param1,param2);

вот почему компиляторы с языка С создают более компактный и быстрый код не­жели компиляторы с других языков.