Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Потрепаться";
Текущий архив: 2004.04.18;
Скачать: [xml.tar.bz2];

Вниз

Разомнем слегка мозги... :)   Найти похожие ветки 

 
Kerk ©   (2004-03-22 16:25) [0]

Что будет выведено на экран в результате выполенения этой проги?
(только давайте честно, не надо запускать, определите на глаз).

program test;

{$APPTYPE CONSOLE}

function SetA(var a: Cardinal): Cardinal;
begin
 a := 5;
 Result := a;
end;

procedure Proc1(a,b: Cardinal); stdcall;
begin
 WriteLn("=== proc1 ====");
 WriteLn("a = ",a);
 WriteLn("b = ",b);
 WriteLn("==============");
end;

procedure Proc2(a,b: Cardinal); pascal;
begin
 WriteLn("=== proc2 ====");
 WriteLn("a = ",a);
 WriteLn("b = ",b);
 WriteLn("==============");
end;

procedure Proc3(a,b: Cardinal);
begin
 WriteLn("=== proc3 ====");
 WriteLn("a = ",a);
 WriteLn("b = ",b);
 WriteLn("==============");
end;

var
 a: Cardinal;
begin
 a := 0;
 Proc1(SetA(a),a+1);
 a := 0;
 Proc2(SetA(a),a+1);
 a := 0;
 Proc3(SetA(a),a+1);
end.


 
REA ©   (2004-03-22 16:33) [1]

На глаз сложно представить.
Скорее всего для pascal 5 и 6, а для cdecl, 5 и 1.
Хотя это так - догадка. Легче запустить и проверить.


 
Kerk ©   (2004-03-22 16:34) [2]


> REA ©   (22.03.04 16:33) [1]

Запускать не надо! %)
Там три процедуры, а ты сказал только про две.


 
Dmitriy O. ©   (2004-03-22 16:35) [3]

"Программа ..... выполнила некоректную операцию и будет закрыта"


 
Kerk ©   (2004-03-22 16:37) [4]


> Dmitriy O. ©   (22.03.04 16:35) [3]

Неправильно! :)
А если серьезно, то почему? Прога-то вроде нормальная.


 
Плохиш   (2004-03-22 16:44) [5]

В Proc2 и Proc3 используется одинаковый способ передачи параметров, соответственно и результат будет одинаковый


 
Kerk ©   (2004-03-22 16:47) [6]


> В Proc2 и Proc3 используется одинаковый способ передачи
> параметров

нет!


 
MBo ©   (2004-03-22 17:00) [7]

В Proc1 используется stdcall, при этом параметры загоняются в стек справа налево, и a+1 при этом еще равно 1, а в P2 и P3 параметры идут слева направо (P2-в стеке, P3 (Register по умолчанию)  - в EAX и EDX), и a+1 берется уже после срабатывания SetA, т.е. 6.
Если добавить еще процедуру с cdecl, то результат будет аналогичен P1.
А подводный камень интересный...


 
Плохиш   (2004-03-22 17:01) [8]

>Kerk ©   (22.03.04 16:47) [6]
Скажем подругому: вычисление параметров производится в одинаковой последовательности, т.ч. результат всё равно одинаковый ;-)


 
Piter ©   (2004-03-22 18:04) [9]

Кстати, а мне вот тут стало очень интересно

Proc1(SetA(a),a+1);

А как компилятор это обрабатывает? Справа налево, это понятно, в справке написано. Но как?
Ведь он не может сначала передать один аргумент (a+1) потом вычислить значение второго и уже его передать? Верно?
Он сразу оба должен передать, соответтсвенно, сначала он вычислит значение a+1 и где то его должен сохранить, потом сзначение (SetA(a), а потом все это передать в процедуру... или я чего не понимаю?


 
Плохиш   (2004-03-22 18:08) [10]

>Piter ©   (22.03.04 18:04) [9]

Ты в справке до табличке не дочитал :-) А в ней есть колонка, в которой написано "используется стек или нет" ;-)


 
Piter ©   (2004-03-22 19:20) [11]

Плохиш   (22.03.04 18:08) [10]
А в ней есть колонка, в которой написано "используется стек или нет"


есть. И там написано, что не используются регистры... а при чем здесь стек?

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


 
Kerk ©   (2004-03-23 14:52) [12]


> MBo ©   (22.03.04 17:00) [7]
> а в P2 и P3 параметры идут слева направо.


Где-нибудь документировано в какой последовательности значения заносятся в соответствующие регистры?


 
MBo ©   (2004-03-23 14:59) [13]

>Где-нибудь документировано в какой последовательности значения заносятся в соответствующие регистры?
Думаю, нет.
Для стека по крайней мере есть логика - чтобы засунуть туда правый параметр раньше левого (stdcall,cdecl) - надо его сначала получить, для pascal наоборот. Для register же, видимо, только общий принцип работает "что вижу - о том и пою, слева направо".


 
Игорь Шевченко ©   (2004-03-23 19:02) [14]


> Где-нибудь документировано в какой последовательности значения
> заносятся в соответствующие регистры?


Первый - в EAX, второй в EDX, третий в ECX, остальные в стек. Просмотр слева направо.
Источник - Object pascal language guide


 
Cobalt ©   (2004-03-23 22:17) [15]

Плохиш   (22.03.04 18:08) [10]
Piter ©   (22.03.04 19:20) [11]

> Ты в справке до табличке не дочитал :-)

А что это за статья в хелпе, о которой вы упоминаете? Как называется?


 
Verg ©   (2004-03-23 22:45) [16]


>  Kerk ©   (22.03.04 16:25)
> Что будет выведено на экран в результате выполенения этой
> проги?
> (только давайте честно, не надо запускать, определите на
> глаз).


Если честно, то я бы просто не рискнул ТАК использвать процедуры и их параметры. Извратов в жизни и так хватает....

Однажды один мой товарисч написал, типа, замену С-евому оператору ?: для паскаля - ф-цию

function igrIfb( a: boolean; arTrue : Integer; arFalse : Integer) : Integer;
begin
 if A then reuslt := arTrue else result := arFalse;
end;

Ага. Долго, помнится, пришлось объяснять, что между вызовом ф-ции и операторм есть "глубинная разница" :)

Давно было, горячие были, молодые, чуть не подралися :))

Пришли к выводу, что надо написать Борладу письмо с просьбой ввести такой оператор и в ммм.. БорландПаскаль - прикинте сколько пива мы выпили :))


 
Игорь Шевченко ©   (2004-03-23 22:56) [17]


> igrIfb


Расшифровать можно ?

Кстати, эта функция называется iif если мне память не изменяет. В ряде случаев может служить заменой оператору ? :


 
Verg ©   (2004-03-23 23:09) [18]

Тогда igr означало - integer
If - это если, а b - ... не помню, видимо boolean

C := igrIf( a = 0, 0, B div a );

C = (a == 0)? 0 : B / a;


 
Игорь Шевченко ©   (2004-03-23 23:20) [19]

Verg ©   (23.03.04 23:09)

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


 
Verg ©   (2004-03-23 23:38) [20]

А оператора-то так и нет.
И присваиваний "на лету" тоже.
И препроцессор вообще на уровне 70-тых-протухших застыл.
Уж раз двинулись в строну "универасльного, могучего и модульного", то уж и синтаксис можено было поправить.
Помните, когда функцию нельзя было вызвать не присвоив ее чему-нибудь? :)))
Вместо result надо было писать название ф-ции, а если оно по смыслу встречалось в "правой" части выражения.... дербенец полный - каждой ф-ции по одной локальной пременной ее же типа!
А эти "мучения с поинторами" до Inc/Dec ? (А, вообще, что мешает ввести прозрачную арифметику указателей, как в С? А class templates?)

Раз уж Дельфи отошел настолько от классики Паскаля, то что ему мешает (в лице Борлада) "впитать" в себя лучшее из обоих?
Таким образом, в угоду "динамическим массивам" они потеряли динамику развития идеологии, которая всегда привлекала в Паскаль-Основанных-Борланд-Идеях.....


 
Игорь Шевченко ©   (2004-03-23 23:58) [21]

Verg ©   (23.03.04 23:38)


> А оператора-то так и нет.


И оператора "запятая" нету :) И шаблонов нету :) И в цикле for нельзя задать приращение переменной цикла отличным от плюс/минус единицы...


> А, вообще, что мешает ввести прозрачную арифметику указателей,
> как в С?


Вроде как Inc(PInt) изменит указатель типа ^Integer на нужное значение...

Но С есть С, Паскаль есть Паскаль, и с мест они не сойдут.
Оба языка хорошие :)))

А в Object pascal есть слово property :)


 
Verg ©   (2004-03-24 00:04) [22]

Нет, ты меня не понял...
Ладно.


 
Verg ©   (2004-03-24 00:13) [23]

Кстати, мимо for в Си нельзя спокойно пройти.

Вот такое вот одностишье... на ночь глядя :))


 
dr Tr0jan ©   (2004-03-24 03:42) [24]

А объясните, плиз, что значит stdcall.
Я так понял что в Proc1 будет:
push a;
push b;

А в Proc2 и Proc3 будет:
push b;
push a;

Правильно мыслю?
Хотя судя по хелпу правильно мыслю...
А расскажите, зачем нужно применять эти параметры вызова?


 
MBo ©   (2004-03-24 06:32) [25]

>dr Tr0jan
Proc1
push b
push a

Proc2
push a
push b

Proc3
mov eax,a
mov edx,b


 
Kerk ©   (2004-03-24 09:54) [26]


> Игорь Шевченко ©   (23.03.04 19:02) [14]
>
> > Где-нибудь документировано в какой последовательности
> значения
> > заносятся в соответствующие регистры?
>
>
> Первый - в EAX, второй в EDX, третий в ECX, остальные в
> стек. Просмотр слева направо.
> Источник - Object pascal language guide


Я это знаю... не первый год замужем... :)))
Я спрашивал, документировано ли где-нибудь, что сначала происходит mov eax,XXX, затем mov edx,XXX, а не наоборот?
MBo ответил, что нет... будем ему верить.. %)


 
Игорь Шевченко ©   (2004-03-24 10:01) [27]


> Я спрашивал, документировано ли где-нибудь, что сначала
> происходит mov eax,XXX, затем mov edx,XXX, а не наоборот?


А какая, собственно говоря, разница ?


 
Kerk ©   (2004-03-24 10:04) [28]


> Игорь Шевченко ©   (24.03.04 10:01) [27]
> А какая, собственно говоря, разница ?


Разницу между stdcall и pascal видел? Порядок заноса параметров играет роль.


 
Verg ©   (2004-03-24 10:20) [29]


> Я спрашивал, документировано ли где-нибудь, что сначала
> происходит mov eax,XXX, затем mov edx,XXX, а не наоборот?


Ну ведь на самом деле - абсолютно по барабану  какой из регистров будет заполнен первым. Ты же про регистры спрашиваешь.

И вообще, при чем тут регистры там, стек ли это или еще что.

Если фция описана как stdcall/pascal/cdecl, то и у вызывающего прототипа должен стоять такой же stdcall/pascal/cdecl и все.

Чисто формально - модификаторы вызова должны быть одинаковыми.

А как он там устроено - дело десятое. И с этой точки зрения на самом деле - без разницы что там, в какой стек и ногами ли вперед заходит.

Или вы на ассемблере программируете?


 
Kerk ©   (2004-03-24 10:27) [30]


> Verg ©   (24.03.04 10:20) [29]
>
> И вообще, при чем тут регистры там, стек ли это или еще
> что.
>
> А как он там устроено - дело десятое. И с этой точки зрения
> на самом деле - без разницы что там, в какой стек и ногами
> ли вперед заходит.

Ты сабжевую прогу запускал? Разницу в работе процедур видишь?


> Или вы на ассемблере программируете?

И на нем родимом тоже... но сейчас речь идет о Delphi :)


 
Verg ©   (2004-03-24 10:36) [31]

Если же интересует где документирован порядок вычисления операндов, то прямо в Help-е дельфозном:

The register and pascal conventions pass parameters from left to right; that is, the leftmost parameter is evaluated and passed first and the rightmost parameter is evaluated and passed last. The cdecl, stdcall, and safecall conventions pass parameters from right to left.


 
Kerk ©   (2004-03-24 10:37) [32]


> Verg ©   (24.03.04 10:36) [31]

tx


 
Verg ©   (2004-03-24 10:41) [33]


> Ты сабжевую прогу запускал? Разницу в работе процедур видишь?


Ну, а при чем тут регистры или стек? Раз речь идет про язык высокого уровня, то важен порядок вычисления операндов, а не местоположение их в регистрах или на стеке.

Чувствуешь разницу от
что сначала происходит mov eax,XXX, затем mov edx,XXX, а не наоборот?


 
Kerk ©   (2004-03-24 10:43) [34]


> Ну, а при чем тут регистры или стек? Раз речь идет про язык
> высокого уровня, то важен порядок вычисления операндов,
> а не местоположение их в регистрах или на стеке.

Я думал, что порядок вычисления операндов напрямую зависит от местоположения их в стеке.


 
Verg ©   (2004-03-24 10:50) [35]

Кстати, про register в Help-е (D6) наврано :)


> Я думал, что порядок вычисления операндов напрямую зависит
> от местоположения их в стеке.


Тогда уж так - местоположение операндов в стеке (если вообще они через стек передаются) зависит от порядка их вычисления.


 
MBo ©   (2004-03-24 12:15) [36]

>Kerk
>MBo ответил, что нет... будем ему верить.. %)
Мюллер не зря говорил - верить нельзя никому ;)))
parameter is evaluated and passed
этого я не заметил


 
Плохиш   (2004-03-24 12:27) [37]

Cobalt ©   (23.03.04 22:17) [15]

> А что это за статья в хелпе, о которой вы упоминаете? Как
> называется?

На stdcall F1 нажми и там вверху название статьи будет ;-)



Страницы: 1 вся ветка

Форум: "Потрепаться";
Текущий архив: 2004.04.18;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.55 MB
Время: 0.036 c
4-1076476162
ShiFT
2004-02-11 08:09
2004.04.18
Как выдрать ресурсы из посторонней программы


6-1076419526
Павел
2004-02-10 16:25
2004.04.18
WinSocket, Proxy серверы и чат...


3-1079529989
Visnuk
2004-03-17 16:26
2004.04.18
Печать DBGrid с множественным выбором


14-1080339459
Mr.BiZONe
2004-03-27 01:17
2004.04.18
WWW.MISHABOG.NAROD.RU


7-1076171882
nester
2004-02-07 19:38
2004.04.18
Как добавить задание в Планировщик(он же Scheduler)





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский