Здравствуйте, уважаемые друзья! Продолжаем изучать нашу рубрику, на очереди тема умножения и деления в Assembler. Разберемся со всеми тонкостями этих операций, конечно же, на практическом примере.
Основные команды
- Для умножения в Assembler используют команду
mul
- Для деления в Assembler используют команду
div
Правила умножения в Assembler
Итак, как мы уже сказали, при умножении и делении в Assembler есть некоторые тонкости, о которых дальше и пойдет речь. Тонкости эти состоят в том, что от того, какой размерности регистр мы делим или умножаем многое зависит. Вот примеры:
- Если аргументом команды mul является 1-байтовый регистр (например
mul bl
), то значение этого регистра bl умножится на значение регистра al, а результат запишется в регистр ax, и так будет всегда, независимо от того, какой 1-байтовый регистр мы возьмем.
bl*al = ax
- Если аргументом является регистр из 2 байт(например
mul bx
), то значение в регистре bx умножится на значение, хранящееся в регистре ax, а результат умножения запишется в регистр eax.
bx*ax = eax
- Если аргументом является регистр из 4 байт(например
mul ebx
), то значение в регистре ebx умножится на значение, хранящееся в регистре eax, а результат умножения запишется в 2 регистра: edx и eax.
ebx*eax = edx:eax
Правила деления в Assembler
Почти аналогично реализуется и деление, вот примеры:
- Если аргументом команды div является 1-байтовый регистр (например
div bl
), то значение регистра ax поделится на значение регистра bl, результат от деления запишется в регистр al, а остаток запишется в регистр ah.
ax/bl = al, ah
- Если аргументом является регистр из 2 байт(например
div bx
), то процессор поделит число, старшие биты которого хранит регистр dx, а младшие ax на значение, хранящееся в регистре bx. Результат от деления запишется в регистр ax, а остаток запишется в регистр dx.
(dx,ax)/bx = ax, dx
- Если же аргументом является регистр из 4 байт(например
div ebx
), то процессор аналогично предыдущему варианту поделит число, старшие биты которого хранит регистр edx, а младшие eax на значение, хранящееся в регистре ebx. Результат от деления запишется в регистр eax, а остаток запишется в регистр edx.
(edx,eax)/ebx = eax, edx
Программа
Далее перейдем к примеру: он не должен вызвать у вас каких либо затруднений, если вы читали наши предыдущие статьи, особенно важна статья про вывод на экран, советую вам с ней ознакомиться. Ну а мы начнем:
.386 .model flat,stdcall option casemap:none include ..\INCLUDE\kernel32.inc include ..\INCLUDE\user32.inc includelib ..\LIB\kernel32.lib includelib ..\LIB\user32.lib BSIZE equ 15 .data ifmt db "%d", 0 ;строка формата stdout dd ? cWritten dd ? CRLF WORD ? .data? buf db BSIZE dup(?) ;буфер
Стандартное начало, в котором мы подключаем нужные нам библиотеки и объявляем переменные для вывода чисел на экран. Единственное о чем нужно сказать: новый для нас раздел .data? Знак вопроса говорит о том, что память будет выделяться на этапе компилирования и не будет выделяться в самом исполняемом файле с расширением .exe (представьте если бы буфер был большего размера) . Такое объявление — грамотное с точки зрения программирования.
.code start: invoke GetStdHandle, -11 mov stdout,eax mov CRLF, 0d0ah ;-------------------------деление mov eax, 99 mov edx, 0 mov ebx, 3 div ebx invoke wsprintf, ADDR buf, ADDR ifmt, eax invoke WriteConsoleA, stdout, ADDR buf, BSIZE, ADDR cWritten, 0 invoke WriteConsoleA, stdout, ADDR CRLF, 2, ADDR cWritten,0
В разделе кода, уже по традиции, считываем дескриптор экрана для вывода и задаем значения для перевода каретки. Затем помещаем в регистры соответствующие значения и выполняем деление регистра ebx, как оно реализуется описано чуть выше. Думаю, тут понятно, что мы просто делим число 99 на 3, что получилось в итоге выводим на экран консоли.
;-------------------------умножение mov bx, 4 mov ax, 3 mul bx invoke wsprintf, ADDR buf, ADDR ifmt, eax invoke WriteConsoleA, stdout, ADDR buf, BSIZE, ADDR cWritten, 0 invoke ExitProcess,0 end start
Думаю, что здесь тоже все понятно и без комментариев. Как производиться умножение в Assembler вы тоже можете прочитать чуть выше, ну и результат выводим на экран.
Просмотр консоли
Этот код я поместил в файл seventh.asm, сам файл поместил в папку BIN (она появляется при установке MASM32). Далее открыл консоль, как и всегда, с помощью команды cd
перешел в эту папку и прописал amake.bat seventh
. Скомпилировалось, затем запускаю исполняемый файл и в консоли получаются такие числа:
Как видите, мы правильно посчитали эти операции.
На этом сегодня все! Надеюсь вы научились выполнять деление и умножение на Assembler.
Скачать исходники
Отличная статья, спасибо!)
al * rm8 = ax
ax * rm16 = dx:ax <- ЭТО!!! т.к. в 286'ом 32 битных регистров небыло
eax * rm32 = edx:eax
Пожалуй, вы правы. Но мы работаем с директивой .386, вы увидите это, если посмотрите пример.