Смекни!
smekni.com

Взаимосвязь языков C и ассемблера

Раздел 1:Регистры ипараметры


1.1 Использованиерегистров


В создаваемыхассемблерныхпрограммахможно использоватьвсе регистрыпроцессора.Но чтобы предотвратитьпутаницу сфункциями Си С++, необходимовосстанавливатьbp, cs, sp и ss, которыеони имели дозапуска созданнойподпрограммы.Тогда можнобыть совершенноуверенным, чтообращение кдругим функциямне изменит этирегистры. Такженельзя забывать,что С используетрегистры si иdi для регистровыхпеременных,поэтому прииспользованиивстроенногоассемблеразамедляетсяобщая работапрограммы.

К регистрамax, bx, cx, dx и es можнообращатьсясвободно и ненужно резервироватьих значениядо окончанияподпрограммы.Эта свободакасается идругих функций,поэтому надопомнить, чтоэти регистрыизменяться,если вызываютсяфункции С и С++из ассемблерныхподпрограмм.


1.2 АссемблерныеоператорыInline


Ассемблерныеоператорыinline начинаютсясловом asm, закоторым следуетинструкцияи ее операнды.Например, чтобысинхронизироватьпрограмму свнешним сигналомпрерывания,можно написать:

/* ожиданиепрерывания*/

asm sti

asm hlt

printf(“Прерываниеполучено\n”)

Когда ранниеверсии Turbo C компилируютпрограмму совстроеннымикомандами asm,компиляторсперва создаетассемблерныйтекст для всейпрограммы,вставляя втекст нашиассемблерныеинструкциивместе с откомпилированнымкодом для остальныхоператоровС. Затем компиляторвызывает TurboAssembler и Linker (компоновщик),чтобы провестиассемблированиеи подключитьпрограмму кконечному файлукода. Болеепоздние версииTurbo и Borland C++ могуткомпилироватьоператоры asmбез вызоваTASM. Полный синтаксисasm:

asm[метка]мнемоника/директиваоперанды [;] [/*Скомментарий*/]

Точки с запятымив конце строкasm и комментарииС, расположенныемежду /*и*/ удаляютсяиз текста передассемблированием,поэтому ихможно опускатьв тексте программы.


1.3 Размещениеданных и операторовв тексте программы


Каждая строкатекста программыС и С++ находитсялибо внутри,либо снаружифункции, и операторыasm могут вставлятьсякак в одном,так и в другомместе. Конкретноеположениеоператора asmвлияет на то,куда ассемблируетсякод или директива.Если операторasm появляетсяснаружи функции,то он ассемблируетсяв сегмент данныхпрограммы, есливнутри функции- в кодовый сегмент.Обычно, чтобысоздать переменные,операторы asmвставляютсяснаружи функций;для созданиякода их следуетвставлятьвнутрь функций.Например:

asm count db ?

int main()

{

asm shl [count], 1/*умножениеcount на 4*/

asm shl [count], 1

return 0;

}

Переменнаяcount объявляетсяв сегментеданных программы(относительноds). Операторывнутри функцииmain умножают countна 4, используявместо mul быстрыеинструкциисдвига shl. Еслиобъявлятьпеременныевнутри функции,данные ассемблируютсяв кодовый сегмент,требуя особогообхождения:

int main()

{

asm jmp OverThere

asm count db ?

OverThere:

asm shl [count], 1 /* умножениеcount на 4*/

asm shl [count], 1

return 0;

}

Посколькутеперь переменнаяcount находитсяв кодовом сегменте,требуетсяинструкцияjmp, чтобы избежатьслучайноговосприятиязначения count вкачестве машинногокода и егоисполнения.


7



Раздел 2:Особенностиданных


2.1 Разделениеданных


Inline операторыasm имеют свободныйдоступ к переменными структурамС и C++ - одно изсамых привлекательныхпреимуществметода inline посравнению сподходом посредствомвнешних модулей.Самое интересноев типах данныхассемблераи С++, что dq можетиспользоватьсядля созданияинициализированныхпеременныхдвойной длиныс плавающейточкой в языкеассемблера,но в Turbo Assembler отсутствуютдирективы длянепосредственногосоздания переменныхс плавающейточкой.

В операторахasm можно ссылатьсяна переменныетипов С++. Например:

unsigned char initial

initial = 'T'

asm mov dl, [initial] /*Загрузкасимвола в dl*/

asm mov ah, 2 /* Пересылкасимвола в ДОС*/

asm int 21h /* Стандартнаявыходная функция*/

Беззнаковаясимвольнаяпеременнаяinitial загружаетсяоператоромasm в dl. Так как иdl, и беззнаковыесимвольныеданные имеютдлину одинбайт, нет необходимостив ссылке использоватьопределительByte, хотя его применениеи не будет ошибкой:

asm mov dl, [Byte ptr initial]


2.2 Объявлениеассемблерныхданных


Можно объявитьпеременныедля использованиятолько ассемблернымиоператорами.Например, чтобысоздать 16-битовоеслово с именемTwoBytes и загрузитьзначение переменнойв сх, можно написать:

asm TwoBytes db 1, 2

int main()

{

asm mov cx, [Word ptr TwoBytes]

return 0

}

ПеременнаяTwoBytes объявляетсяв сегментеданных программы(снаружи функции),с использованиемдирективы db,чтобы хранитьв памяти 2 байта(1 и 2). Операторассемблеразатем загружаетTwoBytes в сх. ОпределительWordptr необходимдля ссылки наTwoBytes как на 16-битовоеслово.

ПосколькуTwoBytes объявляетсяв оператореasm, на эту переменнуюнельзя ссылатьсяв тексте программыС или C++. Поэтому,если тольконе требуютсяотдельныепеременныедля ассемблерныхинструкций,следует объявлятьих обычнымобразом и ссылатьсяна них из ассемблерногомодуля.


2.3 Разделениекода


Ассемблерныеоператорыinline могут вызыватьфункции С иC++, а операторыС и C++ обращатьсяк функциям,написаннымполностью наассемблере.Вся эта взаимосвязьбудет хорошорассмотренав данном курсовомпроекте.

8



Раздел 3: Вызовассемблерныхфункций из С


3.1 Символыподчеркивания


Как показываетпрактика, всесимволы PUBLIC иEXTERN должны начинатьсясимволамиподчеркивания.Это необходимоделать тольков ассемблерноммодуле (но нев исходной программе С илиC++), посколькукомпилятордобавляетподчеркиваниеко всем глобальнымсимволам, еслитолько неиспользуетсяопция -u длякомпиляциипрограмм. (Нестоит применятьэту опцию, еслитолько не надотакже перекомпилироватьвсю используемуюпри выполненииС библиотеку,в которойпредполагается,что все глобальныесимволы начинаютсясимволомподчеркивания.)Если во времякомпоновкивыходит сообщениеоб ошибке "undefinedsymbol" (неопределенныйсимвол), то причинойможет оказатьсяотсутствиеподчеркиванияв ассемблерноммодуле.


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) {}

Что будетв ассемблере?

1. @ test $ gv proc near

push bp

mov bp, sp

pop bp

ret

@ test $ gv endp


2. @ test $ gi proc near

.............

@ test $ gi endp


3. @ test $ gii proc near

............

@ test $ gii endp


4. @ test $ gfd proc near

............

@ test $ gfd endp


BC++ разрешаетиспользованиенеискаженныхимен asm функций,определяястандартныеимена С функцийв С программах.Для этого впрограммеопределяетсявнешний С блок:

extern “C”{

int add(int *a, int b);

}

________________

public _add

_add proc ...и т.д.


Определениеили декларированиеasm функции вовнешнем С блокеизбавляетпрограммистаот необходимостиопределениядействительногоимени ассемблернойфункции и повышаетнаглядность.

С++ передаетпараметрыфункции черезстек. Перед темкак вызватьфункцию С++ помещаетпараметры встек, начинаяс последнего.


3.4 Ассемблированиеи компоновкавнешних модулей


Существуетнесколькометодов ассемблирования,компиляциии компоновкиотдельныхмодулей (ианалогичныхмногофайловыхпрограмм) длясоздания конечной.ЕХЕ программы.Проще всегопредоставитьпроделать всеэто Turbo С:

tcc cfillstr cfill.asm/*первыймодуль - cfillstr.c*/

Если используетсяBorland C++, надо ввестиследующуюкоманду (заменитьbсс на tсс дляTurbo C++):

bcc cfillstr.с cfill.asm

В любом случаекоманда спервакомпилируетCFILLSTR.C в CFILLSTR.OBJ. Затем,распознаврасширениеимени файла.ASM как имя ассемблерногомодуля, компиляторвызывает TurboAssembler, чтобы ассемблироватьCFILL.ASM в CFILL.OBJ. И наконец,компиляторвызывает Turbo Linkerдля объединениямодулей с объектнымикодами в CFILLSTR.EXE. Есликомпиляциии ассемблированиюподлежит небольшоеколичествомодулей, этотодношаговыйметод наиболеепрост дляиспользования.

Если у имеетсябольшое количествомодулей, можносэкономитьвремя, осуществляяассемблированиеи компоновкураздельно.Первым шагомследует ассемблироватьвсе .ASM файлы.Посколькупример flllsrting обладаеттолько однимтаким файлом,все можно проделатьс помощьюединственнойкоманды

tasm /ml cfill.asm

Опция /ml включаетразличениестрочных ипрописныхсимволов, чтобык примеру словаUpAndDown и upanddown рассматривалиськак различные- как это принятов программахС и C++. (Turbo Assembler обычноне обращаетвнимания нато, в каком регистренабраны символы,поэтому опция/ml необходимаво избежаниеошибок прикомпоновке.)После ассемблированиявсех внешнихмодулей откомпилироватьосновную программу.Опять же, посколькув этом примереимеется толькоодин файл .С,для этого необходиматолько однакоманда

tcc -с cfillstr.c

Если используетсяBorland C++, надо применитьследующуюкоманду (заменитьbсс на tсс дляTurbo C++):

bсс -с cfillstr.c

Опция -с означает"только компилировать",вызывая созданиеCFILLSTR.OBJ, но не компоновкупрограммы взаконченныйкодовый файл.Для включениявсех модулейнеобходимовыполнить этотшаг самим, вызываяTurbo Linker для объединенияфайлов с объектнымкодом с соответствующимибиблиотечнымиподпрограммамидля созданияCFILLSTR.EXE. Существуетдва методакомпоновки.Сначала рассмотримболее сложныйметод:

t1ink с:\tc\lib\c0s cfillstr cfill, cfillstr,,с:\tc\lib\cs

При использованииBorland C++4 можно применитьследующуюкоманду:

tlink с:\bc4\lib\c0s cfillstr cfill, cfillstr,,с:\bc4\lib\cs

Первый членпосле tlink специфицируетфайл объектногокода в директории\LIB для соответствующеймодели памяти,в данном случае- COS.OBJ. Второй и третийчлены перечисляютподлежащиекомпоновкефайлы с объектнымкодом .OBJ - онимогут бытьперечисленыв любом порядке.Запятая отделяетсписок файлов.OBJ от имени, котороедолжно использоватьсядля конечногофайла, в данномслучае - CFILLSTR-EXE. Двезапятые, следующиеза этим, показываютместо необязательногофайла карты(*.map), не создающегосяв данном примере.И наконец,специфицируетсярабочая библиотека- также в каталоге\LIB.

Имена файлас объектнымкодом COS и библиотечнымфайлом CS должнысоответствоватьмодели памяти,используемойпрограммой.

Упрощенный(но не оченьбыстрый) методкомпоновкиотдельныхмодулей состоитв использованиикомпиляторав качестве"первой части"Turbo Linker. Другимисловами, вставляяразличныекоманды компиляции,можно пропуститькомпиляциюи перейти прямок компоновке.Это дает возможностьизбежатьнеобходимостиспецифицироватьимена рабочихбиблиотечныхфайлов и, следовательно,упрощает командукомпоновки.Например, дляассемблирования,компиляциии компоновкиCFILLSTR этим методомтребуются трикоманды:

tasm /ml cfill.asm

tee -с cfillstr.c

tee -ms cfillstr.obj cfill.obj

Для Borland C++ надоввести следующиекоманды (заменитьbсс на tсс дляTurbo C++):

tasm /ml cfill.asm

bee -с cfillstr.с

bee -ms cfillstr.obj cfill.obj

Первые двекоманды - теже, что былиописаны выше.Третья вызываеткомпиляторво второй раз,используя опцию-ms для определениямодели памяти,в данном случаеsmall (малая). Вследза опцией моделипамяти идутфайлы с объектнымкодом, подлежащиекомпоновке.Хотя приходитсявключать расширениеимен файлов.OBJ в перечислениекаждого файла,этот не оченьдлинный методкомпоновкиупрощает большуючасть черновойработы понепосредственномузапуску Turbo Linker. Длятого, чтобыузнать, какуюопцию надописать при TCC,можно воспользоватьсяследующейтаблицей.


Таблица3.1: Имена файловрабочей библиотеки


Модельпамяти Объектныйфайл Библиотечныйфайл ОпцияTCC
Tiny c0t.obj cs.lib -mt
Small c0s.obj cs.lib -ms
Medium c0m.obj cm.lib -mm
Compact c0c.obj cl.lib -mc
Large c0l.obj cl.lib -ml
Huge c0h.obj ch.lib -mh

15



Раздел 4: Вызовфункций С изязыка ассемблера


4.1 Вызов С иС++ из ассемблера


До сих поррассматривалось,как разделитьпеременныемежду С или C++и ассемблером,а также каквызывать внешниеассемблерныефункции изпрограмм, написанныхна С или C++. Теперьподойдем кэтому с другойстороны, т.е. квызову функцийС или C++ из ассемблерногомодуля - этотакже возможно,но требуетбольшего внимания.

Если функцияне обладаетпараметрами,процесс достаточнопрост. Надообъявить функциюС или C++ в директивеEXTRN и воспользоватьсяинструкциейcall:

CODESEG

EXTRN _cfuntion:proc

......

call _cfunction

Здесь предполагается,что функция,названная_cfunction, существуетв программе,подлежащейкомпоновкевместе с ассемблерныммодулем.

Если функциитребуютсяпараметры,процесс усложняется.Простые параметры,такие как символыи целые числачасто передаютсянепосредственнов стек. Сложныепеременные,такие как строки,структуры имножества,передаютсяпосредствомссылок, т.е. поадресу. Крометого, многиефункции возвращаютрезультат вспецифичныерегистры. Привызове функцийС или C++ из языкаассемблеранадо самимпозаботитьсяо подобныхнюансах.

Сперва рассмотримпростейшийслучай вызовафункции с однимцелочисленнымпараметром:

void showscore( int thescore)

{

printf(“\nThe score is: %d\n, thescore);

}

Чтобы вызватьфункцию showscore изассемблерногомодуля, передаваязначение переменнойтипа слова вкачестве thescore,можно написать:

CODESEG

EXTRN showscore: proc

mov ах, 76 ;Присвоениеscore регистру

push ах ;Передача параметрав стек

call _showscore ; Вызовфункции С

pop ах ;Фиксация стека


Прежде всего,значение scoreприсваиваетсяах (любой другойрегистр точнотак же подойдетдля этого), азатем выталкиваетсяв стек передвызовом showscore. Послевозврата изфункции слововыталкиваетсяиз стека. Этонеобходимопотому, что вС и C++ вызывающаяпрограммаудаляет параметрыиз стека. Еслиимеется несколькопараметров,может быть,будет лучшепросто прибавитьих общее числобайтов к sp. Например,чтобы вызватьфункцию, котораяоперируетчетырьмя 16-битовымипараметрами,можно воспользоватьсяследующимикомандами:

push [vl] ; Выталкиваниечетырех переменных

push [v2] ; (не показанных)в стек

push [v3]

push [v4]

call _aCfunction ; Вызовфункции С

add sp, 8 ; Удалениепараметров

Выталкиваниенесколькихпараметровосуществляетсяв порядке, обратномтому, в какомони объявляютсяфункции С илиC++. Исходя изпредположения,что функцияfillstring определенакак

void fillstring( unsigned char far *thestring, intstringLength, char fillchar );

для вызоваэтой функциииз языка ассемблераи заполнениястроковойпеременнойпробеламитребуютсянесколькошагов. Сперваассемблерныймодуль объявляетсястроковойпеременной:

DATASEG

PUBLIC _astring

_astring db 80 dup (0)

Затем этотже модуль объявляетfillstring в директивеEXTRN и вызываетфункцию длязаполнениястрочной переменнойпробелами:

CODESEG

EXTRN _fillstring: ргос

xor ah, ah ; Обнулениест. половиныах

mov al,’ ‘ ;Присвоениепробела а1

push ах ;Проталкиваниепар-ра fillchar

mov ах, 79 ;Присвоениедлины строкиах

push ах ;Проталкиваниепар-ра дл. строки

push ds ;Проталкиваниесег-та адресастроки

mov ах, offset _astring ;Присвоениесмещения адресаах

push ах ;Проталкиваниесмещ. адресастроки

call _fillstring ; Вызовфункции

add sp, 8 ; Удалениепараметровиз стека

Каждый изпараметров- заполняющийсимвол, длинастроки и 32-битовыйуказательстроковойпеременной-проталкиваетсяв стек в порядке,обратномперечисленномув определениифункции. Применительнок указателю- сегмент адресапроталкиваетсяперед смещением.После обращенияк _fillstring к указателюстека sp добавляются8 байт, удаляяпараметры изстека.

Несмотряна то что в этомпримере функция_fillstring в действительностинаписана наязыке ассемблера,вызовы функцийС и C++ ничем неотличаются.


4.2 Локальныепеременные


В дополнениек переменным,объявленнымв сегментеданных либообщим с программойС и С++, можноиспользоватьлокальныепеременные,помещенныев стек создаваемыхассемблерныхмодулей. Локальныепеременныесуществуюттолько во времявыполненияфункции. Стековаячасть создаетсядля переменныхпри запускефункции, а затемочищается передее завершением.Таким образом,другие функциимогут использоватьэти же областипамяти длясвоих собственныхлокальныхпеременных,снижая общийобъем памяти,требуемой длявсей программы.Например:

void countup()

{

int i;

for (i = 0; i

printer("%d", i);

}

Целая переменнаяi помещаетсяв памяти в стекпри запускефункции countup исуществуеттолько до техпор пока выполняетсяэта функция.В ассемблерноммодуле можнопроделать тожесамое с помощьюдирективыLOCAL. Вот примерзаконченнойфункции:

PROС _cfunction NEAR

LOCAL i:Word=stacksize

push bp

mov bp, sp

sub sp, stacksize

mov [i], 0

@@10:

inc [ i ]

;

;--Код, использующийлокальнуюпеременную[i]

;

cmp [i], 10

jne @@10

mov sp, bp

pop bp

ret ; Возвратв точку вызова

ENDP _cfunction

ДирективаLOCAL в этом примереподготавливаетпеременнуюi типа Word (слово).Указание = stacksizeназначает общеечисло байтов,занимаемоевсеми локальнымипеременными- в данном случае2 байта. Это значениевычитаетсяиз sp после подготовкиадресациипеременныхв стек. Затем,для ссылки наi, используютсятакие инструкции,как mov, inc и crop. Благодарядирективе LOCALссылки типа[i] переводятсяследующимобразом:

mov [bp-2], 0

inc [bp-2]

и т.д. ПрииспользованииLOCAL нет необходимостивычислятьотрицательныесмещения относительноbp, чтобы определитьместоположениепеременныхв стеке, -достаточновоспользоватьсяименами переменных.

Посколькуbp не изменяетсяво время выполненияэтой функции,можно восстановитьsp по средствомbp, удаляя областьлокальнойпеременнойиз стека, илиприбавитьstacksize к sp с помощьюкоманды

add sp, stacksize

Подходятоба метода, новосстановлениеsp посредствомbp - быстрее. Можнотакже объявитьнескольколокальныхпеременныхоператорами,подобнымиследующему:

LOCAL i:Word; j:Word; c:Byte=stacksize

Теперь, послевычитанияstacksize из указателястека длярезервированияобласти в стеке,можно использоватьтри локальныепеременные- i, j и с. (Необходимовсегда делатьLOCAL, что упрощаетадресациюлокальныхпеременных,это не создаетобласть дляпеременныхв памяти.)


4.3 Передачааргументов


СовместноеиспользованиеC++ и ассемблерастановитсяболее сложным,когда к функциямдобавляютсяаргументы.Приходитсяочень внимательнопрограммировать,обращаясь кфункциям изразличныхмодулей и выбираяаргументы изстека. Но следующаядиректива беретна себя задачусама произвестиломку имен изанести их встек:

ARG c_offset:byte, k_pffset:word

Аргументы,перечисленныетаким образом,не являютсяобъектамиданных; онисмещаются встеке относительнорегистра bр.ИспользованиеARG подобным образомпозволяетассемблерувычислитьсмещения вместонас - но мы должныспецифицироватьправильныетипы данных.Символьнаяпеременнаяв C++ являетсябайтом в ассемблере,целая в C++ - эквивалентомассемблерногослова и т.д.

Обратныйпроцесс - передачааргументовиз языка ассемблерав C++ - требует инойтактики:

proc _asmfunction C c_arg:byte, k_arg:word

“C” послеимени функцииуказывает, чтоаргументыприводятсядля языка С(т.е. они выталкиваютсяв стек в порядкесправа налево).Остальноетакже, как идля директивыARG.

В результатеTurbo Assembler автоматическипишет инструкциидля сохранения,инициализациии восстановленияbp. При использованииэтой альтернативнойметодики неприходитсяпроводитьточные операциипо выталкиваниюbp. За исключениемэтого отличия,в остальномпроцесс программированияостается темже самым.


20



Раздел 5:Курсовая программа


5.1 Постановказадачи


В курсовойтребовалосьнаписать программу,вычисляющуюзначение многочленаn-ой степени повектору размерностиn коэффициентовмногочленаи по некой переменнойх, задаваемыепользователем.Необходимобыло реализоватьмногомодульнуюсвязь (два модуля:на С и на ассемблере),а также выразитьнаглядно связьассемблерас языком С.


5.2 Блоксхемапрограммы


Программареализовываласьпо следующейблоксхеме:


Очевидно,что была реализованасвязь в обестороны.

5.3 Модуль наС++


/*Это частьна С++, есть ещена ассемблере*/

#include


extern "C" void vvod();/*ассемблернаяпроцедура*/

extern "C" void mnogochlen(int *vec);/*функцияв С*/

int m;

extern int *vect;/*векторкоэффициентов,объявленный*/

/*внешнейпеременной*/

main()

{

cout

cin>>m;

vvod();/*Вызовассемблернойпроцедуры*/

return 0;

}


extern "C"/*Началофункции на С*/

{

void mnogochlen(int *vect)

{

int i,g,x;

int fact,summa;

summa=0;

cout

cin>>x;

for(i=m;i>=0;i--)/*Вычислениеответа*/

{

fact=1;

for(g=0;g

{

fact=fact*x;

}

summa=summa+vect[i]*fact;

}

cout

cout

}

}


5.4 Модуль наассемблере


MODEL small

dataseg

so db 'введитевектор коэффициентов','$'

extrn _m:word, _vec:word; Внешниеаргументы

m2 dw 0

codeseg

extrn _mnogochlen:proc; функцияиз С++

public _vvod; местнаяпроцедура

proc _vvod near

push bp

mov bp,sp

push di;Сохранениезначений этихрегистров

push si;необходимо,т.к. они используютсяС++

MOV ah,09h ;началоввода вектораперестановок

MOV dx,offset so

INT 21h

mov si,0

MOV cx,[_m]

l1: MOV ah,02h

MOV dl,'>'

INT 21h

MOV di,0

m1 : MOV ah,08h

INT 21h

CMP al,13

JE exit

CMP al,'9'

JA m1

CMP al,'0'

JB m1

MOV ah,02h

MOV dl,al

INT 21h

SUB al,'0'

XOR ah,ah

MOV m2,ax

MOV ax,di

MOV bx,10

MUL bx

ADD ax,m2

MOV di,ax

JMP m1

exit: MOV [_vec[si]],di

ADD si,2;Данныетипа слово,прибавляем2

MOV di,0

mov ah,02h

mov dl,' '

int 21h

mov dl,13

int 21h

mov dl,10

int 21h

LOOP l1

mov sp,bp

pop di;извлечениесохраненныхрегистров

pop si;передвозвратом вС++

MOV ax,offset [_vec]

PUSH ax

call _mnogochlen; Вызовфункции С++

ADD sp,4;Удалениеэлементов изстека

POP bp;адресвозврата

ret

endp _vvod

end


5.5 Анализпроведеннойработы


При работев многомодульномрежиме главныетрудностивозникают виспользованиирегистров.Из-за несохранениясистемныхрегистров,используемыхС++, программаможет просто“повиснуть”.Также следовалосделат выбор- какой модульсделать главным.Но практикапоказывает,что следуетпроизводитьвызов языковнизкого уровняиз высокого,а не наоборот.В общем, всетрудности былипреодоленыи программапоявилась всвет.

23



Введение


В идеальноммире программированиякомпиляторыс языков высокогоуровня должныгенерироватьсамый быстрый,самый компактныйи наилучшиймашинный коддля любой программы.Если бы этобыло невозможно,то программированиемного бы потерялоот этого, и навернякане писался быэтот курсовик.Но это невозможно.Несмотря намножествоусовершенствованийпри разработкекомпиляторов,ни один языквысокого уровняпока не в состояниипродублироватькраткий, быстрыйи изящный код,написанныйопытным специалистомпо ассемблеру.

В чем же дело?А в том, чтокомпиляторыобобщают решаемыеими задачи. ВC++ существуеттолько одинспособ написанияцикла FOR. В то жевремя с помощьюассемблераэтот цикл можноорганизоватьс помощью ассемблераэтот цикл можноорганизоватьдесяткамиспособов. Чтобыкомпиляторвыбирал идеальноподходящиев каждой конкретнойситуации методыреализацииалгоритма ипри этом учитываяих влияние наостальные частипрограммы - ондолжен обладатьинтеллектомгения, вкусомхудожника иинтуициейпредсказателя.Сегодняшниекомпиляторыс языков высокогоуровня достаточносообразительны,но не до такойстепени.

Среди всехсуществующихкомпиляторовС наиболееприблизилсяк идеалу С++.Порождаемыйим машинныйкод работаетдостаточнобыстро, занимаетна диске немногоместа и в большинствеслучаев можетиспользоватьсябез каких-либомодификаций.Однако несмотряна все достоинстваС++, все равноостается местодля улучшений,благодаря чемудаже небольшиеучастки программы,переписанныена ассемблере,могут значительноповысить скоростьработы программыи уменьшитьразмер исполняемогофайла. Крометого, добавивассемблер кС++, можно облегчитьдоступ к регистрамаппаратныхсредств и решениедругих задачнизкого уровня,таких как записьсимволовнепосредственнов видеопамять.

Во многихслучаях единственныйспособ дляприбавленияпрограммескорости - немногодополнитьсовершенный“С”, используяодин из двухметодов:

  • Использованиевстроенныхоператоров(операторовInline)

  • Использованиевнешних функций

ОператорыInline вставляютязык ассемблеранепосредственнов исходнуюпрограмму наС и С++. Эта методикабыстрая и простая,но имеет нескольконедостатков,которые пояснятьсяниже. Внешниефункции, хотяих и трудноиспользовать,чем операторыInline, имеют топреимущество,что позволяютнаиболее полноиспользоватьвсе возможностиTurbo Assembler.

4



Списокиспользованнойлитературы


1. Том Сван“Освоение TurboAssembler”, Диалектика,Киев, 1996 г.


2. БерезинБ.И., БерезинС.Б. “Начальныйкурс С и С++”, ДиалогМИФИ, Москва,1996 г.


3. Лекции КомлевойНины Викторовныпо предмету“Языки программированияи методы трансляции”

24



СОДЕРЖАНИЕ


Введение 3
Раздел1: Регистры ипараметры 5
1.1 Использованиерегистров 5
1.2 АссемблерныеоператорыInline 5
1.3 Размещениеданных и операторовв программе 6
Раздел2: Особенностиданных 7
2.1 Разделениеданных 7
2.2 Объявлениеассемблерныхданных 7
2.3 Разделениекода 8
Раздел3: Вызов ассемблерныхфункций из С 9
3.1 Символыподчеркивания 9
3.2 Использованиедальних данных 9
3.3 Вызовассемблерныхфункций из С 10
3.4 Ассемблированиеи компоновкавнешних модулей 11
Раздел4: Вызов функцийС из ассемблера 15
4.1 ВызовС и С++ из ассемблера 15
4.2 Локальныепеременные 17
4.3 Передачааргументов 18
Раздел5: Курсоваяпрограмма 20
5.1 Постановказадачи 20
5.2 Блоксхемапрограммы 20
5.3 Модульна С++ 20
5.4 Модульна ассемблере 21
5.5 Анализпроведеннойработы 23
Списокиспользованнойлитературы 24

МОСКОВСКИЙ ГОСУДАРСТВЕННЫЙУНИВЕРСИТЕТЭКОНОМИКИ,СТАТИСТИКИ И ИНФОРМАТИКИ


КАФЕДРА МОЭВМ


КУРСОВАЯРАБОТА


на тему :“Взаимосвязьязыков С иассемблера”


Студент:Аплемах А.В.

Группа: ДП-202


Руководительпроекта:

Комлева Н.В.


Защищена “___” Мая 1997 г.


Москва 1997г.