Автор: xrnd | Рубрика: Учебный курс | 14-04-2011
До этой части учебного курса мы создавали только COM-программы, в которых один и тот же сегмент использовался для кода, данных и стека. Однако, для дальнейшего изложения необходимо подробнее разобраться с сегментной адресацией.
Формирование адреса в реальном режиме
Основная идея сегментной адресации в том, что адрес состоит из двух частей — сегментной и смещения. Обычно их записывают через двоеточие (например 0100:0500). Линейный адрес любой ячейки памяти получается в результате сложения смещения и сегментной части, сдвинутой на 4 бита влево.

Начало сегмента всегда выровнено на границу параграфа (адрес кратен 16 байтам). Максимальный размер сегмента равен 216 = 64 КБайта. А всего можно адресовать 220 = 1 МБайт памяти. Конечно, сейчас такой объем памяти кажется смешным, но раньше это было очень много 🙂
Читать полностью »
Автор: xrnd | Рубрика: Учебный курс | 06-12-2010
Наверно, вы заметили, что довольно неудобно обращаться к параметрам и локальным переменным, указывая смещения относительно регистра BP. Такой способ подходит только для совсем простых и маленьких процедур. Поэтому в таких ассемблерах, как TASM и MASM, существуют специальные директивы, позволяющие создавать процедуры быстро и удобно. В FASM таких директив нет! Но они и не нужны — то же самое можно сделать с помощью макросов.
Для начала, нам потребуется заголовочный файл с макросами. Стандартный пакет FASM для Windows, к сожалению, не включает в себя макросы для 16-битных процедур. Однако такие макросы можно найти на официальном форуме FASM или скачать здесь: PROC16.INC. Это переделанная версия файла PROC32.INC с точно таким же синтаксисом.
Заголовочный файл необходимо будет включить в программу с помощью директивы include:
Базовый синтаксис объявления процедуры
Для создания процедуры используется следующий синтаксис:
proc <имя_процедуры>[,][<список_параметров>]
...
ret
endp |
proc <имя_процедуры>[,][<список_параметров>]
...
ret
endp
Читать полностью »
Автор: xrnd | Рубрика: Учебный курс | 16-11-2010
Отличительной особенность FASM является очень гибкая и мощная поддержка макросов. В этой статье мы рассмотрим лишь основы создания макросов, так как эта тема довольно обширна и рассказать всё в одной статье не получится.
Что же такое макросы? Макросы — это шаблоны для генерации кода. Один раз создав макрос, мы можем использовать его во многих местах в коде программы. Макросы делают процесс программирования на ассемблере более приятным и простым, а код программы получается понятнее. Макросы позволяют расширять синтаксис ассемблера и даже добавлять собственные «команды», которых нет в процессоре.
Обработкой макросов занимается препроцессор FASM. Преобразование исходного кода в исполняемый код FASM выполняет в два этапа. Первый этап — препроцессирование, а второй — собственно ассемблирование или компиляция. На первом этапе происходит вычисление всех числовых выражений, вместо констант и названий меток подставляются их фактические значения, вместо макросов подставляется сгенерированный код. На втором этапе все данные и машинные команды преобразуются в соответствующие байты, и в результате получается исполняемый файл требуемого формата.
Синтаксис создания макроса
Для создания макроса используется директива macro. Эта директива имеет следующий синтаксис:
macro <название_макроса> [<список_параметров>]
{
<тело_макроса>
} |
macro <название_макроса> [<список_параметров>]
{
<тело_макроса>
}
Читать полностью »
Автор: xrnd | Рубрика: Учебный курс | 03-11-2010
Не сомневаюсь, что объявлять метки вы уже научились 🙂 Однако, синтаксис FASM не ограничивается объявлением простых меток. В этой части мы рассмотрим дополнительную директиву для создания меток, а также научимся использовать локальные и анонимные метки.
В синтаксисе FASM существует 3 основных способа объявления меток:
1. Имя метки, после которого ставится двоеточие. Это самый простой способ. Обычно так объявляются метки в коде. (Подробнее об этом способе читайте в части 13 учебного курса)
exit_app:
mov ax,4C00h
int 21h |
exit_app:
mov ax,4C00h
int 21h
2. Использование директив объявления данных. Имя переменной является по сути той же меткой. Отличие от первого способа в том, что дополнительно с именем метки связывается размер переменной. (Подробнее читайте в части 5 учебного курса)
x db 5
y dw 34,1200,?
z rd 1 |
x db 5
y dw 34,1200,?
z rd 1
Читать полностью »
Автор: xrnd | Рубрика: Учебный курс | 22-04-2010
Режимы адресации — это различные способы указания местоположения операндов. До этой части в учебном курсе использовались только простые режимы адресации: операнды чаще всего находились в регистрах или в переменных в памяти. Но в процессоре Intel 8086 существуют также более сложные режимы, которые позволяют организовать работу с массивами, структурами, локальными переменными и указателями. В этой части я расскажу о всех возможных режимах адресации и приведу примеры их использования.
1. Неявная адресация
Местоположение операнда фиксировано и определяется кодом операции. Примеры:
Читать полностью »
Автор: xrnd | Рубрика: Учебный курс | 28-03-2010
Теперь мы уже знаем, как представляются числа в компьютере, и можем перейти к изучению команд процессора. Начнём с самых простых арифметических операций: сложения и вычитания.
Сложение
Для сложения двух чисел предназначена команда ADD. Она работает как с числами со знаком, так и с числами без знака (это особенность дополнительного кода).
Операнды должны иметь одинаковый размер (нельзя складывать 16- и 8-битное значение). Результат помещается на место первого операнда. В общем, эти правила справедливы для большинства команд.
После выполнения команды изменяются флаги, по которым можно определить характеристики результата:
- Флаг CF устанавливается, если при сложении произошёл перенос из старшего разряда. Для беззнаковых чисел это будет означать, что произошло переполнение и результат получился некорректным.
- Флаг OF обозначает переполнение для чисел со знаком.
- Флаг SF равен знаковому биту результата (естественно, для чисел со знаком, а для беззнаковых он равен старшему биту и особо смысла не имеет).
- Флаг ZF устанавливается, если результат равен 0.
- Флаг PF — признак чётности, равен 1, если результат содержит нечётное число единиц.
Примеры:
add ax,5 ;AX = AX + 5
add dx,cx ;DX = DX + CX
add dx,cl ;Ошибка: разный размер операндов. |
add ax,5 ;AX = AX + 5
add dx,cx ;DX = DX + CX
add dx,cl ;Ошибка: разный размер операндов.
Читать полностью »
Автор: xrnd | Рубрика: Учебный курс | 27-03-2010
Числа со знаком и дополнительный код
Помимо того, что процессор работает с двоичными числами, эти числа могут быть со знаком или без знака. Если число без знака, то оно просто представляет собой результат перевода десятичного числа в двоичный вид. Все биты в таком числе являются информационными и оно может принимать только неотрицательные значения.
Для представления чисел со знаком используется специальное кодирование. Старший бит в этом случае обозначает знак числа. Если знаковый бит равен нулю, то число положительное, иначе — отрицательное. Понятно, что положительное число со знаком будет выглядеть точно так же, как и число без знака.
С отрицательными числами чуть сложнее. Исторически для представления отрицательных чисел в компьютерах использовались разные виды кодирования: прямой, обратный и дополнительный код. В настоящее время наиболее часто используется дополнительный код, в том числе и в процессорах x86.
Читать полностью »
Автор: xrnd | Рубрика: Учебный курс | 19-03-2010
Эта статья по большей части для совсем начинающих. Если вы хорошо разбираетесь в системах счисления, можете обратить внимание лишь на особенности синтаксиса ассемблера FASM в конце статьи.
На самом деле процессор работает только с двоичными числами, состоящими из единиц и нулей 🙂 В виде двоичных чисел хранятся и обрабатываются все данные и команды любой программы. Однако, двоичная запись чисел слишком громоздка и неудобна для человека, поэтому в программах на ассемблере используются и другие системы счисления: десятичная, шестнадцатеричная и восьмеричная.
Читать полностью »
Автор: xrnd | Рубрика: Учебный курс | 14-03-2010
Практически любая программа кроме машинных команд содержит также какие-то данные. Например, числа, текстовые строчки, идентификаторы, различные ресурсы и т.д. Данные могут быть как константами, не меняющими своё значение во время выполнения программы, так и переменными, в которых хранятся всякие промежуточные результаты.
Прежде всего нужно научиться объявлять данные в программе. Для этого в ассемблере существуют директивы объявления данных.
Размер
(в байтах) |
Объявление |
Резервирование |
1 |
db |
rb |
2 |
dw
du |
rw |
4 |
dd |
rd |
6 |
dp
df |
rp
rf |
8 |
dq |
rq |
10 |
dt |
rt |
N |
file |
|
Читать полностью »