Ссылка на MSDN - https://msdn.microsoft.com/en-us/library/windows/hardware/ff561499(v=vs.85).aspx
По мотивам - http://programmingmindstream.blogspot.ru/2016/12/1321.html
Под Win64 модель передачи параметров только одна.
Т.е. stdcall, pascal, cdecl, register - эквивалентны.
Параметры передаются через регистры в порядке - rcx, rdx, r8, r9. Остальные через стек.
Если значение не помещается в регистр, то оно кладется на стек, а в регистре передается указатель на это значение.
Возвращаемое значение помещается в rax. Если оно целочисленное (Integer) или указатель (Pointer).
Вещественные числа возвращаются через регистр xmm0.
Регистры rax, rcx, rdx, r8-r11 - могут изменяться внутри вызываемой функции.
Регистры rbx, rbp, rdi, rsi, r12-r15 - должны сохранять своё значение при работе вызываемой функции.
Также спецификация вызова обязует вызывающую процедуру распределять место в собственном стековом фрейме для временного сохранения (spill) значений тех параметров, которые переданы через регистры.
(Оригинальная цитата - "The caller reserves space on the stack for arguments passed in registers. The called function can use this space to spill the contents of registers to the stack.")
Вызываемая процедура может использовать это место по своему усмотрению.
Пример ручного резервирования:
Листьевые процедуры метятся директивой .NOFRAME, которая гарантирует, что компилятор не будет распределять стековый фрейм.
Локальные процедуры обрабатываются особо. В регистр rcx помещается значение регистра базы (rbp) той процедуры в которую вложена локальная процедура.
От этой базы адресуются локальные переменные охватывающей процедуры.
Таким образом вложенная локальная процедура получает доступ к локальным переменным охватывающей процедуры.
На основании этой информации можно строить заглушки для вызовов локальных функций вместо анонимных.
Ссылки:
http://18delphi.blogspot.ru/2013/03/blog-post_5929.html
http://18delphi.blogspot.ru/2013/07/embarcadero.html
Подсмотреть направление исследований можно в коде Embarcadero. В методе MakeObjectInstance.
Позже я выложу примеры кода.
По мотивам - http://programmingmindstream.blogspot.ru/2016/12/1321.html
Под Win64 модель передачи параметров только одна.
Т.е. stdcall, pascal, cdecl, register - эквивалентны.
Параметры передаются через регистры в порядке - rcx, rdx, r8, r9. Остальные через стек.
Если значение не помещается в регистр, то оно кладется на стек, а в регистре передается указатель на это значение.
Возвращаемое значение помещается в rax. Если оно целочисленное (Integer) или указатель (Pointer).
Вещественные числа возвращаются через регистр xmm0.
Регистры rax, rcx, rdx, r8-r11 - могут изменяться внутри вызываемой функции.
Регистры rbx, rbp, rdi, rsi, r12-r15 - должны сохранять своё значение при работе вызываемой функции.
Также спецификация вызова обязует вызывающую процедуру распределять место в собственном стековом фрейме для временного сохранения (spill) значений тех параметров, которые переданы через регистры.
(Оригинальная цитата - "The caller reserves space on the stack for arguments passed in registers. The called function can use this space to spill the contents of registers to the stack.")
Вызываемая процедура может использовать это место по своему усмотрению.
Пример ручного резервирования:
procedure TMethodHandlerInstance.Handler(Params: Pointer); asm .NOFRAME SUB RSP, 28H // - выделяем место в стеке CALL InternalHandler // InternalHandler - может использовать это место адресуясь через [RSP+Offset] MOV [RSP], RAX // - в этих двух строках ещё попользовали отведённое место MOVSD XMM0, [RSP] // в качестве собственной переменной ADD RSP, 28H // - возвращаем место в стеке end;
Листьевые процедуры метятся директивой .NOFRAME, которая гарантирует, что компилятор не будет распределять стековый фрейм.
Локальные процедуры обрабатываются особо. В регистр rcx помещается значение регистра базы (rbp) той процедуры в которую вложена локальная процедура.
От этой базы адресуются локальные переменные охватывающей процедуры.
Таким образом вложенная локальная процедура получает доступ к локальным переменным охватывающей процедуры.
На основании этой информации можно строить заглушки для вызовов локальных функций вместо анонимных.
Ссылки:
http://18delphi.blogspot.ru/2013/03/blog-post_5929.html
http://18delphi.blogspot.ru/2013/07/embarcadero.html
Подсмотреть направление исследований можно в коде Embarcadero. В методе MakeObjectInstance.
Позже я выложу примеры кода.
Комментариев нет:
Отправить комментарий