Вызов LONGLONG RtlLargeIntegerDivide (LONGLONG, LONGLONG, LONGLONG *) в NASM (стандартный вызов) - PullRequest
2 голосов
/ 26 декабря 2010

Я пытаюсь вызвать следующую функцию:

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 Ответ

4 голосов
/ 27 декабря 2010

В 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)

...