Умножение в ассемблере - IT Справочник
Llscompany.ru

IT Справочник
11 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

Умножение в ассемблере

Команда MUL

Что такое JavaScript

Если вы интересуетесь программированием вообще, и сайтостроением в частности, то вы наверняка слышали слово JavaScript. И, если вы до сих пор не узнали толком, что же это такое, то пришло время сделать это. Подробнее.

Инструкция MUL в Ассемблере выполняет умножение без знака. Понять работу команды MUL несколько сложнее, чем это было для команд, рассмотренных ранее. Но, надеюсь, что я помогу вам в этом разобраться.

Итак, синтаксис команды MUL такой:

Выглядит всё очень просто. Однако эта простота обманчива.

Прежде чем разобраться в подробностях работы этой инструкции, давайте посмотрим, что может быть ЧИСЛОМ.

ЧИСЛОМ может быть один из следующих:

  • Область памяти (MEM)
  • Регистр общего назначения (REG)

Эта команда не работает с сегментными регистрами, а также не работает непосредственно с числами. То есть вот так

MUL 200 ; неправильно

А теперь алгоритм работы команды MUL:

  • Если ЧИСЛО — это БАЙТ, то AX = AL * ЧИСЛО
  • Если ЧИСЛО — это СЛОВО, то (DX AX) = AX * ЧИСЛО

Вот такая немного сложноватая команда. Хотя сложно это с непривычки. Сейчас мы разберём всё “по косточкам” и всё станет ясно.

Для начала обратите внимание, что инструкция MUL работает либо с регистром АХ, либо с регистром AL. То есть перед выполнением этой команды нам надо записать в регистр АХ или в регистр AL значение, которое будет участвовать в умножении. Сделать это можно, например, с помощью уже известной нам команды MOV.

Затем мы выполняем умножение, и получаем результат либо в регистр АХ (если ЧИСЛО — это байт), либо в пару регистров DX и AX (если ЧИСЛО — это слово). Причём в последнем случае в регистре DX будет старшее слово, а в регистре AX — младшее.

А теперь, чтобы совсем всё стало понятно, разберём пару примеров — с байтом и словом.

Пример умножения в Ассемблере

Итак, например, нам надо умножить 150 на 250. Тогда мы делаем так:

Обратите внимание, что нам приходится два раза использовать команду MOV, так как команда MUL не работает непосредственно с числами, а только с регистрами общего назначения или с памятью.

После выполнения этого кода в регистре АХ будет результат умножения чисел 150 и 250, то есть число 37500 (927С в шестнадцатеричной системе).

Теперь попробуем умножить 10000 на 5000.

В результате мы получили довольно большое число, которое, конечно, не поместится в слово. Поэтому для результата используются два регистра — DX и AX. В нашем примере в регистре DX, будет число 762 (02FA — в шестнадцатеричной системе), а в регистре АХ — число 61568 (F080 — в шестнадцатеричной системе). А если рассматривать их как одно число (двойное слово), где в старшем слове 762, а в младшем — 61568, то это и будет 50000000 (2FAF080 — в шестнадцатеричной системе).

Если не верите — может перевести всё это в двоичное число и проверить.

После выполнения команды MUL состояния флагов ZF, SF, PF, AF не определены и могут быть любыми.

А если старшая секция результата (регистр AH при умножении байтов или регистр DX при умножении слов) равна нулю, то

Иначе эти флаги либо не равны, либо равны 1.

В конце как обычно расскажу, почему эта команда ассемблера называется MUL. Это сокращение от английского слова MULTIPLY, которое можно перевести как “умножить, умножать”.

Первые шаги в программирование

Главный вопрос начинающего программиста – с чего начать? Вроде бы есть желание, но иногда «не знаешь, как начать думать, чтобы до такого додуматься». У человека, который никогда не имел дело с информационными технологиями, даже простые вопросы могут вызвать большие трудности и отнять много времени на решение. Подробнее.

Ассемблер. Арифметические инструкции

Обновл. 20 Окт 2019 |

В этом уроке мы будем разбираться с арифметическими инструкциями в ассемблере на примере INC, DEC, ADD, SUB и пр.

Инструкция INC

Инструкция INC (от англ. «INCREMENT») используется для увеличения операнда на единицу. Она работает с одним операндом, который может находиться либо в регистре, либо в памяти.

Синтаксис инструкции INC:

Операндом место_назначения может быть 8-битный, 16-битный или 32-битный операнд.

Инструкция DEC

Инструкция DEC (от англ. «DECREMENT») используется для уменьшения операнда на единицу. Она работает с одним операндом, который может находиться либо в регистре, либо в памяти.

Синтаксис инструкции DEC:

Операндом место_назначения может быть 8-битный, 16-битный или 32-битный операнд.

Инструкции ADD и SUB

Инструкции ADD и SUB используются для выполнения простого сложения/вычитания двоичных данных размером в byte, word и doubleword, то есть для сложения или вычитания 8-битных, 16-битных или 32-битных операндов, соответственно.

Читать еще:  Ошибка expected at end of input

Синтаксис инструкций ADD и SUB:

ADD/SUB место_назначения, источник

Инструкции ADD/SUB могут выполняться между:

регистром и регистром;

памятью и регистром;

регистром и памятью;

памятью и константами.

Однако, как и другие инструкции, операции типа память-в-память невозможны с использованием инструкций ADD/SUB. Операции ADD или SUB устанавливают или сбрасывают флаги переполнения и переноса.

В следующем примере мы спрашиваем у пользователя два числа, сохраняем их в регистрах EAX и EBX, затем выполняем операцию сложения, сохраняем результат в ячейке памяти res и выводим его на экран:

Результат выполнения программы выше:

Enter a digit:
3
Please enter a second digit:
4
The sum is:
7

Ниже рассмотрен пример, в котором, за счёт того, что значения переменных для арифметических выражений прописаны в самом коде программы, можно получить код программы короче и проще:

Результат выполнения программы выше:

Инструкции MUL и IMUL

Есть две инструкции для умножения двоичных данных:

инструкция MUL (от англ. «MULTIPLY») обрабатывает данные unsigned;

инструкция IMUL (от англ. «INTEGER MULTIPLY») обрабатывает данные signed.

Обе инструкции влияют на флаги переноса и переполнения.

Синтаксис инструкций MUL/IMUL:

Множимое в обоих случаях будет в аккумуляторе, в зависимости от размера множимого и множителя, и результат умножения также сохраняется в двух регистрах, в зависимости от размера операндов.

Рассмотрим 3 разных сценария:

Сценарий №1: Когда перемножаются 2 значения типа byte — множимое находится в регистре AL, а множителем является значение типа byte в памяти или в другом регистре. Результат произведения находится в AX. Старшие 8 бит произведения хранятся в AH, а младшие 8 бит — хранятся в AL:

Сценарий №2: Когда перемножаются 2 значения типа word — множимое должно быть в регистре AX, а множителем является значение типа word в памяти или в другом регистре. Например, для такой инструкции, как MUL DX , вы должны сохранить множитель в DX, а множимое — в AX. В результате получится значение типа doubleword для которого понадобятся два регистра. Часть высшего порядка (крайняя слева) сохраняется в DX, а часть нижнего порядка (крайняя справа) — сохраняется в AX:

Сценарий №3: Когда перемножаются 2 значения типа doubleword — множимое должно находится в EAX, а множителем является значение типа doubleword, хранящееся в памяти или в другом регистре. Результат умножения сохраняется в регистрах EDX и EAX. Биты старшего порядка сохраняются в регистре EDX, а биты младшего порядка — сохраняются в регистре EAX:

Умножение в ассемблере

7.1. Сложение и вычитание.

7.1.1. ADD – команда для сложения двух чисел. Она работает как с числами со знаком, так и без знака.

Логика работы команды:

Возможные сочетания операндов для этой команды аналогичны команде MOV .

По сути дела, это – команда сложения с присвоением, аналогичная принятой в языке C / C ++:

Операнды должны иметь одинаковый размер. Результат помещается на место первого операнда.

После выполнения команды изменяются флаги, по которым можно определить характеристики результата:

  1. Флаг CF устанавливается, если при сложении произошёл перенос из старшего разряда. Для беззнаковых чисел это будет означать, что произошло переполнение и результат получился некорректным.
  2. Флаг OF обозначает переполнение для чисел со знаком.
  3. Флаг SF равен знаковому биту результата (естественно, для чисел со знаком, а для беззнаковых он равен старшему биту и особо смысла не имеет).
  4. Флаг ZF устанавливается, если результат равен 0.
  5. Флаг PF — признак чётности, равен 1, если результат содержит нечётное число единиц.

add ax ,5 ; AX = AX + 5

add dx,cx ;DX = DX + CX

add dx,cl ;Ошибка: разный размер операндов.

7.1.2. SUB — команда для вычитания одного числа из другого. Она работает как с числами со знаком, так и без знака.

Логика работы команды:

Возможные сочетания операндов для этой команды аналогичны команде MOV .

По сути дела, это – команда вычитания с присвоением, аналогичная принятой в языке C / C ++:

Операнды должны иметь одинаковый размер. Результат помещается на место первого операнда.

На самом деле вычитание в процессоре реализовано с помощью сложения. Процессор меняет знак второго операнда на противоположный, а затем складывает два числа.

sub ax ,13 ; AX = AX — 13

sub ax , bx ; AX = AX + BX

sub b x,cl ;Ошибка: разный размер операндов.

7.1.3. Инкремент и декремент. Очень часто в программах используется операция прибавления или вычитания единицы. Прибавление единицы называется инкрементом, а вычитание — декрементом. Для этих операций существуют специальные команды процессора: INC и DEC. Эти команды не изменяют значение флага CF.

Читать еще:  Критическая ошибка 32

Эти команды содержит один операнд и имеет следующий синтаксис:

Логика работы команд:

В качестве инкремента допустимы регистры и память: reg , mem .

inc ax ; AX = AX + 1

dec ax ; AX = AX — 1

7.1.4. NEG – команда для изменения знака операнда.

Логика работы команды:

В качестве декремента допустимы регистры и память: reg , mem .

7.2. Сложение и вычитание с переносом.

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

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

На следующем рисунке показано сложение двух двоичных чисел командой ADD:

При сложении происходит перенос из 7-го разряда в 8-й, как раз на границе между байтами. Если мы будем складывать эти числа по частям командой ADD, то перенесённый бит потеряется и в результате мы получим ошибку. К счастью, перенос из старшего разряда всегда сохраняется в флаге CF. Чтобы прибавить этот перенесённый бит, достаточно применить команду ADC:

//Сложение двух чисел с учетом переноса: FFFFFFAA + FFFF

Умножение (MUL) и Умножение с накоплением (MLA) с 32-битным результатом

Эти команды будут выполнены, если условие истинно. Все различные условия их выполнения перечислены в таблице 6. Машинный код обеих команд приведен на рис.21.

Обе команды для выполнения целочисленного умножения используют алгоритм, основанный на цепочке операций логического сдвига и сложения 8-битных операндов (Booth’s algorithm).


Рис. 21. Команды умножения

В команде умножения (MUL) используется следующая форма записи: Rd := Rm*Rs. Регистр Rn игнорируется и должен быть равен нулю с целью совместимости с возможным в будущем расширением системы команд.

В командах умножения с накоплением (MLA) используется другая форма записи: Rd := Rm*Rs + Rn. При Rm=1 или Rs=1 эта команда по своим действиям эквивалентна выполнению команды ADD.

Обе команды позволяют выполнять операции только с целочисленными операндами как без знака так и со знаком (дополнение до 2-х).

Результаты умножения 32-битных операндов со знаком и 32-битных операндов без знака различаются только своими старшими 32-мя битами, а младшие 32 бита обоих результатов — одинаковы обоих типов операндов. Поскольку результат выполнения команд MUL и MLA только 32-битный (старшие 32 бита результата будут отброшены), то результат выполнения этих команд будет одинаков как для операндов со знаком, так без знака.

Например, команда умножения 0xFFFFFFF6 (операнд A) на 0x00000014 (операнд B) даст результат, равный 0xFFFFFF38.

Если операнды интерпретируются как знаковые

Пусть, операнд А = -10, а операнд B = 20, то результатом их умножения будет число -200, которое корректно записывается так: 0xFFFFFF38.

Если операнды — без знака

Пусть, операнд А = 4294967286, а операнд B = 20, то результатом их умножения будет число 85899345720, которое корректно записывается так: 0x13FFFFFF38, но старшие 32 бита результата отбрасываются, то окончательным результатом умножения будет число 0xFFFFFF38.

Недопустимо использование регистра-результата Rd одновременно в качестве регистра-операнда (Rm, Rn или Rs). Также недопустимо использование регистра R15 в качестве регистра-операнда или регистра-результата.

Все другие комбинации остальных регистров будут давать корректный результат, а, если требуется, то в роли Rd, Rn и Rs может выступать один и тот же регистр.

Флаги регистра CPSR

Возможность воздействия на флаги регистра CPSR определяется битом S в соответствующем поле команды. Флаги N (минус) и Z (ноль) устанавливаются в соответствии с результатом умножения: флаг N становится равным 31-му биту результата, а флаг Z устанавливается только, если результат — ноль. Флаг С (перенос) устанавливается в неизвестное состояние, а флаг V (переполнение) — не используется.

Число машинных тактов при выполнении

Команда MUL выполняется за 1S + mI машинных тактов, а команда MLA — за 1S + I(m + 1) машинных тактов, где S и I зависят от типа машинных тактов, m — количество 8-битных множителей, необходимых для выполнения умножения, и зависит содержимого операнда-множителя Rs. Возможные значения m перечислены ниже:

Читать еще:  Ошибка stop engine

m = 1, если биты [31:8] операнда-множителя — либо все нули, либо все единицы. m = 2, если биты [31:16] операнда-множителя — либо все нули, либо все единицы. m = 3, если биты [31:24] операнда-множителя — либо все нули, либо все единицы. m = 4: во всех остальных случаях.

ProgrammWS

Все для начинающего программиста

Меню сайта

Информация

Programm.ws — это сайт, на котором вы можете почитать литературу по языкам программирования , а так-же посмотреть примеры работающих программ на С++, ассемблере, паскале и много другого..

Программирование — в обычном понимании, это процесс создания компьютерных программ.
В узком смысле (так называемое кодирование) под программированием понимается написание инструкций — программ — на конкретном языке программирования (часто по уже имеющемуся алгоритму — плану, методу решения поставленной задачи). Соответственно, люди, которые этим занимаются, называются программистами (на профессиональном жаргоне — кодерами), а те, кто разрабатывает алгоритмы — алгоритмистами, специалистами предметной области, математиками.
В более широком смысле под программированием понимают весь спектр деятельности, связанный с созданием и поддержанием в рабочем состоянии программ — программного обеспечения ЭВМ. Более точен современный термин — «программная инженерия» (также иначе «инженерия ПО»). Сюда входят анализ и постановка задачи, проектирование программы, построение алгоритмов, разработка структур данных, написание текстов программ, отладка и тестирование программы (испытания программы), документирование, настройка (конфигурирование), доработка и сопровождение.

Приложение. Система команд процессоров Intel

IMUL Умножение целых чисел со знаком

Команда IMUL выполняет умножение целого числа со знаком, находящегося в регистре AL (в случае умножения на байт) или АХ (в случае умножения на слово), на операнд-источник (целое число со знаком). Размер произведения в два раза больше размера сомножителей.
Для однобайтовых операций один из сомножителей помещается в регистр AL; после выполнения операции произведение записывается в регистр АХ.
Для двухбайтовых операций один из сомножителей помещается в регистр АХ; после выполнения операции произведение записывается в регистры DX:AX (в DX — старшая часть, в АХ — младшая).
В качестве операнда-сомножителя команды imul можно указывать регистр (кроме сегментного) или ячейку памяти; не допускается умножение на непосредственное значение. Команда воздействует на флаги OF и CF. Если АН или DX представляют собой просто знаковое расширение AL или АХ, соответственно (т.е. результат умножения со знаком верен), OF и CF сбрасываются в 0; в противном случае (результат со знаком не помещается в АХ или DX:AX) OF и CF устанавливаются в 1.

mov AL,5 ;Первый сомножитель
mov BL,3 ;Второй сомножитель
imul BL ;AX=000Fh (произведение)

mov AX,256 ;Первый сомножитель
mov BX,256 ;Второй сомножитель
imul BX ;DX=0001h, AX=0000h
;(число 65536)

mov AL,-5 ;AL=FBh
mov BL,3 ;BL=03h
imul BL ;AX-‘FFF1h (-15)

Допустимо использование 32-битовых операндов и дополнительных режимов адресации 32-разрядных процессоров. Имеются также варианты команды с двумя и тремя операндами.

Для команды imul с одним операндом второй сомножитель должен располагаться в AL, АХ или ЕАХ. Процессор выбирает размерность второго сомножителя, исходя из размерности первого, указанного в качестве операнда. 16-, 32- или 64-битовый знаковый результат помещается в регистры АХ, DX:AX или EDX:EAX, соответственно. Если после операции умножения содержимое АН, DX или EDX является лишь знаковым расширением AL, АХ или ЕАХ, соответственно, то флаги CF и OF сбрасываются в 0. В противном случае они устанавливаются в 1.
Для команды imul с двумя операндами их произведение записывается в первый операнд; второй операнд не изменяется. В качестве первого операнда могут выступать 16- или 32-разрядные регистры общего назначения; в качестве второго операнда — 16- или 32-разрядные регистры общего назначения, 16- или 32-битовые ячейки памяти или непосредственное значение. Оба операнда должны иметь один размер. Если результат умножения помещается в первый операнд, флаги CF и OF сбрасываются в 0. В противном случае они устанавливаются в 1.
Для команды imul с тремя операндами произведение второго и третьего операндов записывается в первый операнд. В качестве первого операнда могут выступать 16- или 32-разрядные регистры общего назначения; в качестве второго операнда — 16- или 32-разрядные регистры общего назначения или 16- или 32-битовые ячейки памяти; в качестве третьего операнда — только непосредственное значение. Два первых операнда должны иметь один размер. Если результат умножения помещается в первый операнд, флаги CF и OF сбрасываются в 0. В противном случае они устанавливаются в 1.

mov EAX,-1 ;Первый сомножитель
mov ESI,100000000 ;Второй сомножитель
imul ESI ;EDX=FFFFFFFFh,
;EAX=FA0AlF00h
;Результат=-100000000

;В полях данных
ор2 dd 100h ;Первый сомножитель
; В программном сегменте
mov EAX,400000h ;Второй сомножитель
imul EAX,op2 ;EAX=40000000h
Пример 3
mov BX,300h
imul АХ,ВХ,4 ;AX=300h*4=0C00h

Ссылка на основную публикацию
ВсеИнструменты 220 Вольт
Adblock
detector