Обучающие курсы:

Обучение профессии "Разработчик C#" + стажировка в Mail.ru
Обучение профессии "Разработчик Python" + трудоустройство
Обучение профессии "Веб-разработчик" + стажировка в Mail.ru


Главная страница
Библиотека (скачать книги)
Скачать софт
Введение в программирование
Стандарты для C++
Уроки по C#
Уроки по Python
HTML
Веб-дизайн
Ассемблер в среде Windows
ActiveX
Javascript
Общее о Линукс
Линукс - подробно
Линукс - новое
Delphi
Паскаль для начинающих
Турбопаскаль
Новости
Партнеры
Наши предложения
Архив новостей





Для демонстрации примеров используются только 32-разрядные вычисления. Это означает, что, например, при адресации регистров процессора будет использоваться мнемоника ЕАХ, ЕВХ. ЕСХ И Т. Д. Все операции с памятью предполагают использование 32-разрядных операндов. Мы не будем ссылаться на сегментные регистры cs, DS И ES, Т. К. В 32-разрядной модели вычислений отсутствует само понятие сегментных регистров. Более того, попытка использовать эти регистры для каких-либо операций сразу приведет к аварийному завершению программы.

Прежде чем начать программировать на ассемблере, необходимо определиться с инструментами разработки программ. Для демонстрации примеров программного кода, написанного на ассемблере, использован пакет MASM 6.15 фирмы Microsoft.

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

В этой и во всех последующих главах в примерах программного кода будет использоваться упрощенный синтаксис для обозначения логических сегментов кода и данных. Так, например, сегмент данных будет обозначаться как .data, а сегмент кода — .code.

Вначале рассмотрим принципы построения подпрограмм на языке ассемблера. Этот материал является очень важным, и мы будем опираться на него при рассмотрении других тем книги.

В дальнейшем термины "подпрограмма", "процедура" и "функция" будут использоваться как синонимы. Функция — это процедура, которая возвращает значение, поэтому, думается, не должно возникать путаницы в применении этих понятий.

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

Кратко напомним определение процедуры и способ ее вызова. Для обозначения начала и конца процедуры в языке ассемблера используются директивы ргос и endp. Последней командой процедуры обычно является команда ret, а для вызова процедуры используется команда call. Фрагмент кода, приведенный в листинге 2.1, демонстрирует в общем виде принципы использования Процедуры myProc.

Листинг 2.1. Вызов процедуры myProc из программы на ассемблере
.data
.code /
start:
call myProc
myProc proc
ret
myProc endp
end start

В процедуру обычно передаются один или несколько параметров или аргументов. Для 32-разрядных приложений любой параметр представлен двойным СЛОвОМ DWORD.

Общепринято, что процедура возвращает значение в регистре ЕАХ (напомним, что мы рассматриваем только 32-разрядные приложения).
Параметры в вызывающую процедуру могут передаваться одним из нескольких способов. Наиболее распространенным из них является передача параметров через стек. Обычно такой способ используется для интерфейса программ на языке ассемблера с программами на языке высокого уровня. Далее показан фрагмент программного кода (листинг 2.2), демонстрирующий этот метод передачи параметров.
Листинг 2.2. Передача параметров в процедуру через стек
data
SUM DD 0
11 DD 32
12 DD -43
code
start:
push DWORD PTR II
push DWORD PTR 12
call SumTwo
mov SUM, EAX
SumTwo proc
push EBP
mov EBP, ESP
mov EAX, DWORD PTR [EBP+12
add EAX, DWORD PTR [EBP+8]
pop EBP
ret
SumTwo endp
end start

Перед вызовом процедуры SumTwo передаваемые параметры (два целых числа II и 12) помещаются в стек, и размещается в стеке по адресу [ЕВР+12], а 1 2 — по адресу [ЁВР+8] . Следует сказать, что стек увеличивается вниз, т. е. от верхних адресов памяти к нижним. Поэтому первый параметр, который помещается в стек, имеет больший адрес, чем второй.


 
 
 

Библиотека программиста. 2009.
Администратор: admin@programmer-lib.ru