Называя тип longlong RtlLargeIntegerDivide(тип longlong, тип longlong, тип longlong*) в NASM (нарушением соглашения о стандартном)
Я пытаюсь вызвать следующую функцию:
long long RtlLargeIntegerDivide(long long dividend, long long divisor, long long* pRemainder)
В ассемблерном коде (NASM). Он использует соглашение о вызове stdcall и возвращает частное. Это спецификации:
Входные данные: [EDX, EAX] (дивиденд), [ECX, EBX] (делитель)
Выходные данные: [EDX, EAX] (частное), [ECX, EBX] (остаток)
Как мне это сделать? (Моя главная проблема заключается не в точном понимании EBP и ESP, а в том, как они соотносятся с локальными переменными.)
(и нет, это не домашнее задание; Я пытаюсь реализовать оболочку C библиотеки времени выполнения.)
Спасибо!
1 ответ:
В 32-битном режиме вам вообще не нужно использовать EBP для доступа к локальным переменным, это просто остаток соглашения от 16-битных времен и нас сейчас не касается.
ESP-это ваш указатель стека, я полагаю, вы это знаете. Вы можете "выделить" пространство для ваших локальных переменных, уменьшив ESP.
соглашение о вызове stdcall использует стек для передачи аргументов. Они находятся в обычном порядке, когда находятся в стеке, но если вы используете
PUSH
, это означает, что вы нажимаете их в обратном порядке. Интегральные возвращаемые значения находятся в EAX (и EDX, когда это необходимо). Вызываемая функция очищает аргументы из стека.Итак, следующий код должен делать то, что вы хотите:
sub ESP, 8; make room for remainder push ESP ; pass pointer to remainder as argument push ECX push EBX ; pass divisor argument push EDX push EAX ; pass dividend argument call RtlLargeIntegerDivide ; quotient returned in EDX:EAX ; so just load remainder from stack pop EBX pop ECX
(для скорости вы можете использовать
MOV
вместоPUSH
/POP
)