Преобразование 64-битного числа в строку

Автор: xrnd | Рубрика: Исходники | 27-12-2010

В части 22 учебного курса рассматривались способы преобразования чисел в строку. Однако, вывести в десятичном виде число больше 32 бит не так просто. Сложность в том, что требуется делить число на 10, а число слишком большое и в регистры DX:AX не помещается.

К счастью, в программе на ассемблере можно делить числа любой разрядности 🙂 Правда, одной командой DIV тут не обойтись. Придётся реализовать специальный алгоритм.

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

Рекурсивные процедуры

Автор: xrnd | Рубрика: Исходники | 21-10-2010

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

Что такое факториал? Это математическая функция, определённая для целых неотрицательных чисел. 🙂 Обозначается восклицательным знаком (n! — факториал числа n). Факториал натурального числа равен произведению всех натуральных чисел до него. Факториал нуля равен 1. Подробнее можете прочесть здесь.

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

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

Процедуры с переменным количеством параметров

Автор: xrnd | Рубрика: Исходники | 29-09-2010

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

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

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

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

Учебный курс. Часть 23. Ввод чисел с консоли

Автор: xrnd | Рубрика: Исходники, Учебный курс | 07-08-2010

В прошлой части мы научились преобразовывать числа в строку и выводить на консоль. А в этой займёмся обратной задачей — вводом чисел с консоли и преобразованием строки в число. Поскольку ввод в двоичном и восьмеричном виде используется редко, я рассмотрю только примеры ввода чисел в десятичном виде (со знаком и без знака) и в шестнадцатеричном.

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

Ввод строки с консоли

Для ввода строки можно использовать функцию MS-DOS 0Ah. Функция позволяет ввести строку длиной от 1 до 254 символов. При вызове в DX передаётся адрес буфера, первый байт которого должен содержать максимально допустимую длину строки. Длина считается вместе с символом конца строки CR (0dh). В результате работы функции во второй байт буфера записывается фактическая длина введённой строки (не считая символа CR). Начиная с третьего байта в буфер записываются символы строки. Подробнее о работе функции можно узнать в раритетном справочнике по DOS 🙂

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

32-битное умножение

Автор: xrnd | Рубрика: Исходники | 31-07-2010

Эта статья посвящена разбору примера умножения 32-битных чисел на 16-битном процессоре. Как вы наверно знаете, команда MUL в 16-битном режиме позволяет умножать максимум 16-битные значения, поэтому для умножения 32-битных чисел необходим специальный алгоритм.

Умножать большие числа приходится по частям, а затем складывать эти промежуточные результаты. Чтобы всё стало понятно я напишу небольшую формулу. Допустим, нам надо умножить два 32-битных числа a и b. В результате должно получиться 64-битное число c. Обозначим как a1 — младшее слово a, a2 — старшее слово a, b1 — младшее слово b, b2 — старшее слово b. Тогда получается:

a = (a2<<16) + a1

b = (b2<<16) + b1

Символы <<16 обозначают сдвиг влево на 16 бит. По сути это то же самое, что умножить на 65536.

c = a x b = ((a2<<16) + a1) x ((b2<<16) + b2) =
= (a1 x b1) + ((a2 x b1)<<16) + ((a1 x b2)<<16) + ((a2 x b2)<<32)

Алгоритм очень напоминает способ умножения в столбик. Графически можно изобразить следующим образом:

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

Учебный курс. Часть 22. Вывод чисел на консоль

Автор: xrnd | Рубрика: Исходники, Учебный курс | 31-07-2010

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

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

Для начала рассмотрим две полезные процедуры, которые будут использоваться в дальнейшем. Чтобы постоянно не обращаться в коде в функции DOS 09h, удобно написать маленькую процедуру для вывода строки:

;Процедура вывода строки на консоль
; DI - адрес строки
print_str:
    push ax
    mov ah,9                ;Функция DOS 09h - вывод строки
    xchg dx,di              ;Обмен значениями DX и DI
    int 21h                 ;Обращение к функции DOS
    xchg dx,di              ;Обмен значениями DX и DI
    pop ax
    ret

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