Программа, которая использует функцию stdcall get_str_length с асемблерной вставкой, для нахождения длины ASCIIZ-строки.
Пример использования директивы ASM и команд сопроцессора в программе на языке Паскаль (Delphi 5.0).
Примеры
Встроенный ассемблер
В ассемблерном модуле в регистре EAX возвращается значение, которое может быть либо числом, либо указателем на некую переменную или структуру. Если возвращаемое число типа WORD, то оно содержится в младшем слове регистра EAX.
Тип возвращаемых функцией данных
Когда происходит взаимодействие ассемблерного модуля с языками высокого уровня, это необходимо учитывать и знать, как работают те или иные соглашения.
Согласование параметров
В таблице ниже представлены основные соглашения по передаче параметров в процедуру.
Ранее во всех ассемблерных программах указывался тип передачи параметров как stdcall. Однако, это никак и нигде не использовалось - так как передача и извлечение параметров делалась явно, без помощи транслятора.
Таблица, представляющая соглашения о вызовах
Соглашение | Параметры | Очистка стека | Регистры |
Pascal (конвенция языка Паскаль) | Слева направо | Процедура | Нет |
Register (быстрый или регистровый вызов) | Слева направо | Процедура | Задействованы три регистра (EAX,EDX,ECX), далее стек |
Cdecl (конвенция С) | Справа налево | Вызывающая программа | Нет |
Stdcall (стандартный вызов) | Справа налево | Процедура | Нет |
Встроенные ассемблеры часто несколько отстают от обычных ассемблеров в части поддержки новых команд микропроцессоров. Это вполне объяснимо, так как разработка новой версии пакета, скажем C++ Builder, требует гораздо больше времени, чем пакета TASM.
Ассемблерные вставки (inline-ассемблер) используются в двух случаях:
1. Если нужно оптимизировать критичные по скорости и небольшие по объему участки программы. Грамотно написанный ассемблерный код всегда быстрее кода, который генерируется компилятором С++ или Delphi.
2. Нужен прямой доступ к памяти и портам. Чаще всего используется в драйверах, так как из третьего кольца защиты с портами не очень-то поработаешь.
program Project2;{$APPTYPE CONSOLE}uses SysUtils;var d:double;function soproc(f:double): double;var res:double;begin asm FLD f FSIN FSTP res end; soproc:=res;end; begin d:=-pi; while (d<=pi) do begin writeln(d:10:2,'-',soproc(d):10:2); d:=d+0.1; end;end.
2) Пример использования директивы ASM и команд сопроцессора в программе на языке Си (Borland C++ 5.0).
#include <windows.h>#include <stdio.h>double soproc(double f); void main(){ double w=-3.14; while(w<=3.14) { printf("%f- %f\n", w, soproc(w)); w=w+0.1; } ExitProcess(0);} double soproc(double f){ double d; asm { FLD f FSIN FSTP d } return d;}
#include "stdafx.h"
int _stdcall get_str_length(char *inputstr)
{
__asm{
mov edi, inputstr
mov esi, edi
mov ecx, -1
xor al, al
cld
repne scasb
sub edi, esi
; Результат работы функции следует возвращать в eax.
mov eax, edi
dec eax
}
}
int main()
{
char str_1[]="Hello, world! My name is Alex...";
int i;
i = get_str_length(str_1);
printf("String: %s\nLength: %d", str_1, i);
printf("\n");
return 0;
}
4) Программа, которая складывает два числа в десятичной системе исчисления и выдаёт результат тоже в десятичной системе исчисления. (Example2)
#include "stdafx.h"
int main()
{
int a = 120;
int b = 159;
int c;
__asm{
mov eax, a
mov ebx, b
add eax, ebx
mov c, eax
}
printf("a + b = %d + %d = %d\n", a, b, c);
return 0;
}