Вопрос

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

long long RtlLargeIntegerDivide(long long dividend, long long divisor, long long* pRemainder)

в коде сборки (NASM). Он использует Конвенцию о вызове STDCALL, и возвращает коэффициент. Это спецификации:

Ввод: [EDX, EAX] (дивиденд), [ECX, EBX] (Divisor)

Вывод: [edx, eax] (коэффициент), [ecx, ebx] (остаток)

Как мне это сделать? (Моя главная проблема - не совсем понимание EBP и ESP, и как они относятся к локальным переменным.)

(И нет, это не домашнее задание; я пытаюсь внедрить библиотеку времени выполнения обертки.)

Благодарю вас!

Это было полезно?

Решение

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top