汇编语言只用ADD指令实现整数和浮点数的加减乘法
![汇编语言只用ADD指令实现整数和浮点数的加减乘法](https://img.360docs.net/imgaa/1jvqb21v3bj8u67yqdzwa3a39ztyvm3r-a1.webp)
![汇编语言只用ADD指令实现整数和浮点数的加减乘法](https://img.360docs.net/imgaa/1jvqb21v3bj8u67yqdzwa3a39ztyvm3r-32.webp)
课程项目报告
一、要求:
利用汇编语言完成以下功能:
通过键盘输入二进制指令,对指令译码,完成相应的加、减和乘操作全过程。只能使用汇编的ADD指令,不能使用汇编已有的其他加法、加法和乘法指令。
*指令格式一为:
*
其中00为加法,01为减法,10为乘法
*指令格式二为:
*
其中当操作码为11,第二定点数全为0,第一定点数分别为000,001,010时,分别执行第一浮点数和第二浮点数的加、减和乘法操作,浮点数格式采用IEEE754标准。
二、程序流程:
1.通过中断输入要译码的二进制字符流;
2.选择其前8位合成1个数(如00101001就可合并为29H),先对其
进行要运算的判定。
通过依次移位将最左端的值放进CF位,判断其值为0或1跳转到相应的位置进行运算;
3.此程序显然有六种运算:
1)整数加法:最简单的一种,将两个操作数通过移位和设定寄存器的初值来获得,然后只需调用加法使两个寄存器相加即可,
将结果存入result内存单元中。并通过中断对结果进行输出到
屏幕的显示。
2)整数减法:取数和加法一致,但由于规定只能使用加法指令,因此必须先将减数的值进行求补(取反加1),再进行加法指令
即可,将结果存入result内存单元中。并通过中断对结果进行
输出到屏幕的显示。
3)整数乘法:利用硬件实现乘法的思想,通过判断第二个操作数的未判断的较低位决定是加被乘数还是加0的操作,然后将结
果右移,直到将操作数的所有位判断完毕(最后一位不移位),
将结果存入result内存单元中。并通过中断对结果进行输出到屏幕的显示。
4)浮点数加法:前面取了前8位归并后,将指针的位置保留下来,现在将其指针弹栈继续对剩下的输入的字符进行操作。首先调用子程序将剩下的输入字符流存入内存以待使用(将字符流转变成数值并组成一个完整的数字,即浮点数有三个数:1位的数符,8位的阶码,23位的数值)。此次运算严格按照浮点数的运算进行,即先对阶(阶码小的向阶码大的对齐)->取数运算(由于输入的是二进制字符流,因此在运算之前需根据数符对数值进行补码操作,而且由于有23位数值,通用寄存器只有16位,需调用两个寄存器来运算,注意低位是否有向高位的进位)->规格化,最后将阶码存到float_jie内存,数值运算结果存入result单元。并通过中断对阶码和数值进行输出显示。5)浮点数减法:及加法一样先调用中断将剩下的浮点数信息存入内存。及加法不同的是由于只能用加法指令,在操作的时候同样需先对第二个浮点数进行求补操作(取反加1),然后在进行及加法一样的操作,最后将阶码存到float_jie内存,数值运算结果存入result单元。并通过中断对阶码和数值进行输出显示。
6)浮点数乘法:及前面两个浮点数的操作一样先将剩下的浮点数信息存入内存。我们这里操作数均取得补码,因此用booth算法做乘法运算(通过移位取最低两位进行判断,如果相同则加
0,如果ynyn-1=10,则加【x】补,如果为ynyn-1=01,则加【-x】
补),通过23次的判断,进行加法操作和移位,最终得到结果,
将阶码存到float_jie内存,数值运算结果存入result单元。
并通过中断对阶码和数值进行输出显示。
三、在此给出部分运行结果:
1.整数加法
输入:
注意:指令P下面的二进制字符流严格按照要求的格式进行输入
输出:
注意:由于我在存储的时候将result内存设为了dd型,而我在存的时候存在了高位,在内存中是以大端格式存储,对于此题我们只用到了三位数的加法,显然可以看出最后结果为02(001+001),正确。
2.整数减法
输入:
输出:
这里和整数加法是一样的输出设置,因此结果为01(010-001),正确。
4.整数乘法
输入:
输出:
输出为1(001*001),结果正确。
5.浮点数加法:
注意:这里输入并未输入特别规范的移码表示其阶码的格式,这样输入比较简单,而且在两个阶码均正的情况下不会涉及到大小对阶时判断错误的情况。
输出:
注意:阶码为0(浮点数1和2的阶码均为0的结果)
注意:浮点数23位数值的计算结果为002,这里我将其设为十进制,但在用的时候还必须将其转变为二进制才可用,例如这个的最后结果应该为1.00000000000000000000010*2^0,可知结果正确。
附录:代码
data segment
user_string db 75,?,72 dup(?)
float1_sign db ?
float1_jie db ?
float1_figure dd ?
float1_figure_bu dd ?
float2_sign db ?
float2_jie db ?
float2_figure dd ?
float_jie db ?,'$'
result dd ?,'$'
;exitt dw "溢出$"
tempr dw ?
data ends
code segment
main proc far
assume ds:data,cs:code
start:mov ax,data
mov ds,ax
call inputBAndSelect8
push bx;将下一字符的地址放入堆栈 mov bh,ah;将输入的字符放到bh rol bx,1;取第一个操作码到cf
jnc INTEGER;CF=0
jc others;CF=1
INTEGER:
rol bx,1;取第二个操作码到cf
jnc INTEGERadd;CF=0
jc INTEGERsub;CF=1 INTEGERadd:
call INTEGER_ADD INTEGERsub:
call INTEGER_SUB
others:
rol bx,1;取第二个操作码到cf
jnc INTEGERmul;CF=0
jnz FLOAT;CF=1
INTEGERmul:
call INTEGER_MUL
FLOAT:
mov bl,0
mov cl,3
rol bx,cl;取第一个定点数放到bl mov ch,bl;转存到ch
mov bl,0
rol bx,cl;取第二个定点数放到bl mov cl,bl;转存到cl
and cx,cx
jz FLOATadd
test cx,10h
jz FLOATsub
test cx,20h
jz FLOATmul
FLOATadd:
call FLOAT_ADD
FLOATsub:
call FLOAT_SUB
FLOATmul:
call FLOAT_MUL
ret
main endp
;-----------------------------------------------------
;=================================================== ==
;INPUT BINARY STREAM(读入字符串,并取出前8个字符到ah 寄存器中,bx指向字符串的下一字符)
inputBAndSelect8 proc near
lea bx,user_string
mov ah,0ah
int 21h
mov ch,0
add bx,2;指向真正字符串开始的位置
mov ah,0
mov cl,8
add cl,255
beginin:
mov al,[bx]
add al,208;将字符串变为数值
mov [bx],al
add ah,al;将输入的字符串组成一个数
rol ah,1
add bx,1
loop beginin
mov al,[bx];最后一次不用移位
add al,208;将字符串变为数值
mov [bx],al
add ah,al;将输入的字符串组成一个数
add bx,1;指向下一个字符
ret
inputBAndSelect8 endp
;==================================================
;==================================================
;整数加法,bh中只有两个操作数,各三位,最后结果存放到result内存
INTEGER_ADD proc near
mov bl,0
mov cl,3
rol bx,cl;取第一个操作数放到bl
mov ch,bl;转存到ch
mov bl,0
rol bx,cl;取第二个操作数放到bl
mov cl,bl;转存到ch
add ch,cl;第一个操作数和第二个操作数做加法
mov result,ch
call DISPLAY_RESULT
ret
INTEGER_ADD endp
;==================================================
;==================================================
;整数减法,bh中只有两个操作数,各三位,最后结果存放到result内存
INTEGER_SUB proc near
mov bl,0
mov cl,3
rol bx,cl;取第一个操作数放到bl
mov ch,bl;转存到cl
mov bl,0
rol bx,cl;取第二个操作数放到bl
mov cl,bl;转存到ch
not cl;将第二个操作数取反
add cl,1;取反加1求补
add ch,cl;第一个操作数和第二个操作数的补相加
call DISPLAY_RESULT
ret
INTEGER_SUB endp
;==================================================
;=================================================== =
;整数乘法,bh中只有两个操作数,各三位,最后结果存放到result内存
INTEGER_MUL proc near
mov bl,0
mov cl,3
rol bx,cl;取第一个操作数放到bl
mov al,bl;转存到al
mov bl,0
rol bx,cl;取第二个操作数放到bl
mov dx,0;初始化结果为0
beginmu:
shr bx,1;判断最后一位是否为1
jc add1;CF=1
ror dx,1;将最后总和右移,为下一步做铺垫
loop beginmu
rol dx,cl;将最后的结果放到dh保存
mov result,dh;再移到result
call DISPLAY_RESULT
ret
add1:
add dh,al ;加第一操作数
ror dx,1;将最后总和右移,为下一步做铺垫
loop beginmu
mov cl,3
rol dx,cl;将最后的结果放到dh保存
mov result,dh;再移到result
call DISPLAY_RESULT
ret
INTEGER_MUL endp
;================================================== ;================================================== ;浮点数的加法,取相应的数据进行对阶-运算-右归操作FLOAT_ADD proc near
call SAVE_FLOAT_DATA
mov ch,float1_jie
mov cl,float2_jie
not ch
add ch,1
add cl,ch
cmp cl,0
jg DUI_JIE_a;第二个浮点数的阶码比较大 cmp cl,0
jz DUI_JIE2_a
not cl
add cl,1
cmp cl,0
jg DUI_JIE1_a
DUI_JIE_a:
mov ch,float2_jie
mov float_jie,ch
mov ax,float1_figure
mov bx,float1_figure+2
xor ch,ch
beginmove1_a:
shr bx,1
shr ax,1
jc adjust_a
loop beginmove1_a
mov cx,float2_figure mov dx,float2_figure+2 jmp d_add
adjust_a:
add bx,10h
loop beginmove1_a
mov cx,float2_figure mov dx,float2_figure+2 jmp d_add
DUI_JIE1_a:
mov ch,float1_jie
mov float_jie,ch
mov ax,float2_figure mov bx,float2_figure+2 xor ch,ch
beginmove2_a:
shr bx,1
shr ax,1
jc adjust1_a
loop beginmove2_a
mov cx,float1_figure mov dx,float1_figure+2
jmp d_add
adjust1_a:
add bx,10h
loop beginmove2_a
mov cx,float1_figure
mov dx,float1_figure+2
jmp d_add
DUI_JIE2_a:
mov ax,float1_jie
mov float_jie,ax
mov ax,float1_figure
mov bx,float1_figure+2
mov cx,float2_figure
mov dx,float2_figure+2
;--------------------------------------;将各个数变为补码
d_add:
mov ah,float1_sign
test ah,1
jz d_add1
mov ah,0
not ax
not bx
add bx,1
jnc d_add1
add ax,1
d_add1:
mov ch,float2_sign
test ch,1
jz d_add2
mov ch,0
not cx
not dx
add dx,1
jnc d_add2
add cx,1
;--------------------------------------;运算
d_add2:
add ax,cx
add bx,dx
jc adjust2_a
test ax,80h
jnz YOU_GUI_a
mov result,ax
mov result+2,bx
call DISPLAY_JIE call DISPLAY_RESULT
ret
adjust2_a:
add ax,1
test ax,80h
jnz YOU_GUI_a
mov result,ax
mov result+2,bx
call DISPLAY_JIE call DISPLAY_RESULT
ret
YOU_GUI_a:
shr bx,1
shr ax,1
jc adjust3_a
mov cx,float_jie add cx,1
cmp cx,0100h
jz exit_a
mov float_jie,cx
mov result,ax
mov result+2,bx
call DISPLAY_JIE
call DISPLAY_RESULT
ret
adjust3_a:
add bx,8000h
mov cx,float_jie
add cx,1
cmp cx,0100h
jz exit_a
mov float_jie,cx
mov result,ax
mov result+2,bx
call DISPLAY_JIE
call DISPLAY_RESULT
exit_a:
;call OVERFLOW
ret
FLOAT_ADD endp
;===================================================
;=================================================== ;将剩余数据存到相应内存
SAVE_FLOAT_DATA proc near
pop bx
;;;;;;;;;;;;将第一个浮点数的信息存入内存;;;;;;;;;;;;;;;;;;;
mov al,[bx]
add al,208
mov [bx],al
mov [float1_sign],al
inc bx
xor ch,ch
mov cl,7
mov ax,0
beginf1_jie:
mov al,[bx]
add al,208
mov [bx],al
add ah,al;将输入的字符串组成一个数
rol ah,1
add bx,1;指向下一个字符
loop beginf1_jie