Форум программистов, компьютерный форум, киберфорум
Assembler, MASM, TASM
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.63/2256: Рейтинг темы: голосов - 2256, средняя оценка - 4.63
Ушел с форума
Автор FAQ
 Аватар для Mikl___
16374 / 7686 / 1080
Регистрация: 11.11.2010
Сообщений: 13,761
14.11.2013, 10:29  [ТС]
ГЛАВА 10
АРИФМЕТИЧЕСКИЕ КОМАНДЫ
(часть 4/7)


Команды умножения
Если сложение и вычитание для знаковых и беззнаковых чисел производятся по одним и тем же алгоритмам, то умножение и деление для знаковых и беззнаковых чисел производятся по разным алгоритмам.
Допустим, вы умножаете 0FFh на 0FFh, если вы перемножаете числа со знаком, тогда результатом будет 1 (https://www.cyberforum.ru/cgi-bin/latex.cgi?-1\times -1=1), а если беззнаковые – тогда 0FE01h (https://www.cyberforum.ru/cgi-bin/latex.cgi?255\times 255=65025). Например, чтобы умножить или разделить два числа с разными знаками вам придется сначала отрицательное число преобразовать командой NEG в положительное, затем перемножить или разделить эти числа, затем опять командой NEG преобразовать результат. Поэтому для знаковых и беззнаковых чисел имеются по две команды умножения и деления. В остальном эти команды действуют одинаково.
Сочетание операций сдвигов (глава «Команды сдвига») и сложения позволяют осуществлять умножение чисел без знака.
Команда MUL
(Умножение целых без учета знака = «Unsigned MULTIPLY»)
Синтаксис команды:
MUL <SRC>
Возможные варианты команды:
mul reg/mem
Семантика команды
: операция умножения двух целых чисел без учета знака.
Псевдокод команды:
IF OperandSize=8
THEN
AXhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrowAL*SRC
IF AL=AX
THEN CFhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow0; OFhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow0
ELSE CFhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow1 OFhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow1 ENDIF
ELSE IF OperandSize =16
THEN DX:AXhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow AX*SRC
IF AX=DX:AX
THEN CFhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow0; OFhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow0
ELSE CFhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow1 OFhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow1 ENDIF
ELSE IF OperandSize =32
THEN EDX:EAXhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrowEAX*SRC
IF EAX=EDX:EAX
THEN CFhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow0 OFhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow0
ELSE CFhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow1 OFhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow1 ENDIF
ELSE IF OperandSize =64
THEN RDX:RAXhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow RAX*SRC
IF RAX=RDX:RAX
THEN CFhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow0 OFhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow0
ELSE CFhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow1 OFhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow1 ENDIF
ENDIF
Алгоритм работы: команда выполняет умножение двух операндов без учета знаков. Алгоритм зависит от формата операнда команды и требует явного указания местоположения только одного сомножителя SRC, который может быть расположен в памяти или в регистре, но не может быть непосредственно числом. Местоположение второго сомножителя фиксировано и зависит от размера сомножителя SRC:
  • если перемножить максимальные числа величиной в байт – результат займет 2 байта:
    0FFh * 0FFh = 255 * 255 = 65025 =0FE01h;
  • при перемножении максимальных чисел величиной в слово (2 байта)
    – результат займет уже 4 байта:
    0FFFFh * 0FF FFh = 65535 * 65535 = 4294836225 = 0FFFE0001h;
и так далее, двоичный код результата будет занимать в два раза больше места, чем максимальный двоичный код сомножителей;
  • если операнд SRC, указанный в команде – байт, то второй сомножитель расположен в регистре AL;
  • если операнд SRC, указанный в команде – слово, то сомножитель расположен в регистре AX;
  • если операнд SRC, указанный в команде – двойное слово, то сомножитель расположен в регистре EAX.
Местоположение результата умножения заранее известно и поэтому в команде явно не указывается. Под результат отводят в два раза больше места, чем под сомножители. Место, в которое будет помещен результат, определяется размером сомножителей:
  • при умножении байтов результат помещается в AX;
  • при умножении слов результат помещается в пару DX:AX;
  • при умножении двойных слов результат помещается в пару EDX:EAX;
  • при умножении счетверенных слов результат помещается в пару RDX:RAX.
Для получения квадрата числа поместите первый сомножитель в регистр AL/AX/EAX/RAX.
Хотя команда умножения выдает результат в удвоенном формате, не всегда величина произведения столь велика, что ей нужен удвоенный формат. Очень часто результат имеет тот же формат, что и сомножители. Вопрос о том, уместится ли результат умножения в формат сомножителей или нет, решается с помощью анализа флагов CF и OF:
CF=OF=1 – если произведение занимает двойной формат;
CF=OF=0 – если произведению достаточен формат сомножителей.
Assembler
1
2
3
4
5
6
7
.data
MN_1 DB 15
MN_2 DB 25
.code
MOV AH,0
MOV AL,MN_1 ;AX=15=0Fh
MUL MN_2 ;AX=15*25=375=177h
Умножение с многократной точностью
Команда MUL предназначена в основном для операций умножения с многократной точностью. Для иллюстрации продемонстрируем умножение двух 64-битных неотрицательных чисел:
https://www.cyberforum.ru/cgi-bin/latex.cgi?X\times Y=Z,
где https://www.cyberforum.ru/cgi-bin/latex.cgi?X=a2^{32} + b и https://www.cyberforum.ru/cgi-bin/latex.cgi?Y= c2^{32} + d
https://www.cyberforum.ru/cgi-bin/latex.cgi?X\times Y= (a2^{32} + b)\times(c2^{32} + d) = ac2^{64} + (ad + bc) 2^{32} + bd
Получаем классический алгоритм с 3 сложениями и 4 умножениями.
Так как умножение выполняется несколько медленнее, чем сложение, мы можем воспользоваться алгоритмом Карацуба из 4 сложений, 2 вычитаний и 3 умножений:
  1. вычислим https://www.cyberforum.ru/cgi-bin/latex.cgi?bd – первое умножение
  2. вычислим https://www.cyberforum.ru/cgi-bin/latex.cgi?ac – второе умножение
  3. вычислим https://www.cyberforum.ru/cgi-bin/latex.cgi?t_{0}=(a + b)\times(c+d) – третье умножение
https://www.cyberforum.ru/cgi-bin/latex.cgi?X\times Y=(a2^{32} + b)\times(c2^{32} + d)=ac2^{64} +(t_{0} - ac- bd)2^{32} + bd
Или используем алгоритм Тоома-Кука из 5 сложений, 3 вычитаний и 3 умножений:
  1. вычислим https://www.cyberforum.ru/cgi-bin/latex.cgi?bd – первое умножение
  2. вычислим https://www.cyberforum.ru/cgi-bin/latex.cgi?t_{0}=(a + b)\times(c + d) – второе умножение
  3. вычислим https://www.cyberforum.ru/cgi-bin/latex.cgi?t_{1}=(b - a)\times(d - c) – третье умножение
Так как
https://www.cyberforum.ru/cgi-bin/latex.cgi?\frac{(t_{0} - t_{1})}{2} = ad + bc и https://www.cyberforum.ru/cgi-bin/latex.cgi?\frac{(t_{0} + t_{1})}{2} - bd = ac
поэтому
https://www.cyberforum.ru/cgi-bin/latex.cgi?X\times Y=(a2^{32} + b)(c2^{32} + d)=(\frac{(t_{0} + t_{1})}{2} - bd)2^{64} +(t_{0} - t_{1})2^{31} + bd
Можно также использовать следующее свойство:
https://www.cyberforum.ru/cgi-bin/latex.cgi?X\times Y=\frac{(X+Y)^{2}}{4} - \frac{(X-Y)^{2}}{4} = \frac{((a + c)2^{32} + b + d)^{2}}{4} - \frac{((a - c)2^{32} + b - d)^{2}}{4}
и обойтись 2 умножениями (возведение в квадрат), 4 сложениями и 3 вычитаниями.
Пример оптимизации по размеру
Реализуем алгоритм в 3 сложения и 4 умножения. Пусть и сами числа, и место под результат располагаются в памяти
последовательно
Адрес Машинный кодВид команды до трансляции
004000C4 A130014000  mov eax,b
004000C9 F72538014000  mul d
004000CF A340014000 mov dword ptr Z,eax
004000D4 891544014000  mov dword ptr [Z+4],edx
004000DA A130014000 mov eax,b
004000DF F7253C014000  mul c
004000E5 010544014000 add dword ptr [Z+4],eax
004000EB 111548014000 adc dword ptr [Z+8],edx
004000F1 7306 jnc a1;если был перенос увеличим [Z+12]
004000F3 FF054C014000 inc dword ptr [Z+12]
004000F9 A134014000 a1: mov eax,a
004000FE F72538014000 mul d
00400104 010544014000 add dword ptr [Z+4],eax
0040010A 111548014000 adc dword ptr [Z+8],edx
00400110 7306 jnc a2;если был перенос увеличим [Z+12]
00400112 FF054C014000  inc dword ptr [Z+12]
00400118 A134014000 a2: mov eax,a
0040011D F7253C014000  mul c
00400123 110548014000  add dword ptr [Z+8],eax
00400129 11154C014000  adc dword ptr [Z+12],edx
0040012F C3 ret ;выход из программы
00400130 FFFFFFFF b dd 0FFFFFFFFh ;сомножители
00400134 FFFFFFFF a dd 0FFFFFFFFh ;X и Y
00400138 FFFFFFFF d dd 0FFFFFFFFh
0040013C FFFFFFFF c dd 0FFFFFFFFh
00400140 0000000000000000 Z dq 2 dup (0) ;результат
00400148 0000000000000000  
Сама программа после компиляции занимает 150h-0C4h=8Ch=140 байт. Пытаемся уменьшить размер программы. Так как и сомножители и место под результат расположены в памяти последовательно, то можно уменьшить размер кода программы если мы используем не прямую, а косвенную адресацию. При каждом таком обращении к памяти будет сэкономлено до четырех байт. Адреса операндов будут передаваться через регистр EBX.
Адрес Машинный код Вид команды до трансляции
004000C4 BB02014000  mov ebx,offset X
004000C9 8B03  mov eax,[ebx]
004000CB F76308  mul dword ptr [ebx+8]
004000CE 894310  mov dword ptr [ebx+16],eax
004000D1 895314  mov dword ptr [ebx+20],edx
004000D4 8B03  mov eax,[ebx]
004000D6 F7630C  mul dword ptr [ebx+12]
004000D9 014314  add dword ptr [ebx+20],eax
004000DC 115318  adc dword ptr [ebx+24],edx
004000DF 7303  jnc a1;если был перенос увеличим [ebx+28]
004000E1 FF431C  inc dword ptr [ebx+28]
004000E4 8B4304 a1: mov eax,[ebx+4]
004000E7 F76308  mul dword ptr [ebx+8]
004000EA 014314  add dword ptr [ebx+20],eax
004000ED 115318  adc dword ptr [ebx+24],edx
004000F0 7303  jnc a2;если был перенос увеличим [ebx+28]
004000F2 FF431C  inc dword ptr [ebx+28]
004000F5 8B4304 a2: mov eax,[ebx+4]
004000F8 F7630C  mul dword ptr [ebx+12]
004000FB 114318  add dword ptr [ebx+24],eax
004000FE 11531C  adc dword ptr [ebx+28],edx
00400101 C3  ret ;выход из программы
00400102 FFFFFFFFFFFFFFFF X dd 0FFFFFFFFFFFFFFFFh ;сомножители
0040010A FFFFFFFFFFFFFFFF Y dd 0FFFFFFFFFFFFFFFFh
00400112 0000000000000000 Z dq 2 dup (0) ;место под результат
0040011A 0000000000000000  
122h–C4h=5Eh=94 байта
В программе имеются повторяющиеся фрагменты кода, выделенные жирным шрифтом, которые можно оформить как процедуру, кроме того, две команды JNC метка и INC DWORD PTR [EBX+28] можно заменить на одну команду ADC DWORD PTR [EBX+28],0. Это сэкономит еще по одному байту кода.
Адрес Машинный кодВид команды до трансляции
004000C4 BB02014000 mov ebx,offset X
004000C9 8B03 mov eax,[ebx]
004000CB F76308 mul dword ptr [ebx+8]
004000CE 894310 mov dword ptr [ebx+16],eax
004000D1 895314 mov dword ptr [ebx+20],edx
004000D4 8B03 mov eax,[ebx]
004000D6 F7630C mul dword ptr [ebx+12]
004000D9 E812000000 call routine; вызов процедуры
004000DE F76308 mul dword ptr [ebx+8]
004000E1 E80A000000 call routine
004000E6 F7630C mul dword ptr [ebx+12]
004000E9 114318 add dword ptr [ebx+24],eax
004000EC 11531C adc dword ptr [ebx+28],edx
004000EF C3 ret ;выход из программы
routine proc; процедура
004000F0 014314 add dword ptr [ebx+20],eax
004000F3 115318 adc dword ptr [ebx+24],edx
004000F6 83531C00 adc dword ptr [ebx+28],0
004000FA 8B4304 mov eax,[ebx+4]
004000FD C3 ret;выход из процедуры
routine endp;сомножители
004000FE FFFFFFFFFFFFFFFF X dd 0FFFFFFFFFFFFFFFFh
0040010A FFFFFFFFFFFFFFFF Y dd 0FFFFFFFFFFFFFFFFh
00400112 0000000000000000 Z dq 2 dup (0) ; место под результат
0040011A 0000000000000000 
11Eh-C4h=5Ah=90 байт
Итак, нам удалось уменьшить программу со 140 до 90 байт, то есть на 50 байт. Попробуем написать еще более короткий код. Вернем в текст программы то, что мы вынесли в подпрограмму. В тексте программы есть три очень похожих фрагмента.
1) MOV [EBX+16], EAX 2) ADD [EBX+20], EAX 3) ADD [EBX+24],EAX
MOV [EBX+20], EDX ADD [EBX+24], EDX ADC [EBX+28],EDX
 ADC [EBX+28],0 
Так как в ячейках памяти, отведенных под результат, пока еще ничего нет и если в ячейки [EBX+16] и [EBX+20] заранее поместить 0, тогда результат команд MOV [EBX+16],EAX и ADD [EBX+16],EAX будет эквивалентен. Добавим также для большей схожести в первый фрагмент – команду ADC DWORD PTR [EBX+24],0, в третий фрагмент – команду ADC DWORD PTR [EBX+32],0. Использование этих команд результат не изменит.
MOV EAX,[EBX] MOV EAX,[EBX] MOV EAX,[EBX]
  MOV EDI,8
MUL D/[EBX+8] MUL D/[EBX+8] MUL D/[EBX+EDI]
MOV [EBX+16],EAX ADD [EBX+16],EAX ADD [EBX+16],EAX
MOV [EBX+20],DX ADC [EBX+20],EDX ADC [EBX+20],EDX
 ADC [EBX+24],0 ADC [EBX+24],0
MOV EAX,[EBX] MOV EAX,[EBX] MOV EAX,[EBX]
  ADD EBX,4
MUL D/[EBX+12] MUL D/[EBX+8+4] MUL D/[EBX+EDI]
ADD [EBX+20],EAX ADD [EBX+16+4],EAX ADD [EBX+16],EAX
ADC [EBX+24],EDX ADC [EBX+20+4],EDX ADC [EBX+20],EDX
ADC [EBX+28],0 ADC [EBX+24+4],0 ADC [EBX+24],0
MOV EAX,[EBX+4] MOV EAX,[EBX+4] MOV EAX,[EBX]
  ADD EBX,4
  SUB EBX,4
  SUB EDI,4
MUL D/[EBX+8] MUL D/[EBX+4+4] MUL D/[EBX+EDI]
ADD [EBX+20],EAX ADD [EBX+16+4],EAX ADD [EBX+16],EAX
ADC [EBX+24],EDX ADC [EBX+20+4],EDX ADC [EBX+20],EDX
ADC [EBX+28],0 ADC [EBX+24+4],0 ADC [EBX+24],0
MOV EAX,[EBX+4] MOV EAX,[EBX+4] MOV EAX,[EBX]
  ADD EBX,4
MUL D/[EBX+12] MUL D/[EBX+4+8] MUL D/[EBX+EDI]
ADD [EBX+24],EAX ADD [EBX+16+8],EAX ADD [EBX+16],EAX
ADC [EBX+28],EDX ADC [EBX+20+8],EDX ADC [EBX+20],EDX
 ADC [EBX+24+8],0 ADC [EBX+24],0
  MOV EAX,[EBX]
  ADD EBX,4
Жирным шрифтом выделены повторяющиеся фрагменты кода. Можно было бы использовать вызов подпрограмм, но при использовании цикла код программы будет короче. Вот что у нас получилось в результате:
Адрес Машинный кодВид команды до трансляции
004000C4 BBEF004000  mov ebx,offset X
004000C9 8B03  mov eax,[ebx]
004000CB BF08000000  mov edi,8
004000D0 B902000000 a2: mov ecx,2
004000D5 F76308 a1: mul dword ptr [ebx+8]
004000D8 014310  add [ebx+16],eax
004000DB 115314  adc [ebx+20],edx
004000DE 83531800  adc dword ptr [ebx+24],0
004000E2 83C304  add ebx,4
004000E5 E2EF  loop a1
004000E7 83EB04  sub ebx,4
004000EA 83EF04  sub edi,4
004000ED 75E2  jnz a2
004000EF C3  ret ;выход из программы
004000F0 FFFFFFFFFFFFFFFF X dd 0FFFFFFFFFFFFFFFFh;сомножители
004000F8 FFFFFFFFFFFFFFFF Y dd 0FFFFFFFFFFFFFFFFh
00400100 0000000000000000 Z dq 2 dup (0) ;место под результат
00400108 0000000000000000  
110h-0C4h=4Ch=76 байт.
Подведем итоги: https://www.cyberforum.ru/cgi-bin/latex.cgi?140\rightarrow 94\rightarrow 90\rightarrow 76
Попробуйте сами написать еще короче, может быть получится…
Пример оптимизации по быстродействию
a, b, c и d 16-разрядные числа. Найти https://www.cyberforum.ru/cgi-bin/latex.cgi?(a+b)\cdot (c+d), используя только 16-разрядные арифметические операции.
1) Решение проблемы «в лоб»:
https://www.cyberforum.ru/cgi-bin/latex.cgi?(a+b)\cdot (c+d)=a\cdot c+b\cdot c+a\cdot d+b\cdot d
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
mov ax,a
mul c ;dx:ax=a*c
mov [z0],ax ;младший байт результата
mov [z1],dx
mov [z2],0 ;старший байт результата
mov ax,b
mul c ;dx:ax=b*c
add [z0],ax
adc [z1],dx
adc [z2],0
mov ax,a
mul d ;dx:ax=a*d
add [z0],ax
adc [z1],dx
adc [z2],0
mov ax,b
mul d ;dx:ax=b*d
add [z0],ax
adc [z1],dx
adc [z2],0
2) Так как умножение достаточно медленная операция – постараемся свести количество умножений к минимуму.
https://www.cyberforum.ru/cgi-bin/latex.cgi?a+b=x\cdot 2^{16} + (a+b) mod 2^{16}
https://www.cyberforum.ru/cgi-bin/latex.cgi?c+d=y\cdot 2^{16} + (c+d) mod 2^{16} ,
где операция https://www.cyberforum.ru/cgi-bin/latex.cgi?mod 2^{16} возвращает младшие 16 бит результата, а x,y={0,1} биты переноса, образовавшиеся в результате сложений.
https://www.cyberforum.ru/cgi-bin/latex.cgi?(a+b)\cdot (c+d)=(x\cdot 2^{16} + (a+b) mod 2^{16})\cdot (y\cdot 2^{16} + (c+d) mod 2^{16})=
https://www.cyberforum.ru/cgi-bin/latex.cgi?=x\cdot y\cdot 2^{32} +(x\cdot (c+d) mod 2^{16} + y\cdot (a+b) mod 2^{16})\cdot 2^{16} + (a+b) mod 2^{16}\cdot (c+d) mod 2^{16}
Умножение на {0,1} можно заменить на логические побитовые операции:
x*y=-((-x)&(-y))
x*(c+d) mod 216 =(-x)&(c+d) mod 216
y*(a+b) mod 216 =(-y)&(a+b) mod 216
тогда
(a+b)*(c+d) = -((-x)&(-y))*232 + ((-x)&(c+d) mod 216 +
+(-y)&(a+b) mod 216)*216+((a+b) mod 216)*((c+d) mod 216)
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
mov ax,a
add ax,b ;ax=(a+b) mod 216
sbb cx,cx ;cx=-x
mov dx,cx ;dx=-x
mov bx,c
add bx,d ;bx=(c+d) mod 216
sbb si,si ;si=-y
and dx,si ;dx=(-x)&(-y)
neg dx ;dx=-((-x)&(-y))
mov [z2],dx
and cx,bx ;cx=(-x)&(c+d) mod 216
and si,ax ;si=(-y)&(a+b) mod 216
add cx,si
mov [z1],cx
adc [z2],0
mul bx ;dx:ax=((a+b) mod 216)?((c+d) mod 216)
mov [z0],ax ;младший байт результата
add [z1],dx
adc [z2],0 ;старший байт результата
Команда IMUL(Умножение целых чисел со знаком =” SIGNED MULTIPLY”)
Синтаксис команды Количество операндов
IMUL <SRC> (1)
IMUL <DEST>,<SRC> (2а)
IMUL <DEST>,<Imm> (2б)
IMUL<DEST>,<SRC>,<Imm> (3)
Возможные варианты команды:
imul reg/mem
imul reg,reg/mem
imul reg,imm
imul reg,reg/mem,imm
Семантика команды: операция умножения двух целочисленных двоичных значений со знаком.
Алгоритм работы: алгоритм работы команды зависит от используемой формы команды. Форма команды с одним операндом (1) требует явного указания местоположения только сомножителя SRC, который может быть расположен в ячейке памяти или регистре. Местоположение второго сомножителя фиксировано и зависит от размера сомножителя SRC:
  • если операнд SRC, указанный в команде, – байт, то второй сомножитель расположен в регистре AL;
  • если операнд SRC, указанный в команде, – слово, то второй сомножитель расположен в регистре AX;
  • если операнд SRC , указанный в команде, – двойное слово, то второй сомножитель расположен в регистре EAX.
Пример:
Assembler
1
2
Alfa db200
IMUL Alfa ; AL*(–200)-> AX
Результат умножения для команды с одним операндом также помещается в строго определенное место, определяемое размером сомножителей:
  • при умножении байтов результат помещается в AX;
  • при умножении слов результат помещается в пару DX:AX;
  • при умножении двойных слов результат помещается в пару EDX:EAX;
  • при умножении счетверенных слов результат помещается в пару RDX:RAX.
Команды с двумя и тремя операндами однозначно определяют расположение результата и сомножителей следующим образом:
  • в команде с двумя операндами (2а) сомножители DEST и SRC. Результат помещается в DEST;
Псевдокод команды:
https://www.cyberforum.ru/cgi-bin/latex.cgi?DEST\leftarrow DEST\times SRC
  • в команде с двумя операндами (2б) сомножители DEST и непосредственно указанное число Imm. Результат помещается в DEST;
Псевдокод команды:
https://www.cyberforum.ru/cgi-bin/latex.cgi?DEST\leftarrow DEST\times Imm
  • в команде с тремя операндами (3) сомножители SRC и непосредственно указанное число Imm размером в байт, слово или двойное слово. Результат помещается в DEST.
Псевдокод команды:
DESThttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow SRChttps://www.cyberforum.ru/cgi-bin/latex.cgi?\times Imm
По команде с с двумя операндами (2а или 2б) генерируется команда
умножения с тремя операндами (3), где операнд SRC=DEST .
Псевдокод команды:
IF (NumberOfOperands=1)
THEN IF (OperandSize=8)
THEN
AXhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrowAL*SRC(Знаковое расширение)
IF AL=AX
THEN CFhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow0; OFhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow0
ELSE CFhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow1 OFhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow1 ENDIF
ELSE IF OperandSize=16
THEN
DX:AXhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrowAX*SRC(Знаковое расширение)
IF sign_extend_to_32 (AX)=DX:AX
THEN CFhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow0 OFhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow0
ELSE CFhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow1 OFhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow1 ENDIF
ELSE IF OperandSize=32
THEN
EDX:EAXhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrowEAX*SRC(Знаковое расширение)
IF EAX=EDX:EAX
THEN CFhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow0 OFhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow0
ELSE CFhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow1 OFhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow1 ENDIF
ENDIF
ENDIF
ELSE IF (NumberOfOperands=2)
THEN IF (OperandSize=8)
THEN
temphttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow DEST*SRC
(Знаковое расширение DEST*SRC, у temp удвоенный размер DEST)
DESThttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrowDEST*SRC(Знаковое расширение)
IF temp?DEST
THEN CFhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow1; OFhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow1
ELSE CFhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow0 OFhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow0 ENDIF
ELSE (NumberOfOperands=3)
DESThttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow SRC1*SRC2(Знаковое расширение)
temphttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow SRC1*SRC2
(Знаковое расширение SRC1*SRC2; у temp удвоенный размер SRC1)
IF temp?DEST
THEN CFhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow1; OFhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow 1
ELSE CFhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow0 OFhttps://www.cyberforum.ru/cgi-bin/latex.cgi?\leftarrow0 ENDIF
ENDIF
ENDIF
Команда IMUL устанавливает в ноль флаги OF и CF, если размер результата соответствует регистру назначения. Если эти флаги отличны от нуля, то это означает, что результат слишком велик для отведенных ему регистром назначения рамок и необходимо указать больший по размеру регистр для успешного завершения данной операции умножения. Конкретными условиями сброса флагов OF и CF в ноль являются следующие условия:
  • для однооперандной формы команды IMUL регистры AX/DX/EDX являются знаковыми расширениями регистров AL/AX/EAX;
  • несмотря на использование регистров EAX и EDX по умолчанию, для двух- и трехоперандной формы команды IMUL можно указать другие источники и приёмники. Первый операнд – место, куда необходимо поместить результат и которое всегда должно быть регистром, второй и третий операнды – два значения, которые нужно перемножить. Для размещения результата умножения достаточно размерности указанных регистров назначения r16/32.
Применение: команда выполняет целочисленное умножение операндов с учетом их знаковых разрядов. Для выполнения этой операции необходимо наличие двух сомножителей. Размещение и задание их местоположения в команде зависит от формы применяемой команды умножения, которая, в свою очередь, определяется моделью микропроцессора. Так, для микропроцессоров до i80386 возможна только однооперандная форма команды, для последующих моделей микропроцессоров дополнительно можно использовать одно-, двух- и трехоперандные формы этой команды.
Assembler
1
2
3
4
5
MOV BX,186
IMUL AX,BX,7 ; AX:=BX*7
;если результату не хватило размерности операнда1,
;то перейдем на метку M1, где и скорректируем ситуацию
JC M1
Следующий пример:
Assembler
1
IMUL EBP,DWORD PTR [ESI+74],0FF800002h; EBP:=[ESI+74] * 0FF800002h
Пусть в ячейке памяти [esi+74] находится число 0C7000000h (–956301312). Это значение будет умножено на 0FF800002h (–8388606), а результат данной операции будет сохранён в EBP:
–956301312?(–8388606)=8022034923651072=1 C7FFF8E000000h
Поскольку 32-разрядный регистр EBP не может вместить это 64-разрядное число полностью, то в нем остается содержимое младших 32 разрядов, равное 8E000000h, а содержимое старших 32 разрядов будет потеряно.
В следующем примере два операнда, которые перемножаются друг на друга, а результат сохраняется в первом операнде.
Assembler
1
IMUL EDX, DWORD PTR [EBP-18]; EDX:=EDX * [EBP-18]
Основной способ для умножения больших чисел – использовать IMUL только с одним операндом, так как в этом случае результат сохраняется в паре регистров EDX:EAX, то есть он может быть двойного размера, чего нельзя добиться при использовании двух или трех операндов, поэтому применяйте двух- и трехоперандные команды imul для умножения небольших чисел.
Пусть нам потребовалось закодировать команду imul esi,5. Из всех опкодов нам подходит следующий: 6B /r ib (IMUL r32, r/m32, imm8). Согласно описанию, поле Reg задает регистр назначения, R/M – регистр или адрес ячейки памяти с умножаемым значением, последним идет байт множителя.
 опкод d w Mod Reg R/M imm8
bin 011010 1 1 11 110=ESI 110=ESI 0101
hex 6Bh0F6h 5


Продолжение
Миниатюры
Электронный учебник   Электронный учебник   Электронный учебник  

Электронный учебник   Электронный учебник   Электронный учебник  

Электронный учебник   Электронный учебник   Электронный учебник  

Электронный учебник   Электронный учебник   Электронный учебник  

Электронный учебник  
Изображения
  
8
Закрытая тема Создать тему
Новые блоги и статьи
сукцессия 33. открытые вопросы от клауде
anaschu 19.07.2026
"Что накопилось за эту часть А — тринадцать правок, из которых шесть пришли из ваших вопросов и каждая оказалась реальной ошибкой, а не калибровкой: односторонний симбиоз, отсутствующий листопад,. . .
32 сукцессия
anaschu 19.07.2026
сукцессия 28‑мерное ядро стабилизировано Коллеги, фиксирую разбор инженерных правок и их изоморфную проекцию на экономику, меметику и половой отбор. Модель теперь не «подкручивает» сходимость —. . .
сукцессия 31: модель микоризы - это модель ещё нескольких явлений, социальных и экономических
anaschu 18.07.2026
Теория «Всего»: апдейт v1. 1. 2 — 28‑мерное ядро стабилизировано Коллеги, фиксирую разбор инженерных правок и их изоморфную проекцию на экономику, меметику и половой отбор. Модель теперь не. . .
сукцессия 30. Массив проверяющих друг друга моделей
anaschu 18.07.2026
Архитектура сети взаимопроверяющих моделей микоризной сукцессии (v2. 0) Развитие тензорного ОДУ-ядра и создание кросс-платформенного калибровочного полигона Уважаемые коллеги! В продолжение. . .
Грибы - это женщины, деревья - это мужчины. Анти инь янь для союза мужчины и женщины.
anaschu 18.07.2026
ГЛАВНЫЙ НАУЧНО-ФИЛОСОФСКИЙ ВЫВОД: Сексуально-Репродуктивный Капитализм против Государства Моногамии Коллеги, мы вышли на финишную прямую 20-мерного ОДУ-моделирования вековой сукцессии (ветка. . .
Текстовый слайдер с нумерацией страниц и кроссбраузерность.
russiannick 18.07.2026
Один мой друг написал текстовый слайдер с нумерацией страниц. Сегодня я расскажу как он умудрился подружить его с кроссбраузерностью. Очевидно сложно угодить с шириной каждому браузеру. Один крадет. . .
Грибы - это мемы, дерево - это человек. Применение микоризной модели к теории меметики Докинза.
anaschu 18.07.2026
Меметический изоморфизм теории «всего»: Грибная сукцессия как модель эволюции идей Докинза Базовый код системы ОДУ микоризной сукцессии описывает не просто биологию, а универсальную. . .
Грибы - это корпорации, деревья - это государства. Механизм массонского захвата власти
anaschu 18.07.2026
Макроэкономический изоморфизм теории «всего»: Грибная сукцессия как модель транснационального капитализма Базовый код системы ОДУ микоризной сукцессии описывает не просто биологию, а. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru