Как я передаю аргументы функциям C++, когда я называю их от встроенного ассемблерного кода

Так, я хотел бы смочь вызвать функции от C++ dll. По определенным причинам я хотел бы назвать их от __ asm блок в моем коде C++. Мой вопрос - это: Я знаю, что, прежде чем я вызову функцию, я должен продвинуть ее аргументы на стеке в порядке, указанном соглашением о вызовах функции. Однако могу я просто делать что-то вроде этого:

int a=5;   
double b = 5.0;  
__asm{  
       push b 
       push a  
       call functionAddress  
}

То, что волнует меня, является тем, что я, кажется, помню, что стандартный размер слова в блоке составляет 2 байта, в то время как размер интервала в C++ обычно - 4 байта и 8 байтов для двойного. Так, в примере выше, я действительно продвигаю полную стоимость каждой переменной, или просто первые два байта? Если бы код выше не является правильным, каков был бы правильный способ сделать это? Кроме того, если функция, мы называем возвраты двойным, где это значение хранится? Я предполагаю, что это не может быть в регистре, потому что это может только сохранить 32 бита (4 байта).Any, справка с этой путаницей значительно ценилась бы :)

8
задан Emil D 22 February 2010 в 18:47
поделиться

3 ответа

Для передачи 8-байтовых значений, таких как двойные, вы не сможете использовать обычную инструкцию PUSH . И вы также не помещаете параметры с плавающей запятой (или двойные) в стек с плавающей запятой. Вам нужно «вручную» положить эти параметры жира в стек. Например, чтобы передать π в качестве параметра функции f:

  __asm {
    FLDPI                    // load pi onto FP stack
    SUB ESP,8                // make room for double on processor stack
    FSTP QWORD PTR [ESP]     // store pi in proc stack slot (and pop from FP stack)
    CALL f
    ADD ESP,8                // clean up stack (assuming f is _cdecl)
  }
13
ответ дан 5 December 2019 в 09:25
поделиться

В общем, вы будете использовать полный размер компьютерного слова. Это зависит от чипа, но на 32-битном Intel это будет 4 байта, а на 64-битном Intel - 8 (в зависимости от компилятора - Visual Studio все еще поддерживает только сборку IA32 - так что 4 байта).

Лучший ответ - посмотреть документацию для вашего конкретного компилятора.

1
ответ дан 5 December 2019 в 09:25
поделиться

32-битная архитектура x86 автоматически дополняет значения, помещаемые в стек, до 32 бит.

Есть кое-что, о чем нужно помнить. Если функция, которую вы вызываете, использует соглашение о вызовах __cdecl, вы должны «вытолкнуть» то, что вы отправили позже. Однако для функций __stdcall этого делать нельзя.

extern "C" int    __cdecl   function1(int, double);
extern "C" double __stdcall function2(char, char*);

int a = 5;
double b = 5.0;
int retval1;
char c = '5';
char *d = "Hello";
double retval2;

__asm {
    push b
    push a
    call function1
    add esp, 4*2 // "pop" what we pushed
    mov retval1, eax
    push d
    push c
    call function2
    mov retval2, eax
}
4
ответ дан 5 December 2019 в 09:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: