vitaly_l писал(а):bormant писал(а):На ошибку компиляции внимания не обращаем... Смотрим на тела процедур и на вызов в одном и другом случае.
У меня получилось вот это: 
Assembler masm.exe not found, Fatal...  
Да, именно на неё не обращаем внимания, нам нужен был ассемблерный листинг, мы его получили в файле с расширением .s, например, если исходник назывался test.pas, то в файле test.s.
Немного поменял исходник для иллюстрации fascall, cdecl, pascal, stdcall:
- Код: Выделить всё
 type
  PChunkRec = ^TChunkRec;
  TChunkRec = record
    id: string;
    size: integer;
    data: Pointer;
  end; 
procedure Proc1(Chunk: TChunkRec; Data: Pointer);
begin
end;
procedure Proc2(Chunk: TChunkRec; Data: Pointer); cdecl;
begin
end;
procedure Proc3(Chunk: TChunkRec; Data: Pointer); pascal;
begin
end;
procedure Proc4(Chunk: TChunkRec; Data: Pointer); stdcall;
begin
end;
var
  c: TChunkRec;
begin
  Proc1(c, nil);
  Proc2(c, nil);
  Proc3(c, nil);
  Proc4(c, nil);
end.
Смотрим на тела процедур и на код вызова, обращаем внимание на то, кто корректирует стек по завершении вызова.
Добавлено спустя 9 минут 18 секунд:Proc1, тело:
- Код: Выделить всё
    PUBLIC   P$PROGRAM_PROC1$TCHUNKREC$POINTER
P$PROGRAM_PROC1$TCHUNKREC$POINTER:
; Temps allocated between ebp-280 and ebp-8
; [test.pas]
; [10] begin
      push   ebp
      mov   ebp,esp
      sub   esp,280
      mov   dword ptr [ebp-280],esi
      mov   dword ptr [ebp-276],edi
; Var Chunk located at ebp-4
; Var Data located at ebp-8
      mov   dword ptr [ebp-4],eax
      mov   dword ptr [ebp-8],edx
      mov   esi,dword ptr [ebp-4]
      lea   edi,dword ptr [ebp-272]
      cld
      mov   ecx,66
      rep   movsd
; [11] end;
      mov   esi,dword ptr [ebp-280]
      mov   edi,dword ptr [ebp-276]
      leave
      ret
Proc2, тело:
- Код: Выделить всё
    PUBLIC   P$PROGRAM_PROC2$TCHUNKREC$POINTER
P$PROGRAM_PROC2$TCHUNKREC$POINTER:
; Temps allocated between ebp+0 and ebp+0
; [14] begin
      push   ebp
      mov   ebp,esp
; Var Chunk located at ebp+8
; Var Data located at ebp+272
; [15] end;
      leave
      ret
Proc3, тело:
- Код: Выделить всё
    PUBLIC   P$PROGRAM_PROC3$TCHUNKREC$POINTER
P$PROGRAM_PROC3$TCHUNKREC$POINTER:
; Temps allocated between ebp-272 and ebp+0
; [18] begin
      push   ebp
      mov   ebp,esp
      sub   esp,272
      mov   dword ptr [ebp-272],esi
      mov   dword ptr [ebp-268],edi
; Var Chunk located at ebp+12
; Var Data located at ebp+8
      mov   esi,dword ptr [ebp+12]
      lea   edi,dword ptr [ebp-264]
      cld
      mov   ecx,66
      rep   movsd
; [19] end;
      mov   esi,dword ptr [ebp-272]
      mov   edi,dword ptr [ebp-268]
      leave
      ret   8
Proc4, тело:
- Код: Выделить всё
    PUBLIC   P$PROGRAM_PROC4$TCHUNKREC$POINTER
P$PROGRAM_PROC4$TCHUNKREC$POINTER:
; Temps allocated between ebp+0 and ebp+0
; [22] begin
      push   ebp
      mov   ebp,esp
; Var Chunk located at ebp+8
; Var Data located at ebp+272
; [23] end;
      leave
      ret   268
Proc1, вызов:
- Код: Выделить всё
 ; [29] Proc1(c, nil);
      mov   eax,offset U_P$PROGRAM_C
      mov   edx,0
      call   P$PROGRAM_PROC1$TCHUNKREC$POINTER
Proc2, вызов:
- Код: Выделить всё
 ; [30] Proc2(c, nil);
      push   0
      sub   esp,264
      mov   edi,esp
      mov   esi,offset U_P$PROGRAM_C
      cld
      mov   ecx,66
      rep   movsd
      call   P$PROGRAM_PROC2$TCHUNKREC$POINTER
      add   esp,268
Proc3, вызов:
- Код: Выделить всё
 ; [31] Proc3(c, nil);
      push   offset U_P$PROGRAM_C
      push   0
      call   P$PROGRAM_PROC3$TCHUNKREC$POINTER
Proc4, вызов:
- Код: Выделить всё
 ; [32] Proc4(c, nil);
      push   0
      sub   esp,264
      mov   edi,esp
      mov   esi,offset U_P$PROGRAM_C
      cld
      mov   ecx,66
      rep   movsd
      call   P$PROGRAM_PROC4$TCHUNKREC$POINTER
Добавлено спустя 44 минуты 29 секунд:Proc1, по умолчанию fastcall.
Вызывающий код в регистре eax передаёт указатель на C, в регистре edx передаёт Data.
Выполняется вызов процедуры.
Сгенерированная компилятором преамбула Proc1:
-- сохраняет в ebp указатель стека;
-- резервирует на стеке место для копий Chunk и Data;
-- копирует содержимое в локальные копии Chunk и Data.
Далее исполняется код процедуры (у нас пусто).
Перед возвратом из процедуры стек приводится в исходное значение.
Proc2, cdecl.
В стек укладываются параметры справа налево, сначала значение Data (nil, он же 0), затем в стек из C копируется содержимое Chunk.
Выполняется вызов процедуры.
Сгенерированная компилятором преамбула Proc1:
-- сохраняет в ebp указатель стека.
Далее исполняется код процедуры (у нас пусто).
Перед возвратом из процедуры стек приводится в значение перед вызовом.
Вызывающий код корректирует содержимое стека на размер Chunk и Data (268 байт).
Proc3, pascal.
В стек укаладываются параметры слева направо, сначала указатель на C, затем значние Data (nil, он же 0).
Выполняется вызов процедуры.
Сгенерированная компилятором преамбула Proc3:
-- сохраняет в ebp указатель стека;
-- резервирует на стеке место для копий Chunk и Data;
-- копирует содержимое в локальные копии Chunk и Data.
Далее исполняется код процедуры (у нас пусто).
Перед возвратом из процедуры стек приводится в исходное значение, дополнительно из него удаляются полученые параметры (8 байт, указатель на Chunk и Data).
Proc4, stdcall.
В стек укладываются параметры справа налево, сначала значение Data (nil, он же 0), затем в стек из C копируется содержимое локальной Chunk (66 двойных слов, 264 байта).
Выполняется вызов процедуры.
Сгенерированная компилятором преамбула Proc4:
-- сохраняет в ebp указатель стека.
Далее исполняется код процедуры (у нас пусто).
Перед возвратом из процедуры стек приводится в исходное значение, дополнительно из него удаляются полученые копии параметров, помещённые вызывающим кодом (268 байт).