Вызов функции Турбо Ассемблера из Borland C++
Теперь мы рассмотрим пример программы на Borland C++, вызы- вающей функцию Турбо Ассемблера. Модуль Турбо Ассемблера COUNT.ASM содержит функцию LineCount, которая возвращает значение счетчика числа строк и символов в передаваемой строке:
; Вызываемая из С++ функция на Ассемблере с малой моделью памяти ; для подсчета числа строк и символов в завершающейся нулем ; "строке". ; ; Прототип функции: ; extern unsigned int LineCount(char * near StringToCount, ; unsigned int near * CharacterCountPtr); ; ; Ввод: ; char near * StringToCount: указатель на "строку", в ; которой нужно выполнить подсчет строк. ; ; unsigned int near * CharacterCountPtr: указатель на ; целую переменную, в которую нужно записать значение ; счетчика NEWLINE EQU 0ah ; символ перевода строки в Си .MODEL SMALL .CODE PUBLIC _LineCount __LineCount PROC push bp mov bp,sp push si ; сохранить регистровую ; переменную вызывающей ; программы mov si,[bp+4] ; SI указывает на строку sub cx,cx ; установить значение ; счетчика символов в 0 mov dx,cx ; установить в 0 счетчик ; строк LineCountLoop: lodsb ; получить следующий символ and al,al ; это 0? конец строки? jz EndLineCount ; да, выполнено inc cx ; нет, подсчитать следующий ; символ cmp al,NEWLINE ; это новая строка? jnz LineCountLoop ; нет, проверить ; следующий символ inc dx ; да, подсчитать еще одну ; строку jmp LineCountLoop EndLineCount: inc dx ; подсчитать строку, которая ; завершается нулевым символом mov [bx],cx ; задать значение переменной- ; счетчика mov ax,dx ; возвратить счетчик строк в ; качестве значения счетчика pop si ; восстановить регистровую ; переменную вызывающей ; программы pop bp ret _LineCount ENDP END
Следующий модуль на языке С++ с именем CALLCT.CPP представ- ляет собой пример вызова функции LineCount:
char * TestString="Line 1\nline 2\nline 3"; extern "C" { unsigned int LineCount(char * StringToCount, unsigned int near * CharacterCountPtr); } main() { unsigned int LCount; unsigned int CCount;
Lcount = LineCount(TestString, &CCount); printf("Lines: %d\nCharacters: %d\n", LCount, CCount); }
Два модуля компилируются и компонуются вместе с помощью ко- мандной строки:
bcc -ms callct.cpp count.asm
Как здесь показано, функция LineCount будет работать только при компоновке с программами на языке С++, в которых используется малая модель памяти, так как в других моделях размеры указателей и адресов в стеке изменятся. Приведем пример версии функции LineCount (COUNTLG.ASM), которая будет работать с программами на С++, использующим большую модель памяти (но не малую модель: пос- кольку передаются дальние указатель, функция LineCount также опи- сана, как функция дальнего типа):
; Вызываемая из С++ функция на Ассемблере для подсчета числа ; строк и символов в завершающейся нулем "строке". ; ; Прототип функции: ; extern unsigned int LineCount(char * far StringToCount, ; unsigned int far * CharacterCountPtr); ; ; Ввод: ; char far * StringToCount: указатель на "строку", в ; которой нужно выполнить подсчет строк. ; ; unsigned int far * CharacterCountPtr: указатель на ; целочисленную переменную, в которую нужно записать ; значение счетчика NEWLINE EQU 0ah ; символ перевода строки в Си .MODEL LARGE .CODE PUBLIC _LinaCount _LineCount PROC push bp mov bp,sp push si ; сохранить регистровую ; переменную вызывающей ; программы push ds ; сохранить стандартный ; сегмент данных lds si,[bp+6] ; DS:SI указывает на строку sub cx,cx ; установить значение ; счетчика символов в 0 mov dx,cx ; установить в 0 счетчик ; строк LineCountLoop: lodsb ; получить следующий символ and al,al ; это 0? конец строки? jz EndLineCount ; да, выполнено inc cx ; нет, подсчитать следующий ; символ cmp al,NEWLINE ; это новая строка? jnz LineCountLoop ; нет, проверить ; следующий символ inc dx ; да, подсчитать еще одну ; строку jmp LineCountLoop EndLineCount: inc dx ; подсчитать строку, которая ; завершается нулевым символом les bx,[bp+10] ; ES:BX указывает на ячейку, ; в которой возвращается ; значение счетчика mov es:[bx],cx ; задать значение переменной- ; счетчика mov ax,dx ; возвратить счетчик строк в ; качестве значения счетчика pop ds ; восстановить стандартный ; сегмент данных Си pop si ; восстановить регистровую ; переменную вызывающей ; программы pop bp ret _LineCount ENDP END
Программу COUNTLG.ASM можно скомпоновать с CALLCT.CPP с по- мощью следующей командной строки:
bcc -ml callct.cpp countlg.asm
Содержание раздела