汇编程序 - 1 (32位无符号乘法)
Posted andy-lcw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了汇编程序 - 1 (32位无符号乘法)相关的知识,希望对你有一定的参考价值。
这个是学校的课程设计《微机原理与接口技术》内容,自己写得有些缺陷,但基本实现了运算功能,暂且记录,方便日后回顾,也供大家参考。
缺陷:
1. 只能固定长度输入(32位对应为00000000 -- FFFFFFFF)
2. 例如输入6(16进制)只能类似输入00000006
3.只考虑了0-F中的0-9输入,也没考虑A-F或者a-f
暂时没空修改,以后有空或许会再写写
实验环境:
1.我是在虚拟机上的Windows 7 调试的,TD调试中显示的cpu是80486,但本次实验要求所用8086(16位),这个没影响,因为80486指令集的向前兼容,只要我们写的8086的指令就行。
说明这个的原因在于,80486已经有新的指令集了,直接可以进行32位运算。
2. ......没了 >==< !
设计思路:
输入:
输入时,因为调用INT 21(01H)进行输入,而该功能调用只能每次输入一个字符,且存入AL中的数据为其ASCII值,所以,首先要对输入的值进行转换成真实数据,同时加循环可以完成对固定长度数据的输入。
运算:
运算时,由于在16位寄存器的8086系统中,一次性只能对16位的数据进行运算,故当我们需要对其进行32位运算时,考虑分段进行,每次分段的结果数据(DX:AX)都放在内存相对应地址中(标号为HH、HL、LH、LL)。以32位长度的数据DX:AX两个数据相乘举例,数据分为高位(H)和低位(L),则分段相乘可以分为L-L,L-H,H-L,H-H相乘(L、H代表32位数据的高位数据和低位数据),其中每个相乘的值都放在DX:AX中。在L-L中,L-L->AX由于是乘积的最低位,且MUL指令无溢出情况,故无需考虑进位;在L-L->DX和L-H->AX和H-L->AX之和中,需要考虑向高位进位的情况,可以使用PUSHF将标志寄存器的状态入栈,在高位使用ADC指令即可;L-H->DX和H-L->DX和H-H->AX之和中,需要同时考虑向高位的进位和低位的进位值,处理方法同前;H-H->DX为乘积的最高位,只需考虑低位的进位。
输出:
输出时,要考虑运算后的数据和输出的数据,即运算后的数据为乘积的真值,而输出的数据是字符所对应的ASCII值。同时为了考虑美观性,前置的0考虑将其去除,加判断跳转语句可实现。具体实现是,先判断取出的BX是否为0,为0则代表该数据不用输出,程序跳转到执行下一个地址处理;当取出的数据可能存在开始数据为0100/0A11和非开始数据为0100/0A11的情况。即最开始的0是不用输出的,但是除了最开始的0不输出外,其他的0是真值,需要输出。考虑设计一个标志实现,本设计用SI实现,初始值为0H,当输出一个真值之后,将其值变为01H,之后同时判断SI和要输出的值,当输出值为0且SI为01H时,即该数据为真值,需要输出。
代码:
//mul.asm DATA SEGMENT BUF1 DB 0DH,0AH,‘PLEASE INPUT NUM_1(00000000-99999999):‘,0DH,0AH,‘$‘ BUF2 DB 0DH,0AH,‘PLEASE INPUT NUM_2(00000000-99999999):‘,0DH,0AH,‘$‘ BUF3 DB 0DH,0AH,‘THE RESULT IS:‘,0DH,0AH,‘$‘ ;做成任意输入的 NUM1 DW 2 DUP(?) NUM2 DW 2 DUP(?) HL DW 2 DUP(?) HH DW 2 DUP(?) LH DW 2 DUP(?) LL DW 2 DUP(?) SUM DW 4 DUP(?) DATA ENDS CODE SEGMENT MAIN PROC NEAR ASSUME CS:CODE,DS:DATA START: IN_TIPS: MOV BX,DATA MOV DS,BX IN_1: LEA DX,BUF1 MOV AH,09H INT 21H LEA BX,NUM1 CALL INPUT IN_2: LEA DX,BUF2 MOV AH,09H INT 21H LEA BX,NUM2 ;ADD BX,3 CALL INPUT ;TAKEMUL CALL TAKEMUL ;OUTPUT CALL OUTPUT ;END MOV AH,4CH INT 21H RET MAIN ENDP INPUT PROC NEAR MOV DX,2 INNUM: ;1(5)->Input Number MOV AH,01H INT 21H SUB AL,30H MOV CL,4 SHL AL,CL MOV CL,AL ;2(6)->Input Number MOV AH,01H INT 21H SUB AL,30H ADD CL,AL PUSH CX ;3(7)->Input Number MOV AH,01H INT 21H SUB AL,30H MOV CL,4 SHL AL,CL MOV CH,AL ;4(8)->Input Number MOV AH,01H INT 21H SUB AL,30H ADD CH,AL MOV AL,CH ;SEND To MEMORY POP CX MOV AH,CL MOV [BX],AX ADD BX,2 DEC DX JNZ INNUM RET INPUT ENDP TAKEMUL PROC NEAR LEA SI,NUM1 LEA DI,NUM2 H_L: ;<<16 MOV AX,[SI] ADD DI,2 MUL WORD PTR[DI] LEA BX,HL MOV [BX],DX ADD BX,2;WORD MOV [BX],AX ADD BX,2 H_H: ;<<32 MOV AX,[SI] SUB DI,2 MUL WORD PTR[DI] LEA BX,HH MOV [BX],DX ADD BX,2 MOV [BX],AX ADD BX,2 L_H: ;<<16 ADD SI,2 MOV AX,[SI] MUL WORD PTR[DI] LEA BX,LH MOV [BX],DX ADD BX,2 MOV [BX],AX ADD BX,2 L_L: ;<<0 MOV AX,[SI] ADD DI,2 MUL WORD PTR[DI] LEA BX,LL MOV [BX],DX ADD BX,2 MOV [BX],AX ADD BX,2 TAKE: ;L-L: ;LL->AX:32位X32位运算数据的最低位 LEA DI,LL ADD DI,2 MOV AX,[DI] LEA BX,SUM MOV [BX],AX ADD BX,2 ;LL->DX:LL->DX + LH->AX + HL->AX LEA DI,LL MOV AX,[DI] MOV [BX],AX ;ADD BX,2 ;HL+LH ;HL->AX+LH->AX LEA DI,HL ADD DI,2 MOV AX,[DI] LEA DI,LH ADD DI,2 ADD AX,[DI] PUSHF ADD AX,[BX];LL->DX MOV [BX],AX ADD BX,2 ;HL->DX+LH->DX (CF) LEA DI,HL MOV AX,[DI] LEA DI,LH POPF ADC AX,[DI] PUSHF MOV [BX],AX ;HH(CF) ;HH->AX LEA DI,HH ADD DI,2 MOV AX,[DI] POPF ADC AX,[BX];HL->DX+LH->DX MOV [BX],AX ADD BX,2 ;HH->DX LEA DI,HH MOV AX,[DI] ADC AX,0H MOV [BX],AX ADD BX,2 RET TAKEMUL ENDP OUTPUT PROC NEAR LEA DX,BUF3 MOV AH,09H INT 21H LEA DI,SUM ADD DI,7 MOV CX,8 MOV SI,0H;RE_COMPARE ADJUST: MOV BL,[DI] MOV BH,BL AND BX,0F00FH PUSH CX CMP BX,0H JE ZERO MOV CL,4 SHR BH,CL MOV DL,BH CALL COMPARE MOV DL,BL CALL COMPARE ZERO: DEC DI POP CX LOOP ADJUST RET OUTPUT ENDP COMPARE PROC NEAR CMP DL,0AH JAE OUT_ENG;JNB CMP DL,00H JE RE_COMPARE JA OUT_NUM JMP COMPARE_END RE_COMPARE: CMP SI,0H JE COMPARE_END JNE OUT_NUM OUT_ENG: ADD DL,37H;ACSII->A-0AH MOV AH,02H INT 21H MOV SI,01H JMP COMPARE_END OUT_NUM: ADD DL,30H MOV AH,02H INT 21H MOV SI,01H COMPARE_END: RET COMPARE ENDP CODE ENDS END START
由于分析中解释清楚了,加上代码命名相对比较见名知意,所以没注释(极少),之后会上传一个TD工具下的调试Blog,我觉得这个会更有用!!!
放两张截图吧 ~__~
说明:输入,输出都为16进制数,为什么是16进制?因为寄存器里面存的的就是16进制啊,我又不傻,直接输出就好,干嘛转换啊。哈哈哈哈哈哈@[email protected],机智!!!
验证说明:验证数据通过计算器得出结果。
验证1:12345678H * 12345678H = 14B 66DC 1DF4 D840H
验证2:99999999H * 99999999H = 5C28 F5C1 D70A 3D71H
验证3:6H * 6 H = 24H
嗯~ o(* ̄▽ ̄*)o,基本上就这样了!欢迎参考,如果你写了更完整的,欢迎留言提供链接。
以上是关于汇编程序 - 1 (32位无符号乘法)的主要内容,如果未能解决你的问题,请参考以下文章
是否可以在没有 bignums 的 JavaScript 中执行快速的 48 位无符号乘法?
如何在 x86(32 位)程序集中将无符号整数转换为浮点数?