Multiplicação
MULTIPLICAÇÃO | |
MUL | Multiplicar byte ou palavra não sinalizados |
IMUL | Multiplicar byte ou palavra inteiros |
AAM | Ajuste ASCII na multiplicação |
++MUL++
Quando digo "sinalizado" entenda "com sinal", "positivo ou negativo".
As operações válidas para MUL e IMUL são:
Fonte |
Registro 8 bits |
Registro 16 bits |
Variável 8 bits |
Variável 16 bits |
Sua sintaxe para multiplicações de 8 bits é:
AX = AL * operando
Veja este exemplo:
MOV AL,25 ;operando fonte1
MOV CL,4 ;operando fonte2
MUL CL ;AX = AL * CL
;AX = 100
Em AX você tem o resultado dessa multiplicação.
Para multiplicações de 16 bits temos:
DX,AX = AX * operando
Mas uma vez me deparo com a falta de exatidão dos meus livros de consulta, eles dizem: "Para valores de word, o resultado encontra-se no par de registradores AX:DX." Certo...entendi tudo!
Na verdade "eles" querem dizer o seguinte:
Se a operação de multiplicação resultar num número menor que 65535, então o registro DX = 0000h e AX = resultado.
Se a operação de multiplicação resultar num número maior que 65535 segue-se esta lógica:
-enquanto AX > 65535 faça:
AX = AX - 65536
DX = DX + 1
-fim_enquanto
Legal! Assim fica melhor pra entender! Note este exemplo:
MOV AX, 50000
MOV CX,3
MUL CX ;AX = AX * CX
;AX = "150000" = 18928
;DX = 2
CMP AX,18928 ;se AX for igual a 18928, vamos logo para o FIM
JE FIM
MOV AH,1 ;se não, espera-se o pressionamento duma tecla
INT 21H ;para só então sair.
FIM:
MOV AH,4CH
INT 21H
++IMUL++
Antes de falar sobre o IMUL, tenho de apresentar dois novos tipos de dados que são: o 'sbyte' e o 'sword'. Note a tabela:
WORD (DW) | Variável de 16 bits. Abrange valores de 0 a 65535 |
SWORD | Variável de 16 bits. Abrange valores de -32768 a 32767 |
BYTE (DB) | Variável de 8 bits. Abrange valores de 0 a 255 |
SBYTE | Variável de 8 bits. Abrange valores de -128 a 127 |
Já sabemos o que ocorre quando ultrapassamos os valores permitidos para variáveis do tipo word e byte. Só para lembrar, são feitas subtrações sucessivas (de 65536 para DW e 256 para DB) até que a variável fique na faixa de valores permitidos para DW e DB. Mas o que ocorre com sword e sbyte, quando ultrapassamos os valores permitidos ?
Observe:
num1 sbyte ?
mov num1,125
add num1,3 ;num1 = 125 + 3 = 128
Poderá notar, se compilar isso, que nada vai acontecer. O código ASCII de número 128 será apresentado na tela. Valendo assim as propriedades descritas no ASM1F, quando ultrapassamos o limite de variáveis DB e DW.
No entanto os tipos de dados sinalizados simplificam a nossa vida. Note este exemplo:
MOV AX,1
SUB AX,3 ;AX = -2
.IF AX < 0
CALL FIM
.ENDIF
Isso não funciona, sabe por quê ? Lembre-se do complemento de dois, e de como os números negativos são representados. Se "0" é igual a 0000h, como é representado "-2" ? Reposta: FFFEh. Por alguma razão que não conheço, o registro não consegue comparar estes dois valores.
MOV AX,1
SUB AX,3 ;AX = -2
.IF AX < -1
CALL FIM
.ENDIF
Isso sim funciona, sabe por quê ? Lembre-se do complemento de dois, e de como os números negativos são representados. Se "-1" é igual a FFFFh, como é representado "-2" ? Reposta: FFFEh. Dessa vez o registrador resolve colaborar e admitir que -2 é menor que -1, seguindo assim a lógica matemática.
O mesmo aconteceria se usássemos uma variável do tipo byte. Note:
NATURAL DB ?
MOV NATURAL,1
SUB NATURAL,3 ;NATURAL=-2
.IF NATURAL < 0
CALL FIM ;essa rotina NUNCA será chamada!
.ENDIF
Mas podemos mudar isso:
MOV NATURAL,1
SUB NATURAL,3 ;NATURAL=-2
.IF NATURAL < -1
CALL FIM ;essa rotina SIM será chamada!
.ENDIF
No entanto se declaramos uma variável do tipo SBYTE nada disso ocorre:
MOV REAL,1
SUB REAL,3
.IF REAL < 0
CALL FIM ;AGORA SIM, funciona mesmo!!!
.ENDIF
Lembrando que tudo o que foi dito para SBYTE é válido para SWORD.
E agora falemos finalmente do IMUL.
Sua sintaxe é a mesma da instrução MUL:
AX = AL * operando
Onde o operando pode ser um número sinalizado.
Mas o que acontece quando ultrapassa-se os limites ? Para valores maiores que 65535, o IMUL comporta-se da mesma forma que o MUL, tanto para valores positivos quanto negativos.