- •Лекция 24
- •Необходимость сочетания языков высокого и низкого
- •Проблемы использования
- •Правила
- •Соглашения о вызове процедур
- •Соглашения о вызове процедур
- •Способы использования Ассемблерных вставок
- •Ассемблерные вставки
- •Ассемблерные вставки
- •Ассемблерные вставки
- •Пример 1
- •Реализация (вариант 1)
- •Реализация (вариант 2)
- •Реализация (вариант 3)
- •Цикл тестирования
- •Пример 2
- •Ассемблерные модули
- •Ассемблерные модули
- •Пример 3
- •Пример 3 – модуль на Ассемблере в Pelles C
- •Пример 3 – Основная программа в PellesC
- •Пример 3 – модуль на Ассемблере в Visual Studio
- •Настройка компилятора в Visual Studio 2010
- •Пример 4
- •Пример 5
- •;Вызываемая функция file2.asm
Пример 1
Реализовать функцию вычисления расстояния между точками в трехмерном пространстве. Точка задается в виде структуры:
typedef struct{ double x,y,z;
} POINT;
Вфункцию передаются два параметра: указатели на две структуры типа POINT.
Функция возвращает расстояние между точками как вещественное число типа double.
Реализация (вариант 1)
double GetDistance(POINT *p1, POINT *p2)
{
return sqrt(pow(p1->x - p2->x,2.0) +pow(p1->y - p2->y,2.0) +pow(p1->z - p2->z,2.0));
}
Размер генерируемого кода: 149 байт
Реализация (вариант 2)
double GetDistanceOpt(POINT *p1, POINT *p2)
{
double s = (p1->x - p2->x), Sum = s*s;
s= (p1->y - p2->y); Sum += s*s;
s= (p1->z - p2->z); Sum += s*s; return sqrt(Sum);
}
Размер генерируемого кода: 85 байт
Реализация (вариант 3)
double GetDistanceAsm(POINT *p1, POINT *p2)
{
__asm{ push eax push ebx
mov |
eax,dword ptr [p1] |
mov |
ebx,dword ptr [p2] |
fld |
qword ptr [eax] |
fsub |
qword ptr [ebx] |
fmul |
st,st |
fld |
qword ptr [eax+0x08] |
fsub |
qword ptr [edx+0x08] |
fmul |
st,st |
fld |
qword ptr [eax+0x10] |
fsub |
qword ptr [edx+0x10] |
fmul |
st,st |
faddp |
st(1),st |
faddp st(1),st |
|
fsqrt |
|
pop |
ebx |
pop |
eax |
}
}
Размер генерируемого кода: 44 байт
Цикл тестирования
printf("\nTest N..."); stime = clock(); for(i=0;i<NUM;i++)
for(j=0;j<NUM;j++){
double d = GetDistanceN(&list[i],&list[j]);
}
etime = clock();
delay = (etime-stime)*1e3/CLOCKS_PER_SEC; printf("Ok!\nDelay: %.2lf ms\n",delay);
printf("One operation time: %.6lf ms\n",delay/NUM/NUM);
Пример 2
Написать программу осуществляющую проверку: поддерживает ли микропроцессор наборы команд MMX, SSE, SSE2, SSE3, SSE4.
Используется команда CPUID (функция 1h): MMX – Бит 23, регистра EDX.
SSE – Бит 25, регистра EDX.
SSE2 – Бит 26, регистра EDX.
SSE3 – Бит 0, регистра ECX.
SSSE3 – Бит 9, регистра ECX.
SSE4.1 – Бит 19, регистра ECX.
SSE4.2 – Бит 20, регистра ECX.
int |
main(int argc, char *argv[]) |
||||
{ |
int mmx |
= 0, sse = 0, sse2 = 0, sse3 = 0, ssse3 = 0, |
|||
|
|
sse4_1 = 0, sse4_2 = 0; |
|
|
|
|
__asm{ |
eax, 1 |
|
|
|
|
|
mov |
|
|
|
|
|
cpuid |
edx, 800000h |
if(mmx) printf("MMX present!\n"); |
|
|
|
test |
if(sse) printf("SSE present!\n"); |
||
|
|
jz |
exit00 |
||
|
|
if(sse2) printf("SSE2 present!\n"); |
|||
|
|
mov |
dword ptr mmx, 1 |
||
|
|
if(sse3) printf("SSE3 present!\n"); |
|||
|
|
test |
edx, 2000000h |
||
|
|
if(ssse3) printf("SSSE3 present!\n"); |
|||
|
|
jz |
exit00 |
||
|
|
mov |
dword ptr sse, 1 |
if(sse4_1) printf("SSE4.1 present!\n"); |
|
|
|
test |
edx, 4000000h |
if(sse4_2) printf("SSE4.2 present!\n"); |
|
|
|
jz |
exit00 |
return 0; |
|
|
|
mov |
dword ptr sse2, 1 |
} |
|
|
|
test |
ecx, 1 |
|
|
|
|
jz |
exit00 |
|
|
|
|
mov |
dword ptr sse3, 1 |
|
|
|
|
test |
ecx, 200h |
|
|
|
|
jz |
exit00 |
|
|
|
|
mov |
dword ptr ssse3, 1 |
|
|
|
|
test |
ecx, 80000h |
|
|
|
|
jz |
exit00 |
|
|
|
|
mov |
dword ptr sse4_1, 1 |
|
|
|
|
test |
ecx, 100000h |
|
|
|
|
jz |
exit00 |
|
|
|
|
mov |
dword ptr sse4_1, 1 |
|
|
exit00: |
|
|
|
||
|
} |
|
|
|
|
|
|
|
|
|
|
Ассемблерные модули
Ассемблерные модули могут быть подключены в программу двумя способами:
в виде файла исходного кода (расширение .asm) – в этом случае Ассемблерный файл транслируется при компиляции всего проекта (или его части);
в виде объектного файла (расширение .obj) – в этом случае файл исходного кода должен транслироваться отдельно.
Ассемблерные модули
Преимущества:
отсутствие ограничений на использование языка Ассемблер;повышение «переносимости» программы;
возможность использования сторонних трансляторов.
Недостатки:
необходимо корректно отслеживать соглашения;возможна несовместимость форматов объектных файлов при использовании стороннего транслятора;проблемы взаимодействия с оптимизатором языка высокого уровня.
Пример 3
Реализовать на языке Ассемблер подпрограмму вычисления суммы положительных элементов целочисленного массива. В подпрограмму передается указатель на массив и размер массива. Подпрограмма возвращает сумму.
Подпрограмму на Ассемблере оформить в виде отдельного ASM-модуля.