asm 2个32位数相乘=一个64位数

时间:2022-10-30 03:34:22
TITLE multiplication
comment !

This is two dword number make multiplication , and finally get a qword number

中文解释:就是输入两个32位(十进制)有符号数(-21474836482147483647)[经计算器检验结果完全正确]
"输出表达式"在 CMD 下,我均采用了十六进制,
例:2147483647(十进制)*2147483647(十进制)=3FFFFFFF00000001(十六进制)
2147483647(十进制)*(-2147483647)(十进制)=c00000008000000(十六进制)

解题思路:①先将输入的两个有符号数的最高位取出进行(异或)判断,确定结果符号。
②将输入的有符号数进行处理(neg)处理,全转化为正数(归一法)
③将乘数右移移位,取出当前最低位,(然后你懂的),循环到乘数等于0
④若相乘后的结果还是32位数,就输出十进制数
⑤若先前的出的结果符号为负,就将64位数(减1取not)

!
include irvine32.inc

.data
value1 dword 0
temp1 dword 0 ;正数
value2 dword 0
temp2 dword 0 ;正数
result qword 0
resultTemp qword 0
sign0 byte 0 ;0表示正数,1表示负数(存放结果符号)
sign1 byte 0
strTitle byte "TITLE:两32位(有符号)二进制数相乘得到一个64位二进制数",0
str1 byte "请输入被乘数(带符号十进制):",0
str2 byte "请输入乘数(带符号十进制):",0
str3 byte "结果为:(十六进制,括号内为十进制数)",0

.code
;==============
getValue proc;读入两有符号数(若输入溢出会提示)
mov edx,offset strTitle
call writestring
call crlf
mov edx,offset str1
call writestring
call crlf
call readint
mov value1,eax
mov temp1,eax
mov edx,offset str2
call writestring
call crlf
call readint
mov value2,eax
mov temp2,eax
ret
getValue endp
;==============
getSign proc;先计算两数相乘后结果的符号(将两有符号数相乘化简为无符号数相乘)
mov eax,value1
shl eax,1
jnc NEXT1_1
mov al,1
mov sign0,al
neg temp1
NEXT1_1:
mov eax,value2
shl eax,1
jnc NEXT1_2
mov al,1
mov sign1,al
neg temp2
NEXT1_2:
mov al,sign1
xor sign0,al
mov eax,0
movzx eax,sign0
ret
getSign endp
;==============
calculate proc;计算两无符号数相乘的结果
mov eax,temp1
mov dword ptr resultTemp,eax
shr temp2,1
jnc BEGIN
mov edx,dword ptr resultTemp+4
mov eax,dword ptr resultTemp
add dword ptr result,eax
adc dword ptr result+4,edx
BEGIN:
;每次都要移动保存被乘数移位后的值
cmp temp2,0
jz OK
mov eax,dword ptr resultTemp+4
shl dword ptr resultTemp,1
jnc NEXT2_1
shl eax,1
inc eax
mov dword ptr resultTemp+4,eax
jmp NEXT2_3
NEXT2_1:
shl eax,1
mov dword ptr resultTemp+4,eax
NEXT2_3:
;进行比较乘数的二进制最低位是否为
shr temp2,1
jnc BEGIN
mov eax,dword ptr resultTemp
mov edx,dword ptr resultTemp+4
add dword ptr result,eax
adc dword ptr result+4,edx
jmp BEGIN
OK:
ret
calculate endp
;==============
makeResult proc;根据符号求最终结果
cmp sign0,0
jz NEXT3_1
mov eax,dword ptr result
mov edx,dword ptr result+4
cmp eax,0 ;若低位为0则要减高位(结果等0的情况已被讨论过)
jnz NEXT3_2
dec edx
NEXT3_2:
dec eax
not eax
not edx
mov dword ptr result,eax
mov dword ptr result+4,edx
NEXT3_1:
ret
makeResult endp
;==============
output proc;输出最终结果(小于32位的直接用十进制输出,方便检验)
mov edx,offset str3
call writestring
call crlf
mov eax,value1
call writeHex
mov al,"*"
call writechar

mov eax,value2
call writeHex
mov al,"="
call writechar

mov eax,dword ptr result+4
call writeHex
mov edx,eax
mov eax,dword ptr result
call writeHex

cmp edx,0 ;小于32位的正数(edx存的是结果的高位)
jnz NEXT4_1
mov al,'('
call writechar
mov al,'+'
call writechar
mov eax,dword ptr result
call writedec
mov al,')'
call writechar

NEXT4_1:
cmp sign0,0 ;小于32位正数也讨论过
jz NEXT4_2 ;将小于32位负数化为十进制
mov eax,dword ptr result+4
mov edx,dword ptr result
cmp edx,0
jnz NEXT4_3
dec eax
NEXT4_3:
dec edx
not edx
not eax
cmp eax,0
jnz NEXT4_2
shl edx,1
jc NEXT4_2
shr edx,1
mov al,'('
call writechar
mov al,'-'
call writechar
mov eax,edx
call writedec
mov al,')'
call writechar
NEXT4_2:
call crlf
call readchar
ret
output endp
;==============
main proc
call getValue
;若两数有一个是0则结果也是0
cmp temp1,0
jz NEXT3_1
cmp temp2,0
jz NEXT3_1
;============
call getSign
call calculate
call makeResult
NEXT3_1:
call output
exit
main endp
end main