Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

ПРИЛОЖЕНИЕ С. Интерфейс языка СИ с языком Ассемблер.

Программирование со смешением языков-это процесс создания программ, использующих два или более исходных языка. Данное средство позволит вам использовать уникальные возможности языков BASIC, C, FORTRAN, Pascal и Macro Assembler (MASM) фирмы Microsoft. Любой из этих языков (в их последних версиях) может вызывать любой другой.

Фактически, все процедуры каждой из данных языковых библиотек доступны для программ со смешением языков. Например, смешанное программирование поможет вам эффективно использовать Макро Ассемблер (MASM). Вы можете быстро разработать большинство ваших программ с помощью Microsoft C или FORTRAN, а затем использовать MASM для тех нескольких процедур, которые часто выполняются и должны работать с большой скоростью.

Смешанное программирование, кроме того, облегчает переход от одного языка к другому. Например, вы можете иметь большую программу на языке FORTRAN, а затем конвертировать ее в СИ.

Вы можете заменить ваши процедуры на языке FORTRAN один к одному на соответствующие СИ-функции. СИ-код будет сгенерирован, как только каждая функция будет написана.

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

Подробно смешанное программирование для всех остальных языков описано в документе "Microsoft Mixed-Language Programming Guide". Данное руководство содержит описание смешанного программирования для языков Microsoft FORTRAN(версия 4.0 и выше),Microsoft Macro Assembler (Версия 5.0 и выше), Microsoft Pascal (Версия 3.3 и выше), Microsoft C(версия 5.0 и выше).

Данное же приложение в основном касается методов программирования необходимых для написания процедур на Ассемблере, пригодных для использования в СИ-программах. Подробности об интерфейсах между другими языками высокого уровня смотрите в документе "Microsoft Mixed-Language Programming Guide" ("Руководство по программированию со смешением языков фирмы Microsoft").

Определения.

Терминологические соглашения, используемые в данном приложении совпадают с соглашиниями, описанными в руководстве пользователя для каждого языка фирмы Microsoft. Однако, следующие термины используются в особом смысле:

Термин      Определения

Процедура   Любая функция, подпрограмма, процедура, которая может
            быть вызвана из другого языка. Данное понятие аналогично
            процедуре в языке Ассемблер; однако сам термин
            "процедура" используется в разных случаях, его не
            следует смешивать с ключевым словом языка Pascal
            "procedure".
Параметр    Часть данных, передаваемая непосредственно между двумя
            процедурами. (Внешними данными пользуются все процедуры,
            но про них нельзя сказать, что они "передаются"). Хотя
            повсюду термин "аргумент" используется попеременно с тер-
            мином "параметр", в данном приложении термин "аргумент"
            используется для обозначения определенных значений или
            выражений, предлагаемых для параметров.
Интерфейс   Метод, обеспечивающий эффективную связь между различными
            форматами. В высокоуровневых языках интерфейс часто ус-
            танавливается некоторыми видами формального объявления.
Формальный  Формальный параметр-это параметр, описанный в интерфей-
параметр    сном операторе или объявлении. Язык СИ использует описа-
              ния типа параметра, а не формальные параметры.

С.1. Написание ассемблерной процедуры.

Высокоуровневые языки фирмы Microsoft используют для процедурных вызовов приблизительно один и тот же интерфейс. Данный раздел описывает интерфейс, позволяющий вам вызывать ассемблерную процедуру с помощью тех же самых методов, которые вы применяли для кода, сгенерированного компиляторами фирмы Microsoft. Процедуры, написанные с помощью данных методов, могут вызываться рекурсивно и могут быть эффективно использоваться со средством Stack Trace многооконного отладчика Code View фирмы Microsoft. Стандартный метод получения интерфейса с языком Ассемблер состоит из следующих шагов:

1.Создание процедуры.

2.Ввод процедуры.

3.Размещение локальных данных (необязательно).

4.Резервирование значений регистров.

5.Параметры доступа.

6.Возвращение значения (необязательно).

7.Выход из процедуры.

Каждый из следующих шагов описывается в Разделах С.1.1-С.1.7.

С.1.1. Написание процедуры.

Компановщик не сможет объединить ассемблерную процедуру с вызывающей процедурой, если используются несовместимые сегменты, либо сама процедура описана неправильно. Могут оказаться полезными следующие положения:

-Если вы имеете Macro Assembler версии 5.0, в начале исходного файла используйте директиву .MODEL. Данная директива автоматически генерирует соответствующий тип возвращаемого значения ("near" для малой или компактной модели, "far"-в противном случае). Если у вас более ранняя версия ассемблера, опишите процедуру с атрибутом "far" (либо "near", если вызывающая программа работает в малой или компактной модели Quick-C).

-Если у вас Microsoft Macro Assembler версии 5.0 или выше, для объявления кодового сегмента используйте упрощенную директиву .CODE и директиву .DATA для объявления сегмента данных. (Если у вас нет объявлений данных, достаточно только кодового сегмента). Если вы используете более раннюю версию ассемблера, рассмотрите директивы SEGMENT, GROUP и ASSUME в Разделе С.4 "Сегментная модель фирмы Microsoft".

-Метка процедуры должна быть объявлена, как "public" с помощью директивы PUBLIC. Данное объявление делает процедуру доступной для вызовов из других модулей. Кроме того, любые данные, которые вы хотите сделать доступными для других модулей, должны быть объявлены, как PUBLIC.

-Глобальные данные или процедуры, к которым осуществляется доступ из вашей процедуры, должны быть объявлены, как EXTRN. Наиболее безопасный путь использования EXTRN-это помещение директивы вне сегментоного определения (тем не менее, "ближние" д

С.1.2. Вход в процедуру.

Процедура начинается с двух инструкций:

push    bp
mov     bp,sp

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

Последовательность инструкций, приведенная выше, сначала сохраняет значение BP, поскольку оно потребуется вызывающей процедуре, как только закончится текущая процедура. Затем в регистр BP заносится значение SP, чтобы иметь значение указателя стека перед входом в процедуру.

С.1.3. Размещение локальных данных (необязательно).

Ассемблерная процедура использует для размещения локальных данных те же самые средства, что и высокоуровневые языки. Чтобы установить размеры памяти для размещения локальных данных, просто уменьшите содержимое регистра SP в третьей инструкции процедуры. (Для гарантии корректного выполнения вам следует всегда увеличивать или уменьшать содержимое SP на четное число). Уменьшение содержимого регистра SP резервирует пространство стека для локальных данных. Данная память должна быть в конце процедуры восстановлена.

В следующих инструкциях, "space"-это общий размер байтов локальных данных. Доступ к локальным переменным осуществляется посредством фиксированных отрицательных смещений BP.

push    bp
mov     bp,sp
        sub     sp,space

-Пример:
push     bp
mov      bp,sp
sub      sp,4
.
.
.
mov     WORD PTR [bp-2],0
mov     WORD PTR [bp-4],0
Приведенный выше пример использует две локальные переменные, каждая из которых имеет размер 2 байта. SP уменьшается на четыре, поскольку для локальных данных требуется четыре байта. Позже, каждая из данных переменных инициализируется 0. Данные переменные никогда не объявляются формально какой-либо директивой ассемблера; программист должен отслеживать их самостоятельно

Локальные переменные называются также динамическими, стековыми или автоматическими переменные.

С.1.4. Резервирование значений регистров.

Ассемблерные процедуры, вызываемые из любого высокоуровнего языка фирмы Microsoft должны зарезервировать значение регистров SI, DI, SS и DS ( в дополнение к регистру BP, который уже был сохранен). То есть, следует сохранить содержимое тех регистров, которые программа может изменить. Если программа не изменяет содержимое какого-либо регистра, этот регистр нет нужды запоминать.

Те регистры, которые вы запомнили перед входом в процедуру, следует затем восстановить перед выходом из процедуры (как объясняется в Разделе С.1.7 "Выход из процедуры").

Рекомендуемый метод (используемый всеми высокоуровневыми языками) состоит в том, чтобы запоминать регистры после того, как установлен указатель на запись активации и размещены локальные данные (если они существуют). В следующем фрагменте программы регистры DI и SI (в данном порядке) должны быть восстановлены перед выходом из процедуры.

push     bp    ;Запоминание старого указателя записи активации
mov      bp,sp ;Установка текущего указателя записи активации
sub      sp,4  ;Размещение памяти для локальных данных
push     si    ;Сохранение SI и DI
puih     di
.
.
.

С.1.5. Доступ к параметрам.

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

Старшие    |параметр       |
адреса     |параметр       |
           |   .           |
           |   .           |
           |   .           |
           |               |
           |параметр       |
           |адрес возврата |
           | запомненное   |   здесь хранится указатель на запись
           | BP            |   активации (BP)
           |память для ло- |
           |кальных данных |
           |запомненный SI |
           |запомненный    |   SP указывает на последний элемент,
           | DI            |   помещенный в стек.
Младшие
адреса

Рисунок С.1. Запись активации.

Запись активации процедуры устанавливается следующей последовательностью действий:

1.Вызывающая программа помещает каждый параметр в стек, после чего регистр SP указывает на последний размещенный параметр.

2.Вызывающая программа инициирует инструкцию CALL, которая устанавливает адрес возврата (место в вызывающей программе, на которое возвращается управление после окончания работы процедуры) и помещает его в стек. Данный адрес может быть либо дыа байта длинной (для "ближних" вызовов), либо четыре байта длинной (для "дальних" вызовов). Теперь регистр SP указывает на данный адрес.

3.Первая инструкция вызванной процедуры сохраняет старое значение BP (push bp). Регистр SP теперь указывает на сохраненную копию BP. 4.Используйте регистр BP для захвата текущего значения регистра SP с помощью инструкции mov bp, sp. Теперь BP указывает на старое значение BP.

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

В основном, смещение (относительно BP) для параметра X равно: 2 + размер адреса возврата

+ общий размер параметров между X и BP.

Например, предположим, что процедура FAR получает один параметр, двухбайтовый адрес. Смещение для этого параметра будет равно: смещение аргумента = 2 + размер адреса возврата

= 2 + 4

= 6

Аргумент может в таком случае быть загружен в регистр BP с помощью следующей инструкции:

    mov bx,[bp+6]

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

    Arg1 EQU [bp+6]

После этого в любой инструкции на данный параметр можно ссылаться по идентификатору Arg1. Используйте это средство в качестве полезного дополнения.


Примечание:

Высокоуровневые языки фирмы Microsoft всегда размещают адреса сегментов перед адресами смещений. Поэтому, если в стек опускаются аргументы больше 2-х байтов, старшие слова всегда опускаются перед младшим словом.


С.1.6. Возврат значений (необязательно).

Высокоуровневые языки Microsoft для получения возвращаемых значений пользуются аналогичными соглашениями. Данные соглашения совпадают, если возвращаемый тип данных не является сложным (например массивом или структурой) и имеет длину не более четырех байтов. Это включает в себя все "ближнии" и "дальние" адреса (то есть все указатели и все параметры, передаваемые по ссылке).

Размер данных          Возвращаемое значение

1 байт                 AL
2 байта                AX
4 байта                старшая часть (или адрес сегмента) в DX
                       младшая часть (или адрес смещения) в AX
Если возвращаемое значение больше четырех байтов, процедура вызываемая из языка СИ, должна отвести память для возвращаемого значения, а затем поместить этот адрес в DX:AX. Удобным способом распределения памяти для возвращаемого значения является простое объявление его в сегменте данных.

С.1.8. Выход из процедуры.

При завершении процедуры должны быть выполнены следующие шаги: 1.Если какие-либо из регистров SS, DS, SI и DI были сохранены, перед выходом из процедуры они должны быть извлечены из стека в порядке, обратном их размещению.

2.Если локальные данные размещены в начале процедуры, регистр SP должен быть восстановлен с помощью инструкции mov sp, bp.

3.Восстановите регистр BP с помощью pop bp. Данный шаг всегда необходим.

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

-Примеры:

pop     bp
ret

Приведенный выше пример показывает простейшую последовательность выхода. Никакие регистры не были зарезервированы, не были размещены локальные данные, и использованы соглашения о связях языка СИ.

pop     di     ;Восстановление зарезервированных регистров
pop     si
mov     sp, bp ;Освобождение пространства, занятого локальными дан-
                ными
pop     bp     ;Восстановление старого указателя на запись активации
ret     6      ;Выход и восстановление 6 байтов, занятых аргументами
В данном примере показана последовательность выхода для процедуры, которая предварительно зарезервировала значения регистров SI и DI, разместила локальные данные и использовала соглашения о связях не относящиеся к языку СИ. Поэтому, процедура должна использовать инструкцию ret 6, чтобы восстановить 6 байтов, занятых параметрами в стеке.

С.2. Вызов процедур на языке Ассемблер из языка СИ.

Программа на языке СИ может вызвать процедуру на языке Ассемблер, находящуюся в другом модуле, как и при вызове СИ-функции. В дополнение к шагам, описанным в Разделе С.1 "Написание процедуры на языке Ассемблер", могут оказаться полезными следующие правила:

1.Описывайте процедуры, вызываемые из СИ-программ с ключевым словом far, если СИ-модуль был скомпилирован в большой, сверхбольшой или средней модели памяти, и с ключевым словом near, если СИ-модуль был скомпилирован в малой или компактной модели. Ключевые слова far или near отменяют любые стандартные назначения. Если вы используете директиву .MODEL, имеющуюся в Micro soft Macro Assembler версии 5.0, объявление модели памяти для процедуры делается явно.

2.Обзор соглашений о связях языка СИ. По соглашениям языка СИ параметры опускаются в стек в том порядке, в каком они находятся в исходном коде. Например, вызов функции СИ calc(a,b); опускает b в стек раньше a. В противоположность остальным высокоуровневым языкам, в соглашениях о связях языка СИ положено, чтобы вызывающая процедура всегда восстанавливала стэк непосредственно после возвращения управления из вызываемой программы. Соглашения о связях языка СИ делают возможным вызов переменным числом параметров. (Поскольку первый параметр всегда опускается в стек последним, он имеет относительно указателя на запись активации один и тот же адрес. Независимо от количества переданных числом параметров применяются следующие этапы:

а)Возврат производится посредством простой инструкцией ret. Не восстанавливайте стек посредством инструкции ret size, поскольку вызывающая СИ-процедура сама восстановит стек, как только ей будет передано управление.

б)Параметры помещаются в стек в порядке, обратном тому, как они появлялись в исходном коде на языке СИ. Первый параметр будет находиться по младшим адресам памяти (поскольку-это последний помещаемый в стэк параметр, то есть стэк растет вниз).

с)Стандартно, параметры языка СИ передаются значением, исключая массивы, передаваемые по адресной ссылке.

3.Обзор соглашений о наименованиях языка СИ.

Наличие подчеркивания перед любым именем в языке СИ делает его глобальным. В языке СИ распознаются только первые восемь символов, поэтому не делайте имена, используемые СИ, длинной более восьми символов. Кроме того, если вы будете выполнять компановку с опцией /NOIGNORECASE, помните, что язык СИ чувствителен к буквенным регистрам, и не преобразуйте имена к верхнему регистру.

В следующем примере программа на языке СИ вызывает ассемблерную процедуру, которая вычисляет А*2**B, где А и В-первый и второй параметры, соответственно. Вычисления выполняются путем сдвига влево разрядов в А В раз.

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

extern int power2(int, int);
main()
{
     printf("3 times 2 to the power of 5 is %d\n", power2(3,5));
}
Чтобы понять, как пишется ассемблерная процедура, рассмотрите рисунок С.2, на котором показана схема размещения параметров в стеке.
Старшие адреса         | B | Arg<-2              |    BP+6
(С каждым опусканием   | A | Arg<-1              |    BP+4
аргумента или каждым   |     Адрес возврата      |    BP+2
вызовом стек растет    |     Зарезервированный   |    BP
вниз)                  |      BP                 |
Младшие адреса

                   Рисунок С.2. Запись активации СИ.
Адрес возврата имеет в длину байта, предполагая, что СИ-модуль был скомпилирован в малой или компактной модели. Если же СИ-модуль компилируется в большой, сверхбольшой или средней модели, то адреса Arg
.MODEL SMALL
.CODE
        PUBLIC _power2
_power2 PROC
        push     bp     ;Входная последовательность-сохранение старо-
                         го BP


        mov      bp,sp  ;Установка указателя на запись активации

        mov      ax,[bp+4]   ;Загрузка Arg 1 в AX
        mov      cx,[bp+6]   ;Загрузка Arg 2 в CX
        shl      ax,cl       ;AX = AX*(2 в степени CX)
                             ;Возвращаемое значение остается в AX
        pop      bp          ;Выходная последовательность-востанов-
                              ление старого BP
        ret                  ;Выход
_power2 ENDP
        END
Приведенный выше пример предполагает, что СИ-модуль компилируется в малой модели памяти. Смещение параметра и директива .MODEL изменятся для других моделей памяти.

Обратите внимание, что инструкция ret используется без переменной size, поскольку вызывающая программа после возвращения из процедуры сама выравнивает стек.

С.3. Вызов языка СИ из языка Ассемблер.

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

       СИ-код                 Код на Ассемблере
(начало программы на СИ)     |
main(){                      |
       asub();               |
}                            | PROC asub
                             |   .
(C termination)              |   .
                             |   .
                             |       call ctest
ctest(){                     |   .
   .                         |   .
   .                         |
                             |       ret
   .                         | ENDP asub
}                            |

                 Рисунок С.3. Вызов СИ из Ассемблера.
Для вызова высокоуровневых языков из языка Ассемблер вам следует соблюдать следующие правила:

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

-При длинных параметрах, всегда опускайте в стэк первыми сегмент, либо старшую часть параметра, независимо от соглашений о связях. -Выполняйте вызов. Вызов должен быть "дальним", если только высокоуровневая процедура не относится к малой модели памяти. -Если процедура использовала соглашения о связях языка СИ, то непосредственно сразу после вызова очистите стек от параметров с помощью инструкции: add sp, size, где size-это общий размер в байтах всех параметров, опущенных в стек.

С.4. Сегментная модель фирмы Microsoft.

Если вы применяете простейшие сегментные директивы, вам не потребуется знать имена, назначенные каждому сегменту. Однако, версии Macro Assembler предшествующие версии 5.0 не поддерживают данные директивы. В старших версиях ассемблера вам следует использовать директивы SEGMENT, GROUP, ASSUME, ENDS, эквивалентные упрощенным сегментным директивам.

В Таблице С.1 показаны стандартные имена сегментов, создаваемые каждой директивой. Использование данных сегментов гарантирует совместимость с языками фирмы Microsoft и поможет вам получить доступ к внешним именам.

За таблицей следует описание трех шагов иллюстрирующих реальные объявления, и пример программы.

                                                 Таблица С.1.
      Стандартные сегменты и типы для стандартных моделей памяти.

Модель    Директива Имя       Выравни-  Способ объ Класс   Группа
                              вание     единения


Малая     .CODE     _TEXT     WORD      PUBLIC     'CODE'
          .DATA     _DATA     WORD      PUBLIC     'DATA'  DGROUP
          .CONST    CONST     WORD      PUBLIC     'CONST' DGROUP
          .DATA?    _BSS      WORD      PUBLIC     'BSS'   DGROUP
          .STACK    STACK     PARA      STACK      'STACK' DGROUP

Средняя   .CODE     name_TEXT WORD      PUBLIC     'CODE'
          .DATA     _DATA     WORD      PUBLIC     'DATA'  DGROUP
          .CONST    CONST     WORD      PUBLIC     'CONST' DGROUP
          .DATA?    _BSS      WORD      PUBLIC     'BSS'   DGROUP
          .STACK    STACK     PARA      STACK      'STACK' DGROUP

Компакт-  .CODE     _TEXT     WORD      PUBLIC     'CODE'
ная       .FARDATA  FAR_DATA  PARA      Private    'FAR_DATA'
          .FARDATA? FAR_BSS   PARA      Private    'FAR_BSS'
          .DATA     _DATA     WORD      PUBLIC     'DATA'  DGROUP
          .CONST    CONST     WORD      PUBLIC     'CONST' DGROUP
          .DATA?    _BSS      WORD      PUBLIC     'BSS'   DGROUP
          .STACK    STACK     PARA      STACK      'STACK' DGROUP

Большая   .CODE     name_TEXT WORD      PUBLIC     'CODE'
          .FARDATA  FAR_DATA  PARA      Private    'FAR_DATA'
          .FARDATA? FAR_BSS   PARA      Private    'FAR_BSS'
          .DATA     _DATA     WORD      PUBLIC     'DATA'  DGROUP
          .CONST    CONST     WORD      PUBLIC     'CONST' DGROUP
          .DATA?    _BSS      WORD      PUBLIC     'BSS'   DGROUP
          .STACK    STACK     PARA      STACK      'STACK' DGROUP

Директивы Таблицы С.1 относятся к следующим типам сегментов:
Директива              Описание сегмента


.CODE                  Сегмент, содержащий весь код модуля.
.DATA                  Проинициализированные данные.
.DATA?                 Неинициализированные данные. Компиляторы фир-
                       мы Microsoft хранят неинициализированные дан-
                       ные отдельно, поскольку такие данные можно раз
                       местить более эффективно, чем проинициализиро-
                       ванные данные.
.FARDATA и .FARDATA?   Данные, которые не будут объединяться с соот-
                       ветствующими сегментами других модулей. Сег-
                       мент размещенных здесь данных, тем не менее,
                       всегда может быть определен с помощью операто-
                       ра ассемблера SEG.
.CONST                 Постоянные данные. Компиляторы фирмы Microsoft
                       используют данный сегмент для элементов, та-
                       ких, как строковые константы и константы с
                       плавающей точкой.
.STACK                 Стек. Обычно, данный сегмент объявляется в
                       главном модуле и не должен быть переопределен.
Для создания реальных директив с помощью Таблицы С.1 используйте следующие шаги:

1.В определении сегмента следует задать имя, тип выравнивания, тип объединения, класс. Таким образом, сегмент кода для малой модели памяти должен быть объявлен следующим образом:

    _TEXT SEGMENT WORD PUBLIC 'CODE'
Если тип объединения "private", просто не используйте никакого типа объединения.

2.Если у вас есть сегменты в DGROUP, поместите их в DGROUP с помощью директивы GROUP, как в примере:

    GROUP DGROUP _DATA _BSS

3.Директивы ASSUME и ENDS используйте, как обычно. Помните, что при вводе, регистры DS и SS, оба указывают на DGROUP.

Следующий пример показывает программу "СИ-Ассемблер" из Раздела С.3, но без упрощенных сегментных директив из версии 5.0 Макроассемблера фирмы Microsoft.

_TEXT   SEGMENT WORD PUBLIC 'CODE'
        ASSUME  cs: TEXT
        PUBLIC   Power2
_Power2 PROC
        push    bp     ;Входная последовательность-сохранения регис-
                        тра BP.
        mov     bp,sp  ;Установка записи активации.

        mov     ax,[bp+4]  ;Загрузка Arg1 в AX.
        mov     cx,[bp+6]  ;Загрузка Arg2 в CX.
        shl     ax,cl      ;AX = AX+(2 в степени CX).
                           ;Значение возврата остается в AX.
        pop     bp   ;Выходная последовательность-восстановление ре-
                      гистра BP.
        ret          ;Выход.
_Power2 ENDP
_TEXT   ENDS
       END

Оставить комментарий

Комментарий:
можно использовать BB-коды
Максимальная длина комментария - 4000 символов.
 
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог