===== Механизм связки Си-Ассемблер =====
На предыдущих уроках мы познакомились с гибридным программированием. В этом разделе будет дана теоретическая модель построения связи asm-c
Данный способ передачи параметров используется в языках программирования Си, Си++, Пролог и других. Этот метод противопоставлен методу языка Паскаль, поэтому связка asm-pascal будет выглядеть по-другому!
Итак, если мы определим функцию в Сиint foo (int a,int b,int c,int d);
то при вызове функции выполнятся следующие машинные инструкции:
push d
push c
push b
push a
call _foo
add sp,8 ;Освобождение стека осуществляется автоматически!
При этом для правильного использования переданных параметров процедура //foo// может выглядеть так:
_foo proc
push bp
mov bp,sp
a = [bp+4]
b = [bp+6]
c = [bp+8]
d = [bp+10]
...
pop bp
ret
_foo endp
==== Пример библиотеки, которая выводит символ на экран ====
Модуль Assembler
.MODEL small
public _put_symbol
extrn _cursor, _type_crt, _mode
.CODE
_put_symbol proc near
cli
push bp
mov bp,sp
mov cx,_type_crt
cmp cx,0
je _monocrome
mov dx,0b800h
jmp _continue
_monocrome:
mov dx,0b000h
_continue:
mov es,dx
mov bx,_cursor
shl bx,1
mov al,[bp+4]
mov ah,[bp+6]
mov es:[bx],ax
pop bp
mov ax,0
sti
ret
_put_symbol endp
end
Заголовочный файл для предыдущего модуля
/* Хидерный файл контроллера Motorola 6845 */
char type_crt = 1; /* Тип монитора. 0 - MDA, 1 - CGA, EGA e t.c.*/
unsigned char mode = 03; /* Режим, очевидно */
extern unsigned int cursor = 0; /* Позиция курсора в линейном режиме */
extern unsigned char attribut = 7; /* Его атрибут */
extern int put_symbol (unsigned char symbol, unsigned char attribut);
Обратите внимание на эти строки:
_put_symbol proc near
push bp
mov bp,sp
...
mov al,[bp+4]
mov ah,[bp+6]
...
pop bp
_put_symbol endp
Это - передача параметров процедуре ассемблера без использования директивы ARG.
В модуле языка Си записано следующее:
extern int put_symbol (unsigned char symbol, unsigned char attribut);
Это значит, что передаваемые параметры начинались с адреса bp+4
==== Альтернативный вариант написания процедур на ассемблере ====
Во многих ассемблерах (в том числе и TASM) встроена поддержка передачи параметров с использованием директивы //ARG// или усложнённой директивы //proc//
Пример:
_foo proc C, a: word, b: word, c: word, d: word
...
ret
_foo endp
В данном методе нельзя использовать регистр BP!