Программирование на Ассемблере

       

Использование отдельных функций на ассемблере


Функция должна удовлетворять соглашениям по вызову для языка С++.

Соглашения по вызову различаются по следующим параметрам:

·        Правила формирования внутреннего имени функции;

·        Правилами передачи параметров;

·        Правилами очистки стека.

При формировании имени возможен регистро – чувствительный или регистро нечувствительный режим, возможно формирование дополнительных символов для обеспечения свойства перегрузки функции.

Для обеспечения возможности использования переменного списка параметров параметры могут записываться в стек, начиная с конца списка, для обеспечения максимальной скорости работы – для передачи параметров используются регистры

Очистку стека может выполнять вызывающая программа или функция.

В табл. 11.4 представлены соглашения по вызову и свойства этих соглашений.

Если файл с программой имеет расширение CPP, то по умолчанию используется режим 1, если файл с расширением С++ - режим 2. Если в программе с расширением СPP необходимо использовать функцию с соглашением С, заголовок этой функции имеет вид:

Extern “C” заголовок;

Если необходимо задать  заголовочный файл, который можно использовать в программе на С и СРР, то применяют директивы

#ifdef __cplusplus



extern “C” {

#endif

заголовок 1;

заголовок 2;

#ifdef __cplusplus

}

#endif

Пример. Составить вызывающую программу и функции вычисления разности для двух чисел, используя все возможные соглашения по вызову.

Таблица 11.4. Соглашения по вызову, принятые в С++

п/п

Тип соглашения

Как задается

Внутреннее имя функции

Порядок передачи параметров

Очистка стека

Переменный список параметров

1.        

Cpp

-

@имя$q[17]…

¬

Вызывающая программа

Да

2.        

С

Extern “C”…

_имя

¬

Вызывающая программа

Да

3.        

Fastcall

Тип __fastcall …

@имя$qqr…

EAX, EDX, ECX

Вызывающая программа

Нет

4.        

Stdcall

Тип

__stdcall …

@имя$qqs…

¬

Функция

Нет

5.        

Pascal

Тип

__pascal …

@ИМЯ$Q…

®

Функция

Нет


// +ыртэр  яЁюуЁрььр
#pragma hdrstop
#include <condefs.h>
#include <stdio.h>
//---------------------------------------------------------------------------
USEASM("std.asm");
USEASM("std1.asm");
USEASM("std2.asm");
USEASM("std3.asm");
USEASM("std4.asm");
//---------------------------------------------------------------------------
#pragma argsused
int __stdcallа substract ( int x, int y, int *z);
intаа substract1 (int x, int y, int *z);
intаа __fastcall substract2 (int x, int y, int *z);
extern "C" intаа substract3 (int x, int y, int *z);
intаа pascal substract4 (int x, int y, int *z);
intаа __fastcall sum (int *x, int y);
int main(int argc, char **argv)
{
ааааа int z;
ааааа substract (3, 2, &z); printf ("%d\n", z);
ааааа substract1 (3, 2, &z); printf ("%d\n", z);
ааааа substract2 (3, 2, &z); printf ("%d\n", z);
ааааа substract3 (3, 2, &z); printf ("%d\n", z);
ааааа substract4 (3, 2, &z); printf ("%d\n", z);
ааааа getchar ();
ааааааа return 0;
}
; stdcall
ideal
p586
model flat
codeseg
procааа @substract1$qiipi
public @substract1$qiipi
argаа a:dword, b:dword, c:dword=s
pushааа ebp
movаааа ebp, esp
pushааа ebx
movаааа eax, [a]
subаааа eax, [b]
movаааа ebx, [c]
movаааа [ebx], eax
popаааа ebx ebp
retаааа
endp
end
;fastcall
ideal
p586
model flat
codeseg
procааа @substract2$qqriipi
publicа @substract2$qqriipi
pushааа esi
movаааа esi, eax
subаааа esi, edx
movаааа [ecx], esi
popаааа esi
retаааа
endp
end
а
;extern C
ideal
p586
model flat
codeseg
procааа _substract3
publicа _substract3
argаа a:dword, b:dword, c:dword=s
pushааа ebp
movаааа ebp, esp
pushааа esi
movаааа esi, [a]
subаааа esi, [b]
movаааа ecx, [c]
movаааа [ecx], esi
popаааа esi ebp
ret
endp
end
; pascal
ideal
p586
model flat
codeseg
proc @SUBSTRACT4$QIIPI
public @SUBSTRACT4$QIIPI
argаа c:dword, b:dword, a:dword=s
pushааа ebp
movаааа ebp, esp
pushааа esi
movаааа esi, [a]
subаааа esi, [b]
movаааа ecx, [c]
movаааа [ecx], esi
popаааа esi ebp
retаааа s
endp
end

Содержание раздела