Автор: xrnd | Рубрика: Учебный курс | 18-04-2010
Очень часто в программах приходится выполнять действия с числами разного размера, например складывать или умножать байт и слово. Напрямую процессор не умеет выполнять такие операции, поэтому в этом случае необходимо выполнять преобразование типов. Сложность представляет преобразование меньших типов в большие (байта в слово, слова в двойное слово и т.д.)
Преобразовать больший тип в меньший гораздо проще — достаточно отбросить старшую часть. Но такое преобразование небезопасно и может привести к ошибке. Например, если значение слова без знака больше 255, то сделав из него байт, вы получите некорректное значение. Будьте внимательны, если вы используете такие трюки в своей программе.
Преобразование типов без знака
Преобразование типов выполняется по-разному для чисел со знаком и без. Для преобразования чисел без знака необходимо просто заполнить все старшие биты нулями. Например, так будет выглядеть преобразование байта в слово:
Читать полностью »
Автор: xrnd | Рубрика: Учебный курс | 01-04-2010
Умножение и деление выполняются по-разному для чисел со знаком и без, поэтому в системе команд процессора x86 есть отдельные команды умножения и деления для чисел со знаком и для чисел без знака.
Умножение чисел без знака
Для умножения чисел без знака предназначена команда MUL. У этой команды только один операнд — второй множитель, который должен находиться в регистре или в памяти. Местоположение первого множителя и результата задаётся неявно и зависит от размера операнда:
Размер операнда |
Множитель |
Результат |
Байт |
AL |
AX |
Слово |
AX |
DX:AX |
Отличие умножения от сложения и вычитания в том, что разрядность результата получается в 2 раза больше, чем разрядность сомножителей. Также и в десятичной системе — например, умножая двухзначное число на двухзначное, мы можем получить в результате максимум четырёхзначное. Запись «DX:AX» означает, что старшее слово результата будет находиться в DX, а младшее — в AX. Примеры:
mul bl ;AX = AL * BL
mul ax ;DX:AX = AX * AX |
mul bl ;AX = AL * BL
mul ax ;DX:AX = AX * AX
Читать полностью »
Автор: xrnd | Рубрика: Учебный курс | 30-03-2010
В системе команд процессоров x86 имеются специальные команды сложения и вычитания с учётом флага переноса (CF). Для сложения с учётом переноса предназначена команда ADC, а для вычитания — SBB. В общем, эти команды работают почти также, как ADD и SUB, единственное отличие в том, что к младшему разряду первого операнда прибавляется или вычитается дополнительно значение флага CF.
Зачем нужны такие команды? Они позволяют выполнять сложение и вычитание многобайтных целых чисел, длина которых больше, чем разрядность регистров процессора (в нашем случае 16 бит). Принцип программирования таких операций очень прост — длинные числа складываются (вычитаются) по частям. Младшие разряды складываются(вычитаются) с помощью обычных команд ADD и SUB, а затем последовательно складываются(вычитаются) более старшие части с помощью команд ADC и SBB. Так как эти команды учитывают перенос из старшего разряда, то мы можем быть уверены, что ни один бит не потеряется 🙂 Этот способ похож на сложение(вычитание) десятичных чисел в столбик.
Читать полностью »
Автор: 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 | Рубрика: Учебный курс | 16-03-2010
В этой части наконец-то напишем долгожданный «Hello, world!». Теперь почти всё должно быть понятно. Для начала необходимо с помощью директивы db объявить строку, содержащую сообщение «Hello, word!». Лучше сделать это в конце программы, за последней командой, иначе процессор может принять строку за код и попытаться её выполнить.
Для вывода строки используется системная функция DOS. Чтобы напечатать строку, нужно поместить 9 в регистр AH, а в регистр DX поместить адрес строки, которая должна заканчиваться символом ‘$’. Обращение к функциям DOS осуществляется с помощью команды int 21h. Вот код программы:
1
2
3
4
5
6
7
8
9
10
11
| use16 ;Генерировать 16-битный код
org 100h ;Программа начинается с адреса 100h
mov dx,hello ;В DX адрес строки.
mov ah,9 ;Номер функции DOS.
int 21h ;Обращение к функции DOS.
mov ax,4C00h ;\
int 21h ;/ Завершение программы
;-------------------------------------------------------
hello db 'Hello, world!$' |
use16 ;Генерировать 16-битный код
org 100h ;Программа начинается с адреса 100h
mov dx,hello ;В DX адрес строки.
mov ah,9 ;Номер функции DOS.
int 21h ;Обращение к функции DOS.
mov ax,4C00h ;\
int 21h ;/ Завершение программы
;-------------------------------------------------------
hello db 'Hello, world!$'
Читать полностью »
Автор: 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 |
|
Читать полностью »
Автор: xrnd | Рубрика: Учебный курс | 13-03-2010
Для того, чтобы писать программы на ассемблере, нам необходимо знать, какие регистры процессора существуют и как их можно использовать. Все процессоры архитектуры x86 (даже многоядерные, большие и сложные) являются дальними потомками древнего Intel 8086 и совместимы с его архитектурой. Это значит, что программы на ассемблере 8086 будут работать и на всех современных процессорах x86.
Все внутренние регистры процессора Intel 8086 являются 16-битными:
Всего процессор содержит 12 программно-доступных регистров, а также регистр флагов (FLAGS) и указатель команд (IP).
Читать полностью »
Автор: xrnd | Рубрика: Учебный курс | 12-03-2010
Прежде всего необходимо запустить отладчик. Для этого удобно использовать bat-файл. Создайте в каталоге программы текстовый файл, назовите его, например, «debug.bat». В него надо записать всего одну строку:
1
| C:\TD\td.exe <файл_программы>.com |
C:\TD\td.exe <файл_программы>.com
После запуска этого bat-файла вы увидите примерно такое окно:
Читать полностью »