Calling Convention
От: Mobster  
Дата: 30.05.01 11:06
Оценка:
Привет, всем!!!

Кто-нибудь может объяснить, зачем при вызове C-функций аргументы копируются
в стек в обратном порядке (справа налево). Какой в этом смысл? Почему не как
в Паскале — слева направо? Так ведь вроде логичнее...

Заранее благодарю!!!
Re: Calling Convention
От: Willi  
Дата: 30.05.01 11:52
Оценка:
Здравствуйте Mobster, вы писали:

M>Привет, всем!!!


M>Кто-нибудь может объяснить, зачем при вызове C-функций аргументы копируются

M>в стек в обратном порядке (справа налево). Какой в этом смысл?

Почему я не знаю.
Но помоему, именно благодаря этому способу, мы имеем возможность передавать в
функцию переменное число параметров.

Поправьте меня если я не прав.
А то мне и самому интересно стало.
\/\/i||i
Re[2]: Calling Convention
От: IT Россия linq2db.com
Дата: 30.05.01 12:22
Оценка:
W>Почему я не знаю.
W>Но помоему, именно благодаря этому способу, мы имеем возможность передавать в
W>функцию переменное число параметров.

W>Поправьте меня если я не прав.

W>А то мне и самому интересно стало.

Именно поэтому. Кстати, к этому прилагается ещё один небольшой недостаток — в C после вызова функции стек должна восстанавливать вызывающая процедура, в Паскале это обязанность вызываемой (в смысле вызванной, та которую вызвали) функция. Получается экономия кода и код работает быстрее, потому как, если мне не изменяет мой склероз, корректировку стека можно сделать прямо в команде возврата.
Если нам не помогут, то мы тоже никого не пощадим.
Re[3]: Calling Convention
От: Igor Soukhov  
Дата: 30.05.01 16:55
Оценка:
Здравствуйте IT, вы писали:

W>>Почему я не знаю.

W>>Но помоему, именно благодаря этому способу, мы имеем возможность передавать в
W>>функцию переменное число параметров.

W>>Поправьте меня если я не прав.

W>>А то мне и самому интересно стало.

IT>Именно поэтому. Кстати, к этому прилагается ещё один небольшой недостаток — в C после вызова функции стек должна

По мойму порядок передачи (слева направо или наоборот) монопенисуален для реализации переменного кол-ва параметров...
А вот то что очищиет стек вызываемая функция — это да ... В этом все и дело.
IT>восстанавливать вызывающая процедура, в Паскале это обязанность вызываемой (в смысле вызванной, та которую вызвали) функция. IT>Получается экономия кода и код работает быстрее, потому как, если мне не изменяет мой склероз, корректировку стека можно IT>сделать прямо в команде возврата.

Igor
* thriving in a production environment *
Re[4]: Calling Convention
От: Alex Fedotov США  
Дата: 30.05.01 17:41
Оценка:
Здравствуйте Igor Soukhov, вы писали:

IT>>Именно поэтому. Кстати, к этому прилагается ещё один небольшой недостаток — в C после вызова функции стек должна

IS>По мойму порядок передачи (слева направо или наоборот) монопенисуален для реализации переменного кол-ва параметров...
IS>А вот то что очищиет стек вызываемая функция — это да ... В этом все и дело.

Порядок важен, потому что иначе вызываемая функция не будет знать, где искать первый параметр. Тогда бы в языке C пришлось бы троеточие в начале списка аргументов ставить :)
-- Alex Fedotov
Re[3]: Calling Convention
От: IAZ http://iaz.simb.ru
Дата: 30.05.01 17:46
Оценка:
Здравствуйте IT, вы писали:

W>>Почему я не знаю.

W>>Но помоему, именно благодаря этому способу, мы имеем возможность передавать в
W>>функцию переменное число параметров.

W>>Поправьте меня если я не прав.

W>>А то мне и самому интересно стало.

IT>Именно поэтому. Кстати, к этому прилагается ещё один небольшой недостаток — в C после вызова функции стек должна восстанавливать вызывающая процедура, в Паскале это обязанность вызываемой (в смысле вызванной, та которую вызвали) функция. Получается экономия кода и код работает быстрее, потому как, если мне не изменяет мой склероз, корректировку стека можно сделать прямо в команде возврата.


Почему это недостаток? Передача переменного кол-ва параметров в функцию было большим плюсом в С
Да и вообше это просто еще один способ реализации. Неужели вы хотите сказать, что С медленно работает? Скаких пор отличие от всех стало считаться недостатком?
Кто ищет то всегда найдет!
Re[3]: Calling Convention - IT и всем...
От: Mobster  
Дата: 31.05.01 01:50
Оценка:
Здравствуйте IT, вы писали:

W>>Почему я не знаю.

W>>Но помоему, именно благодаря этому способу, мы имеем возможность передавать в
W>>функцию переменное число параметров.

W>>Поправьте меня если я не прав.

W>>А то мне и самому интересно стало.

IT>Именно поэтому. Кстати, к этому прилагается ещё один небольшой недостаток — в C после вызова функции стек должна восстанавливать вызывающая процедура, в Паскале это обязанность вызываемой (в смысле вызванной, та которую вызвали) функция. Получается экономия кода и код работает быстрее, потому как, если мне не изменяет мой склероз, корректировку стека можно сделать прямо в команде возврата.


Насчет того, что обратная передача аргументов в стек, позволяет передавать переменное количество параметров — это не совсем так. Если вы пользовались функциями с переменным числом параметров (в stdarg.h находятся; va_arg, va_start, va_end) то там обработка параметров идет именно СЛЕВА НАПРАВО (то есть то, в каком порядке аргументы передались в функцию вообще не имеет никакого занчения), причем Вы должны в функцию в качестве аргумента передавать переменную, которая указывает количество аргументов или реализовывать обработку списка параметров до какого-то параметра, который у вас используется в качестве terminator'а. Так вот весь УЖАС в том, что это все идеально подходит и для паскалеобразных языков, хотя в последнем нет (насколько я знаю) такой возможности. Именно поэтому меня этот вопрос так заинтересовал :-)))))

А насчет ответа, что пришлось бы в качестве первого параметра передавать многоточие — так это вообще уже непонятно что :-))))

Так что я все еще не понимаю!!!
Если кто-нибудь наткнется на варианты ответа пишите в любое время на <serg@alsi.com>
Re[4]: Calling Convention - IT и всем...
От: Alex Fedotov США  
Дата: 31.05.01 03:14
Оценка:
Здравствуйте Mobster, вы писали:

M>Насчет того, что обратная передача аргументов в стек, позволяет передавать переменное количество параметров — это не совсем так. Если вы пользовались функциями с переменным числом параметров (в stdarg.h находятся; va_arg, va_start, va_end) то там обработка параметров идет именно СЛЕВА НАПРАВО (то есть то, в каком порядке аргументы передались в функцию вообще не имеет никакого занчения), причем Вы должны в функцию в качестве аргумента передавать переменную, которая указывает количество аргументов или реализовывать обработку списка параметров до какого-то параметра, который у вас используется в качестве terminator'а. Так вот весь УЖАС в том, что это все идеально подходит и для паскалеобразных языков, хотя в последнем нет (насколько я знаю) такой возможности. Именно поэтому меня этот вопрос так заинтересовал :-)))))


Итак, если функция имеет переменное число параметров и первый параметр кладется в стек последним, как это делается в C, то вызываемая функция может легко найти его по адресу
[ebp + 8] (я предполагаю наличие вполне конкретного стекового фрейма, принятого в Win32
flat модели; в других случаях будет не так, но давайте пока не будем придираться к деталям).
Макрос va_arg соответствует движению выше по стеку.

Если параметры передаются в другом порядке, то по адресу [ebp + 8] окажется последний параметр, а первый параметр окажется где-то выше по стеку, причем неизвестно где (параметров ведь переменное число).

Представь себе printf. Чтобы определить число параметров ему нужно знать форматную строку. Если параметры передаются как они передаются, то форматная строка берется из [ebp + 8] и дальше никаких проблем нет. Но если параметры передать в другом порядке, то printf просто не сможет найти эту форматную строку, так как для этого нужно знать число фактически переданных параметров, а оно определяется только из форматной строки.

Поэтому порядок укладки аргументов в стек имеет значение, когда используется переменное число аргументов.

M>А насчет ответа, что пришлось бы в качестве первого параметра передавать многоточие — так это вообще уже непонятно что :-))))


Это была шутка. Надеюсь она теперь понятна.
-- Alex Fedotov
Re[5]: Calling Convention
От: Igor Soukhov  
Дата: 31.05.01 03:19
Оценка:
Здравствуйте Alex Fedotov, вы писали:

AF>Здравствуйте Igor Soukhov, вы писали:


IT>>>Именно поэтому. Кстати, к этому прилагается ещё один небольшой недостаток — в C после вызова функции стек должна

IS>>По мойму порядок передачи (слева направо или наоборот) монопенисуален для реализации переменного кол-ва параметров...
IS>>А вот то что очищиет стек вызываемая функция — это да ... В этом все и дело.

AF>Порядок важен, потому что иначе вызываемая функция не будет знать, где искать первый параметр. Тогда бы в языке C AF>пришлось бы троеточие в начале списка аргументов ставить :)

Ну вот ж) — значит порядок не важен — важно как реализуешь... хотя как есть вроде проще чем я говорил ;)

Igor
* thriving in a production environment *
Re[5]: Calling Convention - IT и всем...
От: Mobster  
Дата: 31.05.01 04:00
Оценка:
Здравствуйте Alex Fedotov, вы писали:

AF>Итак, если функция имеет переменное число параметров и первый параметр кладется в стек последним, как это делается в C, то вызываемая функция может легко найти его по адресу

AF>[ebp + 8] (я предполагаю наличие вполне конкретного стекового фрейма, принятого в Win32
AF>flat модели; в других случаях будет не так, но давайте пока не будем придираться к деталям).
AF>Макрос va_arg соответствует движению выше по стеку.

AF>Если параметры передаются в другом порядке, то по адресу [ebp + 8] окажется последний параметр, а первый параметр окажется где-то выше по стеку, причем неизвестно где (параметров ведь переменное число).


AF>Представь себе printf. Чтобы определить число параметров ему нужно знать форматную строку. Если параметры передаются как они передаются, то форматная строка берется из [ebp + 8] и дальше никаких проблем нет. Но если параметры передать в другом порядке, то printf просто не сможет найти эту форматную строку, так как для этого нужно знать число фактически переданных параметров, а оно определяется только из форматной строки.


AF>Поэтому порядок укладки аргументов в стек имеет значение, когда используется переменное число аргументов.


Уважаемый Alex!!!

Насколько я понял их Вашего письма, параметры функции копируются в обратном порядке по УБЫВАНИЮ адресов и адрес самого последнего СКОПИРОВАННОГО параметра (то есть первого параметра функции) возвращается как адрес начала стекового фрейма. Так как они копировались по убыванию адресов, то возможны такие штучки как va_arg, которые движутся вверх по стеку.

Я правильно вас понял?
Если да, то я похоже понял что к чему.

Заранее спасибо за ответ :-))))
Re[6]: Calling Convention - IT и всем...
От: Alex Fedotov США  
Дата: 31.05.01 06:51
Оценка:
Здравствуйте Mobster, вы писали:

M>Насколько я понял их Вашего письма, параметры функции копируются в обратном порядке по УБЫВАНИЮ адресов и адрес самого последнего СКОПИРОВАННОГО параметра (то есть первого параметра функции) возвращается как адрес начала стекового фрейма. Так как они копировались по убыванию адресов, то возможны такие штучки как va_arg, которые движутся вверх по стеку.


M>Я правильно вас понял?


Да. Если быть совсем точным, то первый параметр находится по фиксированному смещению от начала стекового фрейма.
-- Alex Fedotov
Re[3]: Calling Convention
От: Alex Ostapenko Россия  
Дата: 31.05.01 08:53
Оценка:
IT>Именно поэтому. Кстати, к этому прилагается ещё один небольшой недостаток — в C после вызова функции стек должна восстанавливать вызывающая процедура, в Паскале это обязанность вызываемой (в смысле вызванной, та которую вызвали) функция. Получается экономия кода и код работает быстрее, потому как, если мне не изменяет мой склероз, корректировку стека можно сделать прямо в команде возврата.

Склероз тебе не изменяет (а может как раз изменяет :)).
Re[6]: Calling Convention - IT и всем...
От: Vitek  
Дата: 31.05.01 09:12
Оценка:
Здравствуйте Mobster, вы писали:

M>Здравствуйте Alex Fedotov, вы писали:


AF>>Итак, если функция имеет переменное число параметров и первый параметр кладется в стек последним, как это делается в C, то вызываемая функция может легко найти его по адресу

AF>>[ebp + 8] (я предполагаю наличие вполне конкретного стекового фрейма, принятого в Win32
AF>>flat модели; в других случаях будет не так, но давайте пока не будем придираться к деталям).
AF>>Макрос va_arg соответствует движению выше по стеку.

AF>>Если параметры передаются в другом порядке, то по адресу [ebp + 8] окажется последний параметр, а первый параметр окажется где-то выше по стеку, причем неизвестно где (параметров ведь переменное число).


AF>>Представь себе printf. Чтобы определить число параметров ему нужно знать форматную строку. Если параметры передаются как они передаются, то форматная строка берется из [ebp + 8] и дальше никаких проблем нет. Но если параметры передать в другом порядке, то printf просто не сможет найти эту форматную строку, так как для этого нужно знать число фактически переданных параметров, а оно определяется только из форматной строки.


AF>>Поэтому порядок укладки аргументов в стек имеет значение, когда используется переменное число аргументов.


M>Уважаемый Alex!!!


M>Насколько я понял их Вашего письма, параметры функции копируются в обратном порядке по УБЫВАНИЮ адресов и адрес самого последнего СКОПИРОВАННОГО параметра (то есть первого параметра функции) возвращается как адрес начала стекового фрейма. Так как они копировались по убыванию адресов, то возможны такие штучки как va_arg, которые движутся вверх по стеку.


M>Я правильно вас понял?

M>Если да, то я похоже понял что к чему.

M>Заранее спасибо за ответ :-))))


Столько мудрости.
Что я чуть не запутался!

Может проще как объяснить?
Стек — первый вошёл, последний вышел.

Записывали в обратном порядке.
Сама функция получила их в НОРМАЛЬНОМ порядке!

Так что как знать ещё, что логичнее — Паскаль или Си?

Элементарно. И пусть благословенен тот кто придумал такую схему. По собственному опыту сужу — насколько
она мне в жизни помогла.
Re[3]: Calling Convention
От: Yarik http://www.vershynin.com
Дата: 16.07.01 06:03
Оценка:
Здравствуйте IT, вы писали:

W>>Почему я не знаю.

W>>Но помоему, именно благодаря этому способу, мы имеем возможность передавать в
W>>функцию переменное число параметров.

W>>Поправьте меня если я не прав.

W>>А то мне и самому интересно стало.

IT>Именно поэтому. Кстати, к этому прилагается ещё один небольшой недостаток — в C после вызова функции стек должна IT>восстанавливать вызывающая процедура, в Паскале это обязанность вызываемой (в смысле вызванной, та которую вызвали) IT>функция. Получается экономия кода и код работает быстрее, потому как, если мне не изменяет мой склероз, корректировку IT>стека можно сделать прямо в команде возврата.


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

ValuateVar (dwVar);
ProcessVar (fFlag, dwVar);
StoreVar (dwVar)

на Сях: на Паскале:

mov eax, dwVar mov eax, dwVar
push eax push eax
call ValuateVar call ValuateVar
mov eax, fFlag mov eax, fFlag
push eax push eax
call ProcessVar mov eax, dwVar
add esp, 4 push eax
call StoreVar call ProcessVar
add esp, 4 mov eax, dwVar
push eax
call StoreVar

И где код эффективнее? Тото же. Надо просто уметь этим пользоваться.

Хотя в общем случае код на Паскале получается немного меньше (ввиду отсутствия add esp,xxx), но насчет скорости смею возразить: ведь ret xxx делает то же, что и последовательность (add esp,xxx)(ret).
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.