我想用8086汇编语言制作一个64位整数计算器,它具有以下功能:加,减,除,乘。
它应该提供一个菜单,这样如果我们按1
,它会增加,如果我们按2
,它会减少等。我们可以给予64位的输入值。
问题是我们在编程时只能使用16位寄存器/内存,所以问题是我们如何使用16位寄存器并在控制台窗口中给予64位输入值。
我正在使用KIP.R.IRVINE汇编链接库。
我们必须以这样的方式编码它,它使用16位寄存器/操作数来实现每个功能,如加法,减法,除法和乘法。16 + 16 + 16 + 16 = 64
我是新的汇编语言,如果任何人可以帮助我,使只有1个功能(+,-,/,x)的计算器,我可以使它的其余部分。
2条答案
按热度按时间ycl3bljg1#
这个问题与汇编语言没有什么关系,或者至少是最大的问题。你应该用C或任何你喜欢的语言来制作原型,然后简单地将其转换为另一种语言(在这种情况下是汇编)。
如果你还记得在小学的时候如果我们想加999 + 1
我们会有很多“挑一个”的活动
现在,在小学里可能没有定义的是“携带”和“携带”。把1进位到下一列的就是进位输出。当你把结转到当前列的那个数加起来,那么这个数现在就被称为进位,对于这一列。
B是进位输入,a是进位输出,操作数是c和d。e是该列的结果。我们在小学的时候确实学过,我们可以把无限大的数字加起来,因为我们只需要学会一次加一列,然后无限地重复。请注意,原来的问题上面的进位在第一列是空白的,它是一个隐含的零。0加9加1等于“0进位1”,0是9+1的结果,1是进位。
所以现在做999 + 1,但人为地限制我们一次只能添加两列,也许我们的纸只够两个数字,谁知道呢(处理器的寄存器有固定的宽度限制,在你的情况下是16位,或16列宽)。
我们知道答案会是这样的四列
一次两列
首先执行最低有效列,其中零用于进位。那么无论该使用的结果是什么,作为进入下两列的进位,我们可以对无限大的数字无限地重复这个过程。
在汇编语言中,你经常(但并不总是)有一些风格的ADD和ADC指令,不带进位的加法和带进位的加法,正常的加法有一个隐含的零进位,理想情况下有一个进位输出到某个处理器状态寄存器中的进位标志。然后如果有一个带进位的加法指令,你用带进位的加法来做其余的高阶加法,带进位的加法使用进位标志作为进位输入,并把进位输出放在进位标志中,所以你可以级联加法。
清澈如泥
减法,在计算机中没有真实的的减法,你在初级编程课上学到的疯狂的二进制补码是有原因的。用二进制补码求一个数的反就是“反相加1”。现在想想我们的加法运算,一个加法加两个数字,并带有一个进位。如果你要反转第二个操作数,然后在进位中放一个1呢?也就是“反转并加1”,对吧?如果我想做数学5 - 1,它和5 +(-1)是一样的,它和5 + inverse(1)+ 1是一样的,对吗?完全符合ADD逻辑。
不同的指令集利用用于减法运算的进位输出位做不同的事情,基本上在进入加法器的途中,减法装置反转第二操作数并反转进位输入,然后进行正常的加法,在输出途中,虽然如果运算是减法,一些处理器系列反转进位输出位,但是一些不反转进位输出位。你可能需要也可能不需要弄清楚这一点,这取决于你在操作后对进位位做了什么(条件分支,例如如果进位设置则跳转,如果进位未设置则跳转),在这种情况下,如另一张海报所示,一些指令集有一个带借用的减法。就像add then一系列addc操作级联一个无限大的加法一样,你可以使用sub和sbb级联一个无限大的减法。
乘...幸运的是,8086使这变得容易一点,但整体属性是相同的任何地方。如果你看数字(二进制),如果你乘以两个x位宽的数字,结果理想地需要是2*x宽,所以要正确地乘以任何两个16位数字,你需要一个32位的结果。如果您硬件只能执行16位 * 16位= 16位,那么为了轻松地级联乘法器,将高8位归零,并假装执行8位 * 8位= 16位...
小学
我们最后得到了四个数字加在一起,对吗?我用hhhh表示abcdh,gggg表示abcdg,等等。
当我们做两列乘法时
它被分解成四个倍增步骤
其中使用数学属性是
以10为基数乘以10只是移动一列,乘以100是两列,所有这些项加起来。因此,如果你把乘法操作数分解成可消化的片段,并记录下你需要移动每个项目的量,这基本上是把那个项目放在特定的列中,使用我们的无限宽加法,我们已经把东西分解成列或列组。是的,它变成了一个迭代过程,如上所述,我们有四个东西要加,我们的级联加法只加了两个东西,所以你必须做3个宽加法,1)前两个操作数,2)1)的结果加上第三个操作数3)2)的结果加上最后一个操作数
假设这些字母中的每一个都是16位数
上面唯一一个没有16的倍数移位的乘法对是hd(想想十进制中的10或100或1000的乘法)。
因此结果的低16位是hd的低16位。但是必须将hd的高16位添加到其它填充中
下一层是hc ≤ 16和gd ≤ 16。将这些中的每一个的低16位加在一起,并且还将其加到DH的高16位。用两个字母的组合来表示它们的相乘结果
换句话说,abcd * efgh =
将上面表示为hd的hd的低16位加到零上,并直接进入结果,将hd的上半部分与hc和gd的下半部分相加,以成为结果的下一个16位,等等。
如果你想使用1616=32位乘法运算和1616=16+进位加法运算来乘两个64位数,你可以基于上面的内容进行硬编码。
如果您想将结果限制为6464= 64位而不是6464= 128位,则可以将其减半
我会离开组织让你自己想办法。。
首先用高级语言实现基本的加、减运算,合成进位位
生成添加函数
以及具有进位功能加法器
或者如果你想像硬件一样只做带进位功能的加法,并且对于加法步骤,输入0表示进位,否则输入进位。
清澈如泥
x86可以例如在减法上反转进位,并且可能ARM不反转进位。有些处理器根本没有标志(mips),你必须使用小于寄存器大小的数字(使用32位寄存器来做16位加法,允许一个地方保存第17位,进位,或者一次做31位,无论如何)来合成所有上述内容。就像一些处理器一样,你必须在输入上使用乘法的一半大小(上半部分为零)来获得结果的未裁剪答案,并执行上述游戏来正确地执行全宽度乘法。
dm7nw8vv2#
要使用16位寄存器减去2个64位值,需要:
使用MASM语法的较短版本:
如果我们用
inc bx
inc bx
替换lea bx, [bx+2]
,仍然会少1个字节。