Вход/Регистрация
Ассемблер для процессоров Intel Pentium
вернуться

Магда Юрий

Шрифт:

.model small, с ; эта директива указывается до объявления

; сегментов

.stack 100h ; размер стека 256 байт

.data ; начало сегмента данных

. . .

: данные

. . .

.code ; здесь начинается сегмент программ

main:

. . .

: команды ассемблера

. . .

end main

end

Здесь оператор end main указывает на точку входа main в главную процедуру. Оператор end закрывает последний сегмент и обозначает конец исходного текста программы. В 16-разрядных приложениях MS-DOS можно инициализировать сегментные регистры так, чтобы они указывали на требуемый логический сегмент данных. Листинг 4.1 демонстрирует это.


Листинг 4.1. Пример адресации сегментов в программе MS-DOS

.model large

.data

s1 DB «TEST STRINGS»

.code

mov AX. @data

mov DS. AX

lea DX. s1

mov AH. 9h

int 21h

mov ax. 4c00h

int 21h

end

Здесь на экран дисплея выводится строка si. При помощи следующих команд в сегментный регистр DS помещается адрес сегмента данных, указанного директивой .data:

mov AX. @data

mov DS. AX

Затем строка s1 , адресуемая через регистры DS:DX, выводится на экран с использованием прерывания 9h функции 21h MS-DOS. Попробуйте закомментировать проанализированные две строки кода и посмотреть на результат работы программы.

Для 32-разрядных приложений шаблон исходного текста выглядит иначе:

.model flat

.stack

.data

: данные

.code

main:

. . .

: команды ассемблера

. . .

end main

end

Основное отличие от предыдущего примера – другая модель памяти (flat), предполагающая 32-разрядную линейную адресацию с атрибутом near.

Как видно из примера, «классический» шаблон 32-разрядного приложения содержит область данных (определяемую директивой .data), область стека (директива .stack) и область программного кода (директива .code). Может случиться так, что 32-разрядному приложению на ассемблере потребуется несколько отдельных сегментов данных и/или кода. В этом случае разработчик может создать их с помощью директивы SEGMENT. Директива SEGMENT определяет логический сегмент и может быть описана следующим образом:

имя SEGMENT список атрибутов

. . .

имя ENDS

Замечу, что директива SEGMENT может применяться с любой моделью памяти, не только flat. При использовании директивы SEGMENT потребуется указать компилятору на то, что все сегментные регистры устанавливаются в соответствии с моделью памяти flat. Это можно сделать при помощи директивы ASSUME:

ASSUME CS: FLAT, DS:FLAT, SS:FLAT, ES:FLAT, FS:ERROR, GS:ERROR

Регистры FS и GS программами не используются, поэтому для них указывается атрибут ERROR.

Сейчас мы рассмотрим программный код 32-разрядной процедуры на ассемблере (она называется segex), в которой используются два логических сегмента данных. Процедура выполняет копирование строки sre, находящейся в сегменте данных datai, в область памяти dst в сегменте данных data2 и содержит один логический сегмент программного кода (code segment).

Успокою читателей, незнакомых с принципами работы процедур (они рассмотрены далее в книге): в данном случае нас будет интересовать код внутри процедуры segex (команды, находящиеся между директивами segex proc и segex endp). Исходный текст программного кода процедуры segex представлен в листинге 4.2.


Листинг 4.2. Использование двух логических сегментов данных в 32-разрядной процедуре

.586

.model flat

option casemap:none

data1 segment

src DB «Test STRING To Copy»

len EQU $-src

data1 ends

data2 segment public

dst DB len+1 DUPC + ')

data2 ends

code segment

_seg_ex proc

assume CS: FLAT,DS:FLAT, SS:FLAT, ES:FLAT, FS:ERR0R, GS:ERR0R

mov ESI, offset datai

mov EDI, offset data2

cld

mov CX, len

rep movsb

mov EAX, offset data2

ret

_seg_ex endp

code ends

end

При использовании модели flat доступ к данным осуществляется по 32-разрядному смещению, поэтому смысл показанных ниже команд, загружающих адреса логических сегментов (а заодно и адреса строк src и dst) в регистры ESI и EDI, думаю, понятен:

mov ESI, offset data1

mov EDI, offset data2

Группа следующих команд выполняет копирование строки src в dst, при этом регистр СХ содержит количество копируемых байтов:

cld

mov CX. len

rep movsb

В регистре ЕАХ возвращается адрес строки-приемника dst. Обращаю внимание читателей на то, что никакой инициализации сегментных регистров не требуется, поскольку это делается при помощи директивы . model flat. Еще один важный момент: программа, использующая модель flat, выполняется в одном физическом сегменте, хотя логических сегментов может быть несколько, как в нашем случае.

Работоспособность процедуры легко проверить, вызвав ее из программы на Visual C++ .NET (нужно только включить объектный файл процедуры в проект приложения). Исходный текст приложения приведен в листинге 4.3.

  • Читать дальше
  • 1
  • ...
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: