Реферат: Взаимосвязь языков C и ассемблера
Раздел 3: Вызов ассемблерных функций из С
3.1 Символы подчеркивания
Как показывает практика, все символы PUBLIC и EXTERN должны начинаться символами подчеркивания. Это необходимо делать только в ассемблерном модуле (но не в исходной про грамме С или C++), поскольку компилятор добавляет подчеркивание ко всем глобальным символам, если только не используется опция -u для компиляции программ. (Не стоит применять эту опцию, если только не надо также перекомпилировать всю используемую при выполнении С библиотеку, в которой предполагается, что все глобальные символы начинаются символом подчеркивания.) Если во время компоновки выходит сообщение об ошибке "undefined symbol" (неопределенный символ), то причиной может оказаться отсутствие подчеркивания в ассемблерном модуле.
3.2 Использование дальних данных
Если объявляются переменные в дальнем сегменте данных после ключевого слова FARDATA, то необходимо подготовить сегментный регистр к размещению переменных в памяти. Прежде всего, вслед за директивой FARDATA необходимо объявить данные:
FARDATA
_OuterLimits dw ?
Затем, в кодовом сегменте, следует перед использованием переменной подготовить сегментный регистр. Одним из возможных подходов является использование оператора SEG для загрузки адреса дальнего сегмента данных:
mov ax, SEG_OuterLimits;Адресует дальний сегмент ;данных
mov es, ах ;посредством es
mov [es:_OuterLimits], dx ;Резервируется dx для пере ;менной
Можно также использовать заранее определенный символ @fardata:
mov ах, @fardata
mov es, ах
mov [es:_OuterLimits], dx
3.3 Вызов ассемблерных функций из С
Чаще всего asm код оформляют в виде отдельных asm функций, которые потом соединяют на этапе загрузки. Ассемблерный код должен поддерживать стиль языка С для вызова функций, которые включают передачу параметров, возврат значений и правила сохранения регистров, которые требуются для С++ функций.
Компилятор и загрузчик должны работать совместно для обеспечения вызовов между модулями. Процесс называется исключением или ломкой имен. Предусматривает наличие информации о типе аргумента. Ломка имени изменяет имя функции, показывая, что за аргумент принимает функция. Когда мы конструируем на языке С++, то ломка имен происходит автоматически.
Когда же пишется модуль на asm, который должен быть подсоединен к модулю на языке С++, необходимо позаботиться о том, чтобы asm модуль содержал ломку имен (знак подчеркивания). Это можно сделать путем написания фиктивной функции на С++ и компилировать его в asm код. И ассемблерный файл, который будет сгенерирован компилятором С++, будет содержать ломку имен, которые мы можем потом использовать при написании asm функции:
@ имя класса @ исходное имя функции $g описание типов
, где
@ - связующий символ
$ - конец исходного имени функции
g - начало описания типов параметров
Пример:
void test() {}
void test(int...) {}
void test(int, int) {}
void test(float, double) {}