Таблица 4 Способ передачи параметров функциями языка Си
Тип возвращаемого значения С++ |
Приемник результата |
unsigned char |
AX |
char |
AX |
enum |
AX |
unsigned short |
AX |
short |
AX |
unsigned int |
AX |
int |
AX |
unsigned long |
DX:AX |
long |
DX:AX |
float |
ST(0) |
double |
ST(0) |
long double |
ST(0) |
near* |
AX |
far* |
DX:AX |
В качестве примера программы со вставкой кода на ассемблере рассмотрим функцию, которая производит преобразование строчных букв в прописные и наоборот.
#include <iostream.h>
#include <string.h>
char *str = "Upper And Lower Case 12345";
char chngcs(char x)
{
asm mov al,x
asm cmp al,'A'
asm jb ext
asm cmp al,'z'
asm ja ext
asm cmp al,'Z'
asm ja met
asm add al,20h
asm jmp ext
met:
asm cmp al,'a'
asm jb ext
asm sub al,20h
ext:
}
void main()
{
char *ptr=str;
cout << "Before: " << str << "\n";
while(*ptr) *ptr++=chngcs(*ptr);
cout << " After: " << str << "\n";
}
Компиляторы языка Си автоматически дополняют внешние имена символом подчерка вначале идентификатора, поэтому, для обеспечения совместимости, в модуле на языке ассемблера такие имена также должны начинаться с символа подчерк.
model small
.stack 256
.data
filda dw 1
.code
_main proc
PUBLIC _main
EXTRN _cproc:proc
mov ax,@data
mov ds,ax
push filda
mov ax,76
push ax
call _cproc
add sp,4
.exit 0
_main endp
end _main
#include <stdio.h>
void cproc(x,y)
int x;
int y;
{
printf("Rez %d %d\n",x,y);
getch();
}
В языке С++ компилятор добавляет к имени функции вместо подчерка символ «@» в начале идентификатора и описание параметров (начинающееся символами $q) в конце.
model small
.stack 256
.data
filda dd 1.5
.code
_main proc
PUBLIC _main
EXTRN @cproc$qif:proc
mov ax,@data
mov ds,ax
push filda
mov ax,76
push ax
call @cproc$qif
add sp,6
.exit 0
_main endp
end _main
#include <iostream.h>
void cproc(int x,float y)
{
cout << "Rez " << x << " " << y << "\n";
}
При этом для формирования имени функции берется одна буква от каждого спецификатора типа. Например, i – integer, f – float, d – double, p – указатель, u – unsigned, x – const, r – ссылка, c – char, l – long, s – short, v - void.
Если функция, написанная на ассемблере, является функцией членом класса, то имя такой функции начинается с символа «@» и имени класса. Остальная часть имени формируется по правилам описанным выше.
При вызове функции, написанной на ассемблере, из программы, написанной на Си++, в её тексте должен встречаться оператор EXTERN, описывающий прототип функции. Если в качестве типа будет указан тип «С», то функция на ассемблере можно оформлять стандартным образом не задумываясь об искажении имен.
Например.
#include <conio.h>
extern "C" void asmproc(char ch,unsigned x,unsigned y,unsigned kol);
void main(void)
{
clrscr();
asmproc('a',2,3,5);
asmproc('c',9,2,7);
}
.model small,c
.stack 256
.code
PUBLIC asmproc
asmproc proc c near
ARG chr:BYTE,x:WORD,y:WORD,kol:WORD
USES ax,dx,cx,dx
mov dh,byte ptr y ; строка
mov dl,byte ptr x ; столбец
xor bh,bh ; видеостраница
mov ah,2 ; позиционирование курсора
int 10h
mov ah,9 ; вывод символа
mov al,chr ; символ
mov bl,7 ; атрибут
mov cx,kol ; мультипликатор
int 10h
ret
asmproc endp
end
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.