передача аргументов в процедуры и функции
Участников: 3
Страница 1 из 1
передача аргументов в процедуры и функции
Глава о том как передать данные в функцию и что с этим можно будет сделать дальше.
В этой главе, под словом "процедура" понимаються любые из конструкций
function ... end function функции
sub ... end sub процедуры
property ... end property
constructor ... end constructor
Так будет проще, чтобы не перечислять их каждый раз. Ведь правила передачи аргументов для них одинаковые.
Передаваемые аргументы могут быть любого типа. Их набор может быть фиксирован или же произволен.
В строке 2, где объявляется наша процедура, в круглых скобочках указываем имя аргументов и тип данных.
Имя аргумента это новая переменная. которая существует только внутри функции. Имя аргумента не зависит от имён переменных, которые передают значение, но имеет тоже самое значение.
Не имеет значения , что мы передаём переменную с именем "p1" или "p2", в процедуре к ней надо будет всё равно обращаться, по имени, которое указано при описании этой процедуры.
В нашем случае это "a" и "b".
byRef и byVal [/i]
Аргументы можно передать двумя способами, по ссылке или значению. КАкой способ используется по умолчанию зависит от настроек. По сему рекомендую задавать его в обязательном порядке.
Делается это с помощью ключевых слов
byVal - по значению
byRef - по ссылке
Разница заключается в том, что byVal, копирует значение в аргумент. В процедуре или функции вы можете изменять его, но на оригинальную переменную это не повлеяет.
А указав byRef мы берём ссылку на оригинальное значение. Изменяя значения аргумента, вы изменяете значение параметра.
Вот посмотрите пример
Программа вернёт
Как видим, с оригинальным значением p1 ничего не случилось. Оно было 123. А то что в процедуре аргумент был изменён, на оригинальное значение не повлеяло.
Значение переменной p2 456, передавалось по ссылке. Оно было изменено в процедуре.
По этому, после завершения процедуры переменная p2 уже содержит 0.
[b] передача массива в функцию
Массив передаётся только по ссылке. Обязательно нужно указать пустые круглые скобочки. после имени массива. Указывать ключевые слова byVal и byRef не допускаеться.
передача указателей
Вы думаете указатели будут обрабатыватся по особенному. Ну зачем же такие сложности. Указатель это переменная с каким-то значением и только.
указатель передаётся точно так же, как из правой части в левую при присвоении. Если вам будет легче, считайте его как число uinteger.
сколько допустимо аргументов
В функцию могут передаваться несколько аргументов. Сколько вы запросите при объявлении функции, столько и будет.
Можно вообще не принимать аргументов. Просто укажите пустые скобочки после имени функции.
Если же несколько аргументов, то их нужно перечислить через запятую.
Эта функция требует 3 аргумента. При её вызове ей нужно передавать 3 параметра. Не больше и не меньше. Это обязательно!
Параметры также, перечесляем через запятую.
Существует возможность передавать неопределённое число аргументов, но об этом поговорим дальше.
аргумент по умолчанию
Число передаваемых параметров можно и уменьшить. Допустим, что один из параметров меняеться только в исключительных ситуациях.
В этом примере третий аргумент (poryadok) являеться не обязательным. Мы задали его значение по умолчанию. Если параметр был опущен, то аргумент примет значение по умолчанию.
Значение по умолчанию указываеться после знака равенства.
function fulName( poryadok as integer = 0)
Обратите внимание, на то что аргументы со значением по умолчанию должны быть с права, а аргументы без с лева. Иначе будет ошибка.
переменное число аргументов
У функции может быть переменное число аргументов.
Переменное число аргументов разрешено только для функций cdecl .
Первым аргументом должно быть обычное значение. С помощью него можно указать сколько других аргументов передано в функцию.
Инициировать нужно с помощю функции va_first
Получаем аргумент с помощью va_arg
перейти к следующему аргументу va_next
будет выведено:
3.925
259.927405
Большинство языков высокого уровня передают параметры вызываемой процедуре в стеке и ожидают возвращения параметров в регистре AX (EAX). иногда используется DX:AX (EDX:EAX), если результат не умещается в одном регистре и ST(0), если результат - число с плавающей запятой.
Конвенция Pascal
Самый очевидный способ вызова процедуры или функции языка высокого уровня, после того как решено, что параметры передаются в стеке и возвращаются в регистре AX/EAX, - это способ, принятый в языке Pascal, - просто поместить параметры в стек в естественном порядке:
запись
some_proc(a, b, c, d, e)
превращается в:
push a
push b
push c
push d
push e
Это означает, что процедура some_proc, во-первых, должна очистить стэк по окончании работы (например, завершившиськомандой ret 10) и, во-вторых, параметры, переданные ей, находятся в стэке в обратном порядке:
some_proc proc
push bp
mov bp, sp ; создать стековый кадр
a equ [bp+12] ; определения для простогодоступа к параметрам
b equ [bp+10]
c equ [bp+8]
d equ [bp+6]
e equ [bp+4]
[текст процедуры, использующей параметры a, b, c, d, e]
pop bp
ret 10
some_proc endp
Главный недостаток этого подхода заключается в сложности создания функции с изменяемым числом параметров. Чтобы определить число параметров, процедура должна сначала прочитать первый параметр, но она не знает его расположения в стэке. Эту проблему решает подход, используемый в C, где параметры передаются в обратном порядке.
Конвенция C
Данный способ передачи параметровиспользуется в первую очередь в языках C и C++. Параметры помещаются в стек в обратном порядке, а удаление из стека (в противоположность Pascal-конвенции) выполняет вызывающая процедура:
запись
some_proc(a, b, c, d, e)
превращается в:
push e
push d
push c
push b
push a
call some_proc
add sp, 10 ; освободить стек
Вызванная процедура может инициализироваться следующим образом:
some_proc proc
push bp
mov bp, sp ; создать стековый кадр
a equ [bp+4] ; определения для простого доступа к параметрам
b equ [bp+6]
c equ [bp+8]
d equ [bp+10]
e equ [bp+12]
[текст процедуры, использующей параметры a, b, c, d, e]
pop bp
ret
some_proc endp
Преимущество по сравнению с Pascal-конвенцией заключается в том, что освобжнеие стека от параметров в C возлагается на вызывающую процедуру, а это позволяет лучше оптимизировать код программы. Например, если мы должны вызывать несколько функций, принимающих одни и те же параметры подряд, можно не заполнять стек каждый раз заново:
push param1
push param2
call proc1
call proc2
add sp, 4
эквивалентно
proc1(param1, param2);
proc2(param1, param2);
вот почему компиляторы с языка C создают более компактный и быстрый код нежели компиляторы с других языков.
Смешанные конвенции
Существует также конвенция STDCALL, отличающаяся и от C, и от PASCAL-конвенций, которая применяется для всех системных функций Win32 API. Здесь параметры помещаются в стект в обратном порядке, как в C, но процедуры должны очищать стек сами, как в PASCAL.
Искажение имён
Компиляторы Microsoft C (а также многие компиляторы UNIX), изменяют названия процедур, чтобы отразить используемый способ передачи параметров. Так, к названиям всех процедур, применяющих C-конвенцию, добавляется символ подчёркивания. То есть, если в C-программе записано
some_proc();
то реально компилятор пишет
call _some_proc
и это означает: если процедура написана на ассемблере, она должна называться именно _some_proc.
Названия процедур, использующих STDCALL, искажаются ещё более сложным образом: слева к названию процедуры добавляется символ подчёркивания, а сзади — сивол @ и размер области стека в байтах, которую занимают параметры (то есть число, стоящее после команды ret в конце процедуры)
some_proc(a:word);
превращается в
push a
call _some_proc@4
см. также:
процедуры, функции и свойства
возвращение данных из функции
область видимости
В этой главе, под словом "процедура" понимаються любые из конструкций
function ... end function функции
sub ... end sub процедуры
property ... end property
constructor ... end constructor
Так будет проще, чтобы не перечислять их каждый раз. Ведь правила передачи аргументов для них одинаковые.
Передаваемые аргументы могут быть любого типа. Их набор может быть фиксирован или же произволен.
- Код:
' передача параметра
' тестовая процедура
sub foot( a as integer, b as integer )
' первый аргумент
print "a = "; a
' второй аргумент
print "b = "; b
end sub
' вызываем процедуру с параметрами
foot 5, 8
В строке 2, где объявляется наша процедура, в круглых скобочках указываем имя аргументов и тип данных.
- Код:
sub foot( a as integer, b as integer )
Имя аргумента это новая переменная. которая существует только внутри функции. Имя аргумента не зависит от имён переменных, которые передают значение, но имеет тоже самое значение.
- Код:
' пример передачи переменной
' тестовая процедура
sub foot( a as integer, b as integer )
' первый аргумент
print "a = "; a
' второй аргумент
print "b = "; b
end sub
' переменные
dim p1 as integer = 123
dim p2 as integer = 456
' вызываем процедуру с параметрами
foot p1, p2
Не имеет значения , что мы передаём переменную с именем "p1" или "p2", в процедуре к ней надо будет всё равно обращаться, по имени, которое указано при описании этой процедуры.
В нашем случае это "a" и "b".
byRef и byVal [/i]
Аргументы можно передать двумя способами, по ссылке или значению. КАкой способ используется по умолчанию зависит от настроек. По сему рекомендую задавать его в обязательном порядке.
Делается это с помощью ключевых слов
byVal - по значению
byRef - по ссылке
Разница заключается в том, что byVal, копирует значение в аргумент. В процедуре или функции вы можете изменять его, но на оригинальную переменную это не повлеяет.
А указав byRef мы берём ссылку на оригинальное значение. Изменяя значения аргумента, вы изменяете значение параметра.
Вот посмотрите пример
- Код:
' тестовая процедура
sub foot( byVal a as integer, byRef b as integer )
' первый аргумент
print "a = "; a
' второй аргумент
print "b = "; b
' обнуляем оба аргумента
a = 0
b = 0
end sub
' переменные
dim p1 as integer = 123
dim p2 as integer = 456
' напечатаем переменные до вызова процедуры
print p1, p2
' вызываем процедуру с параметрами
foot p1, p2
' напечатаем переменные после процедуры
print p1, p2
Программа вернёт
123 456
a = 123
b = 456
123 0
Как видим, с оригинальным значением p1 ничего не случилось. Оно было 123. А то что в процедуре аргумент был изменён, на оригинальное значение не повлеяло.
Значение переменной p2 456, передавалось по ссылке. Оно было изменено в процедуре.
По этому, после завершения процедуры переменная p2 уже содержит 0.
[b] передача массива в функцию
Массив передаётся только по ссылке. Обязательно нужно указать пустые круглые скобочки. после имени массива. Указывать ключевые слова byVal и byRef не допускаеться.
- Код:
' передача массива
' создадим массив
dim a(1 to 10) as integer
a(10) = 1000
function myfunc3(b() as integer) as integer
print b(10)
b(1) = 111
b(2) = 222
b(3) = 333
end function
myfunc3( a() )
' выведем все значения массива
dim i as integer
for i = 1 to 10
print a(i)
next
sleep
передача указателей
Вы думаете указатели будут обрабатыватся по особенному. Ну зачем же такие сложности. Указатель это переменная с каким-то значением и только.
указатель передаётся точно так же, как из правой части в левую при присвоении. Если вам будет легче, считайте его как число uinteger.
сколько допустимо аргументов
В функцию могут передаваться несколько аргументов. Сколько вы запросите при объявлении функции, столько и будет.
Можно вообще не принимать аргументов. Просто укажите пустые скобочки после имени функции.
- Код:
function myfunc0() as integer
end function
Если же несколько аргументов, то их нужно перечислить через запятую.
- Код:
function fTrio( a as integer, b as integer, c as integer ) as integer
end function
Эта функция требует 3 аргумента. При её вызове ей нужно передавать 3 параметра. Не больше и не меньше. Это обязательно!
- Код:
fTrio( 1, 2, 3 )
Параметры также, перечесляем через запятую.
Существует возможность передавать неопределённое число аргументов, но об этом поговорим дальше.
аргумент по умолчанию
Число передаваемых параметров можно и уменьшить. Допустим, что один из параметров меняеться только в исключительных ситуациях.
- Код:
' функция печатает имя и фамилию.
function fullName( FirstName as string, lastName as string, poryadok as integer = 0) as integer
if poryadok = 0 then
' в правильном порядке (вариант по умолчанию)
print firstName + " " + lastName
else
' если требуеться другой порядок
print lastName + " " + firstName
end if
return 0
end function
FullName("Ivan", "Ivanovich", 0) ' вывести в правильном порядке
fullName("Mihail", "Sergeevich") ' третий параметр (0), подразумеваеться, но не указываеться, а вообще он не важен
fullName("Vasya", "Pupkin", 1) ' вывести задом наперёд
В этом примере третий аргумент (poryadok) являеться не обязательным. Мы задали его значение по умолчанию. Если параметр был опущен, то аргумент примет значение по умолчанию.
Значение по умолчанию указываеться после знака равенства.
function fulName( poryadok as integer = 0)
Обратите внимание, на то что аргументы со значением по умолчанию должны быть с права, а аргументы без с лева. Иначе будет ошибка.
переменное число аргументов
У функции может быть переменное число аргументов.
- Код:
Function FOO cdecl (X As Integer, ...) As Integer
end function
Переменное число аргументов разрешено только для функций cdecl .
Первым аргументом должно быть обычное значение. С помощью него можно указать сколько других аргументов передано в функцию.
Инициировать нужно с помощю функции va_first
Получаем аргумент с помощью va_arg
перейти к следующему аргументу va_next
- Код:
Function Avg cdecl (Count As Integer, ... ) As Double
Dim ARG As Any Ptr
Dim SUM As Double = 0
Dim i As Integer
ARG = va_first()
For i = 1 To COUNT
SUM += va_arg(ARG, Double)
ARG = va_next(ARG,Double)
Next i
Return SUM/COUNT
End Function
Print AVG (4, 3.4,5.0,3.2,4.1)
Print AVG (2, 65.2,454.65481)
будет выведено:
3.925
259.927405
Большинство языков высокого уровня передают параметры вызываемой процедуре в стеке и ожидают возвращения параметров в регистре AX (EAX). иногда используется DX:AX (EDX:EAX), если результат не умещается в одном регистре и ST(0), если результат - число с плавающей запятой.
Конвенция Pascal
Самый очевидный способ вызова процедуры или функции языка высокого уровня, после того как решено, что параметры передаются в стеке и возвращаются в регистре AX/EAX, - это способ, принятый в языке Pascal, - просто поместить параметры в стек в естественном порядке:
запись
some_proc(a, b, c, d, e)
превращается в:
push a
push b
push c
push d
push e
Это означает, что процедура some_proc, во-первых, должна очистить стэк по окончании работы (например, завершившиськомандой ret 10) и, во-вторых, параметры, переданные ей, находятся в стэке в обратном порядке:
some_proc proc
push bp
mov bp, sp ; создать стековый кадр
a equ [bp+12] ; определения для простогодоступа к параметрам
b equ [bp+10]
c equ [bp+8]
d equ [bp+6]
e equ [bp+4]
[текст процедуры, использующей параметры a, b, c, d, e]
pop bp
ret 10
some_proc endp
Главный недостаток этого подхода заключается в сложности создания функции с изменяемым числом параметров. Чтобы определить число параметров, процедура должна сначала прочитать первый параметр, но она не знает его расположения в стэке. Эту проблему решает подход, используемый в C, где параметры передаются в обратном порядке.
Конвенция C
Данный способ передачи параметровиспользуется в первую очередь в языках C и C++. Параметры помещаются в стек в обратном порядке, а удаление из стека (в противоположность Pascal-конвенции) выполняет вызывающая процедура:
запись
some_proc(a, b, c, d, e)
превращается в:
push e
push d
push c
push b
push a
call some_proc
add sp, 10 ; освободить стек
Вызванная процедура может инициализироваться следующим образом:
some_proc proc
push bp
mov bp, sp ; создать стековый кадр
a equ [bp+4] ; определения для простого доступа к параметрам
b equ [bp+6]
c equ [bp+8]
d equ [bp+10]
e equ [bp+12]
[текст процедуры, использующей параметры a, b, c, d, e]
pop bp
ret
some_proc endp
Преимущество по сравнению с Pascal-конвенцией заключается в том, что освобжнеие стека от параметров в C возлагается на вызывающую процедуру, а это позволяет лучше оптимизировать код программы. Например, если мы должны вызывать несколько функций, принимающих одни и те же параметры подряд, можно не заполнять стек каждый раз заново:
push param1
push param2
call proc1
call proc2
add sp, 4
эквивалентно
proc1(param1, param2);
proc2(param1, param2);
вот почему компиляторы с языка C создают более компактный и быстрый код нежели компиляторы с других языков.
Смешанные конвенции
Существует также конвенция STDCALL, отличающаяся и от C, и от PASCAL-конвенций, которая применяется для всех системных функций Win32 API. Здесь параметры помещаются в стект в обратном порядке, как в C, но процедуры должны очищать стек сами, как в PASCAL.
Искажение имён
Компиляторы Microsoft C (а также многие компиляторы UNIX), изменяют названия процедур, чтобы отразить используемый способ передачи параметров. Так, к названиям всех процедур, применяющих C-конвенцию, добавляется символ подчёркивания. То есть, если в C-программе записано
some_proc();
то реально компилятор пишет
call _some_proc
и это означает: если процедура написана на ассемблере, она должна называться именно _some_proc.
Названия процедур, использующих STDCALL, искажаются ещё более сложным образом: слева к названию процедуры добавляется символ подчёркивания, а сзади — сивол @ и размер области стека в байтах, которую занимают параметры (то есть число, стоящее после команды ret в конце процедуры)
some_proc(a:word);
превращается в
push a
call _some_proc@4
см. также:
процедуры, функции и свойства
возвращение данных из функции
область видимости
Последний раз редактировалось: Eric-S (Вт Сен 08, 2009 5:16 pm), всего редактировалось 5 раз(а)
Re: передача аргументов в процедуры и функции
Ещё раз, спасибо, за критику, главу исправил.
О скобках. Первые три примера, компилятор не ругался. Всё нормально откомпилировал.
Возможно, что он будет ругаться если в функции есть return?
А кстати, как функции задать пустое значение для возвращения. Это как void в c?
О скобках. Первые три примера, компилятор не ругался. Всё нормально откомпилировал.
Возможно, что он будет ругаться если в функции есть return?
А кстати, как функции задать пустое значение для возвращения. Это как void в c?
Re: передача аргументов в процедуры и функции
Использовать всместо функции процедуру. Весь смысл в том, что в Си-шке вообще нет процедур, их роль выполняют функции с возвращаемым параметром void
Re: передача аргументов в процедуры и функции
Я знаю.
Тоесть когда я буду к c подключать библиотеку fb, то это будет тоже самое , что функция с void?
Тоесть когда я буду к c подключать библиотеку fb, то это будет тоже самое , что функция с void?
Re: передача аргументов в процедуры и функции
угу, можно для примера посмотреть как переносят Сишные прототипы функций на FB
Ассемблер и языки высокого уровня: передача параметров
Большинство языков высокого уровня передают параметры вызываемой процедуре в стеке и ожидают возвращения параметров в регистре AX (EAX). иногда используется DX:AX (EDX:EAX), если результат не умещается в одном регистре и ST(0), если результат - число с плавающей запятой.
Конвенция Pascal
Самый очевидный способ вызова процедуры или функции языка высокого уровня, после того как решено, что параметры передаются в стеке и возвращаются в регистре AX/EAX, - это способ, принятый в языке Pascal, - просто поместить параметры в стек в естественном порядке:
запись
some_proc(a, b, c, d, e)
превращается в:
push a
push b
push c
push d
push e
Это означает, что процедура some_proc, во-первых, должна очистить стэк по окончании работы (например, завершившиськомандой ret 10) и, во-вторых, параметры, переданные ей, находятся в стэке в обратном порядке:
some_proc proc
push bp
mov bp, sp ; создать стековый кадр
a equ [bp+12] ; определения для простогодоступа к параметрам
b equ [bp+10]
c equ [bp+8]
d equ [bp+6]
e equ [bp+4]
[текст процедуры, использующей параметры a, b, c, d, e]
pop bp
ret 10
some_proc endp
Главный недостаток этого подхода заключается в сложности создания функции с изменяемым числом параметров. Чтобы определить число параметров, процедура должна сначала прочитать первый параметр, но она не знает его расположения в стэке. Эту проблему решает подход, используемый в C, где параметры передаются в обратном порядке.
Конвенция C
Данный способ передачи параметровиспользуется в первую очередь в языках C и C++. Параметры помещаются в стек в обратном порядке, а удаление из стека (в противоположность Pascal-конвенции) выполняет вызывающая процедура:
запись
some_proc(a, b, c, d, e)
превращается в:
push e
push d
push c
push b
push a
call some_proc
add sp, 10 ; освободить стек
Вызванная процедура может инициализироваться следующим образом:
some_proc proc
push bp
mov bp, sp ; создать стековый кадр
a equ [bp+4] ; определения для простого доступа к параметрам
b equ [bp+6]
c equ [bp+8]
d equ [bp+10]
e equ [bp+12]
[текст процедуры, использующей параметры a, b, c, d, e]
pop bp
ret
some_proc endp
Преимущество по сравнению с Pascal-конвенцией заключается в том, что освобжнеие стека от параметров в C возлагается на вызывающую процедуру, а это позволяет лучше оптимизировать код программы. Например, если мы должны вызывать несколько функций, принимающих одни и те же параметры подряд, можно не заполнять стек каждый раз заново:
push param1
push param2
call proc1
call proc2
add sp, 4
эквивалентно
proc1(param1, param2);
proc2(param1, param2);
вот почему компиляторы с языка C создают более компактный и быстрый код нежели компиляторы с других языков.
Смешанные конвенции
Существует также конвенция STDCALL, отличающаяся и от C, и от PASCAL-конвенций, которая применяется для всех системных функций Win32 API. Здесь параметры помещаются в стект в обратном порядке, как в C, но процедуры должны очищать стек сами, как в PASCAL.
Искажение имён
Компиляторы Microsoft C (а также многие компиляторы UNIX), изменяют названия процедур, чтобы отразить используемый способ передачи параметров. Так, к названиям всех процедур, применяющих C-конвенцию, добавляется символ подчёркивания. То есть, если в C-программе записано
some_proc();
то реально компилятор пишет
call _some_proc
и это означает: если процедура написана на ассемблере, она должна называться именно _some_proc.
Названия процедур, использующих STDCALL, искажаются ещё более сложным образом: слева к названию процедуры добавляется символ подчёркивания, а сзади — сивол @ и размер области стека в байтах, которую занимают параметры (то есть число, стоящее после команды ret в конце процедуры)
some_proc(a:word);
превращается в
push a
call _some_proc@4
Конвенция Pascal
Самый очевидный способ вызова процедуры или функции языка высокого уровня, после того как решено, что параметры передаются в стеке и возвращаются в регистре AX/EAX, - это способ, принятый в языке Pascal, - просто поместить параметры в стек в естественном порядке:
запись
some_proc(a, b, c, d, e)
превращается в:
push a
push b
push c
push d
push e
Это означает, что процедура some_proc, во-первых, должна очистить стэк по окончании работы (например, завершившиськомандой ret 10) и, во-вторых, параметры, переданные ей, находятся в стэке в обратном порядке:
some_proc proc
push bp
mov bp, sp ; создать стековый кадр
a equ [bp+12] ; определения для простогодоступа к параметрам
b equ [bp+10]
c equ [bp+8]
d equ [bp+6]
e equ [bp+4]
[текст процедуры, использующей параметры a, b, c, d, e]
pop bp
ret 10
some_proc endp
Главный недостаток этого подхода заключается в сложности создания функции с изменяемым числом параметров. Чтобы определить число параметров, процедура должна сначала прочитать первый параметр, но она не знает его расположения в стэке. Эту проблему решает подход, используемый в C, где параметры передаются в обратном порядке.
Конвенция C
Данный способ передачи параметровиспользуется в первую очередь в языках C и C++. Параметры помещаются в стек в обратном порядке, а удаление из стека (в противоположность Pascal-конвенции) выполняет вызывающая процедура:
запись
some_proc(a, b, c, d, e)
превращается в:
push e
push d
push c
push b
push a
call some_proc
add sp, 10 ; освободить стек
Вызванная процедура может инициализироваться следующим образом:
some_proc proc
push bp
mov bp, sp ; создать стековый кадр
a equ [bp+4] ; определения для простого доступа к параметрам
b equ [bp+6]
c equ [bp+8]
d equ [bp+10]
e equ [bp+12]
[текст процедуры, использующей параметры a, b, c, d, e]
pop bp
ret
some_proc endp
Преимущество по сравнению с Pascal-конвенцией заключается в том, что освобжнеие стека от параметров в C возлагается на вызывающую процедуру, а это позволяет лучше оптимизировать код программы. Например, если мы должны вызывать несколько функций, принимающих одни и те же параметры подряд, можно не заполнять стек каждый раз заново:
push param1
push param2
call proc1
call proc2
add sp, 4
эквивалентно
proc1(param1, param2);
proc2(param1, param2);
вот почему компиляторы с языка C создают более компактный и быстрый код нежели компиляторы с других языков.
Смешанные конвенции
Существует также конвенция STDCALL, отличающаяся и от C, и от PASCAL-конвенций, которая применяется для всех системных функций Win32 API. Здесь параметры помещаются в стект в обратном порядке, как в C, но процедуры должны очищать стек сами, как в PASCAL.
Искажение имён
Компиляторы Microsoft C (а также многие компиляторы UNIX), изменяют названия процедур, чтобы отразить используемый способ передачи параметров. Так, к названиям всех процедур, применяющих C-конвенцию, добавляется символ подчёркивания. То есть, если в C-программе записано
some_proc();
то реально компилятор пишет
call _some_proc
и это означает: если процедура написана на ассемблере, она должна называться именно _some_proc.
Названия процедур, использующих STDCALL, искажаются ещё более сложным образом: слева к названию процедуры добавляется символ подчёркивания, а сзади — сивол @ и размер области стека в байтах, которую занимают параметры (то есть число, стоящее после команды ret в конце процедуры)
some_proc(a:word);
превращается в
push a
call _some_proc@4
Re: передача аргументов в процедуры и функции
Очень знакомый текст. Где-то и когда-то я его уже читал
Страница 1 из 1
Права доступа к этому форуму:
Вы не можете отвечать на сообщения