Организацию такой связи рассмотрим на примере следующей задачи: разработать программу на языке Pascal, которая выводит символ заданное количество раз, начиная с определенной позиции на экране. Все числовые аргументы определяются в программе на Pascal. Вывод символа осуществляет процедура ассемблера. Очевидно, что основная проблема в этой задаче - организация взаимодействия модулей на Pascal и ассемблере.
Модуль на Pascal (листинг 1).
<1> {prg1.pas}
<2> {Программа вызывающая процедуру на ассемблере}
<3> program my_pas;
<4> {$D+} {включение полной информации для отладчика}
<2> ; Процедура на ассемблере, которую вызывает программа на Pascal.
<3> ; Для вывода на экран используются службы BIOS:
<4> ; 02h - позиционирование курсора.
<5> ; 09h - вывод символа заданное количество раз.
<6> MASM
<7> MODEL small
<8> STACK 256
<9> .code
<10> asmproc proc near
<11> PUBLIC asmproc ; объявлена как внешняя
<12> push bp ; пролог
<13> mov bp, sp
<14> mov dh, [bp+6] ; номер строки для вывода символа y - в dh
<15> mov dl, [bp+8] ; номер столбца для вывода символа х - в dl
<16> mov ah, 02h ; номер службы BIOS
<17> int 10h ; вызов прерывания BIOS
<18> ; вызов функции 09h прерывания BIOS 10h:
<19> ; вывод символа из al на экран
<20> mov ah, 09h ; номер службы BIOS
<21> mov al, [bp+10] ; символ ch в al
<22> mov bl, 07h ; атрибут символа - в bl
<23> xor bh, bh
<24> mov cx, [bp+4] ; количество выводов символа - в cx
<25> int 10h ; вызов прерывания BIOS
<26> pop bp ; восстановление bp
<27> ; очистка стека и возврат из процедуры
<28> ret 8
<29> asmproc endp ; конец процедуры
<30> end
Типовая схема организации такой связи следующая:
hНаписать процедуру на ассемблере дальнего (far) и ближнего типа (near). Назовем ее для примера asmproc. В программе на языке ассемблера (назовем ее prg2.asm), в которую входит процедура asmproc, необходимо объявить имя этой процедуры внешним с помощью директивы PUBLIC.
PUBLIC asmproc
Для того чтобы процедура на ассемблере при компоновке с программой на Pascal воспринималась компилятором Borland Pascal 7.0 как far или near, недостаточно будет просто объявить ее таковой в директиве proc. Вам нужно включить или выключить опцию компилятора, доступную через меню интегрированной среды: Options4Compiler4Force far calls. Установка данной опции заставляет компилятор генерировать дальние вызовы программ. Альтернатива данной опции - ключ в программе {$F+} или {$F-} (соответственно, включено или выключено). Это - локальные ключи, то есть в исходном тексте программы на Pascal их может быть несколько, и они могут, чередуясь друг с другом, поочередно менять форму генерируемых адресов перехода - для одних подпрограмм - дальние вызовы, для других - ближние.
hПроизвести компиляцию программы prg1.pas, которая будет вызывать внешнюю процедуру на ассемблере, следует вставить директиву компилятора
{$L \путь\prg1.obj}. Эта директива заставит компилятор в процессе компиляции программы prg1.pas загрузить с диска объектный модуль программы prg1.obj. В программе prg1.pas необходимо объявить процедуру asmproc как внешнюю. В итоге последние два объявления в программе на Pascal будут выглядеть так:
hесли вы собираетесь исследовать в отладчике работу программы, то необходимо потребовать, чтобы компилятор включил отладочную информацию в генерируемый им исполняемый модуль. Для этого есть две возможности. Первая заключается в использовании глобального ключа {$D+}. Этот ключ должен быть установлен сразу после заголовка программы на Pascal. Вторая, альтернативная возможность заключается в установке опции компилятора: Options4Compiler4 Debug Information;
hвыполнить компиляцию программы на Pascal. Для компиляции удобно использовать интегрированную среду. Для изучения особенностей связки Pascal - ассемблер удобно прямо в интегрированной среде перейти к работе в отладчике через меню Tools4Turbo Debugger (или клавишами Shift+F4). Будет загружен отладчик. Его среда вам хорошо знакома; в данном случае в окне Module вы увидите текст программы на Pascal. Нажимая клавишу F7, вы в пошаговом режиме будете исполнять программу на Pascal. Когда очередь дойдет до вызова процедуры на ассемблере, отладчик откроет окно с текстом программы на ассемблере. Но наш совет вам - не ждать этого момента, так как вы уже пропустили некоторые интересные вещи. Дело в том, что отладчик скрывает от вас момент перехода из программы на Pascal в процедуру на ассемблере. Поэтому лучше всего исполнять программу при открытом окне CPU отладчика. И тогда вы станете свидетелями тех процессов, которые мы будем обсуждать ниже.