Учебный курс. Часть 12. Преобразование типов

Автор: xrnd | Рубрика: Учебный курс | 18-04-2010

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

Преобразовать больший тип в меньший гораздо проще — достаточно отбросить старшую часть. Но такое преобразование небезопасно и может привести к ошибке. Например, если значение слова без знака больше 255, то сделав из него байт, вы получите некорректное значение. Будьте внимательны, если вы используете такие трюки в своей программе.

Преобразование типов без знака

Преобразование типов выполняется по-разному для чисел со знаком и без. Для преобразования чисел без знака необходимо просто заполнить все старшие биты нулями. Например, так будет выглядеть преобразование байта в слово:

Читать полностью »

Учебный курс. Часть 11. Умножение и деление

Автор: 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

Читать полностью »

Учебный курс. Часть 10. Сложение и вычитание с переносом

Автор: xrnd | Рубрика: Учебный курс | 30-03-2010

В системе команд процессоров x86 имеются специальные команды сложения и вычитания с учётом флага переноса (CF). Для сложения с учётом переноса предназначена команда ADC, а для вычитания — SBB. В общем, эти команды работают почти также, как ADD и SUB, единственное отличие в том, что к младшему разряду первого операнда прибавляется или вычитается дополнительно значение флага CF.

Зачем нужны такие команды? Они позволяют выполнять сложение и вычитание многобайтных целых чисел, длина которых больше, чем разрядность регистров процессора (в нашем случае 16 бит). Принцип программирования таких операций очень прост — длинные числа складываются (вычитаются) по частям. Младшие разряды складываются(вычитаются) с помощью обычных команд ADD и SUB, а затем последовательно складываются(вычитаются) более старшие части с помощью команд ADC и SBB. Так как эти команды учитывают перенос из старшего разряда, то мы можем быть уверены, что ни один бит не потеряется 🙂 Этот способ похож на сложение(вычитание) десятичных чисел в столбик.

Читать полностью »

Учебный курс. Часть 9. Сложение и вычитание

Автор: 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       ;Ошибка: разный размер операндов.

Читать полностью »

Учебный курс. Часть 8. Числа со знаком и без

Автор: xrnd | Рубрика: Учебный курс | 27-03-2010

Числа со знаком и дополнительный код

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

Для представления чисел со знаком используется специальное кодирование. Старший бит в этом случае обозначает знак числа. Если знаковый бит равен нулю, то число положительное, иначе — отрицательное. Понятно, что положительное число со знаком будет выглядеть точно так же, как и число без знака.

С отрицательными числами чуть сложнее. Исторически для представления отрицательных чисел в компьютерах использовались разные виды кодирования: прямой, обратный и дополнительный код. В настоящее время наиболее часто используется дополнительный код, в том числе и в процессорах x86.

Читать полностью »

Учебный курс. Часть 7. Системы счисления

Автор: xrnd | Рубрика: Учебный курс | 19-03-2010

Эта статья по большей части для совсем начинающих. Если вы хорошо разбираетесь в системах счисления, можете обратить внимание лишь на особенности синтаксиса ассемблера FASM в конце статьи.

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

Читать полностью »

Учебный курс. Часть 6. Hello, world!

Автор: 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!$'

Читать полностью »

Учебный курс. Часть 5. Директивы объявления данных

Автор: 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

Читать полностью »

Учебный курс. Часть 4. Регистры процессора 8086

Автор: xrnd | Рубрика: Учебный курс | 13-03-2010

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

Все внутренние регистры процессора Intel 8086 являются 16-битными:

Всего процессор содержит 12 программно-доступных регистров, а также регистр флагов (FLAGS) и указатель команд (IP).

Читать полностью »

Учебный курс. Часть 3. Turbo Debugger

Автор: xrnd | Рубрика: Учебный курс | 12-03-2010

Прежде всего необходимо запустить отладчик. Для этого удобно использовать bat-файл. Создайте в каталоге программы текстовый файл, назовите его, например, «debug.bat». В него надо записать всего одну строку:

1
C:\TD\td.exe <файл_программы>.com

После запуска этого bat-файла вы увидите примерно такое окно:

Читать полностью »