汇编程序中的低位?

时间:2013-10-01 19:55:52

标签: assembly

AND Arm9

主要问题是找到如何获得较低的32位和较高的32位。 我真的很感激任何帮助或提示,所以我可以继续做这个功课。

2 个答案:

答案 0 :(得分:1)

在这种情况下,你的问题几乎没有与编程语言有关,所以asm,C,Pascal,Python,它并不重要(除非你只对快捷方式感兴趣,否则它可能适用于高级语言)。 / p>

所以,回到小学数学。乘以两个数字:

  12
* 34
====
   8  (4*2)
  40  (4*10)
  60  (30*2)
+300  (30*10)
====
 408

但是如果我们的计算机对它可以操作的位数(位数)有限制怎么办?例如,如果我们的硬件可以在计算器或头脑中快速地将两个8位数相乘,则0xFF是最大的无符号数,它自身为0xFF * 0xFF = 0xFE01,只是为了检查是否存在符号问题。计算器255 * 255 = 65025 = 0xFE01。如果您没有看到模式,则有两个以上,两位乘法,最大数字是3,3 * 3 = 9,0b11 * 0b11 = 0b1001。两位输入需要四位才能完全覆盖可能性,8位操作数需要16位结果才能完全覆盖这些可能性。如果我错了,请纠正我,但如果您的处理器完全相乘并且结果不是输入大小的两倍,那么您必须做什么?可以说你只能通过以下几种方式之一使用该硬件,如果有溢出标志则尝试相乘然后解决该问题(这个问题的全部目的是如何解决问题),否则你就可以了结果。因此,如果你有一个32位* 32位= 32位多个那么只有当你用作16位* 16位= 32位时才能确保输入的高位为零,或者如果你认为这个和我们意识到只要另一个数字少于16,就会有一个数字比16更重要。

所以使用我开头的十进制数字,但说明我们只能在乘法运算的输入上取一位数字,得到两位数的结果,我们只能在我们的加法中取两位数字并得到一个两位数的结果我们如何执行12 * 34?

简单地说,我们看看中间的东西

8(4 * 2)   40(4 * 10)   60(30 * 2) +300(30 * 10)

和/或我们做了一些基本的数学

12*34 = 
((1*10)+(2*1))*((3*10)+(4*1)) =
((1*10)*(3*10)) + ((1*10)*(4*1)) + ((2*1)*(3*10)) + ((2*1)*(4*1)) = 
((1*3)*(10*10)) * ((1*4)*(10*1)) + ((2*3)*(1*10)) + ((2*4)*(1*1)) 

如果你没有看到答案,请继续阅读。

如果每个数字都是变量abcd,那么代替十进制的12 * 34,我们将数字表示为ab * cd

ab*cd = 
((a*c)*(10*10)) + ((a*d)*(10*1)) + ((b*c)*(1*10)) + ((b*d)*(1*1)) 

还没看到呢?我们现在可以使用一位数,两位数的规则来执行单个数字a * c,a * d,b * c,b * d。乘以100或10或1只是转移。

((a*c)*(10*10))  = a*c * 100 = (a*c) << 2 
((a*d)*(10*1))   = a*d * 10  = (a*d) << 1 
((b*c)*(1*10))   = b*c * 10  = (b*c) << 1 
((b*d)*(1*1))    = b*d * 1   = (b*d) << 0

现在如果我们宣布这个而不是单个十进制数字,十六进制数字和我们的乘数可以在8位输出中做4位。我们的加法器可以8位输出8位。

((a*c)*(0x10*0x10))  = a*c * 0x100 = (a*c) << 8 
((a*d)*(0x10*0x1))   = a*d * 0x10  = (a*d) << 4 
((b*c)*(0x1*0x10))   = b*c * 0x10  = (b*c) << 4 
((b*d)*(0x1*0x1))    = b*d * 0x1   = (b*d) << 0

因此,如果我在这个系统中有两个8位数,我需要干净地将它们相乘,并且指令集必须提供的最好的是4位或8位输入乘法运算,其具有8位输出结果,并且是8位输入和8位输出。要将我的两个8位数字乘以jk * mn,其中j,k,m,n代表单个十六进制(四位)数字,然后

(temp0,1,2,3 ...是8位寄存器/变量)

temp0 = j * m temp1 = j * n temp2 = k * m temp3 = k * n

temp4 =((temp1&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&quot; 0xFF)+((temp2&lt;&lt;&lt;&lt;&lt;&lt;&quot;&quot; 如果设置了进位,则temp0 = temp0 + 1; temp4 = temp4 + temp3 如果设置了进位,则temp0 = temp0 + 1 temp0 = temp0 +(temp1&gt;&gt; 4) temp0 = temp9 +(temp2&gt;&gt; 4)

答案的高8位是temp0,即temp4中的低8位。

这可以扩展到任意数量的位,32位输入,32位输出。如果你想使用8位机器乘以1024位* 1024位= 2048位数,4位* 4位= 8位乘法和8位+ 8位= 8位加法器。然后你可以很容易地做到。

不必完成所有书面数学,只需这样做

      jk
    * mn
    ====
      nk  (n*k<<0)
     nj   (n*k<<1)
     mk   (m*k<<1)
   +mj    (m*k<<2)
    ====

如果有帮助,请用零填充

    00nk  
    0nj0  
    0mk0   
   +mj00    
    ====

然后将它们分开到加法器的宽度

    00  nk  
    0n  j0  
    0m  k0   
   +mj +00    
    ==  ==

简化一点

 nk  
 j0  
+k0   
=== 
lower half of answer

 0n 
 0m
 mj
+carry_out from lower half
====
upper half of answer

直接来自小学的三位数

    abc
  * def
========
     fc (fc = f times c)
    fb0 (fb = f times b)
   fa00
    ec0
   eb00
  ea000
   dc00   
  db000
+da0000
========

然后将添加操作可以消化的列添加到列中...这可以永久地扩展您希望以任何大小乘法操作的任何大小的数字,并添加您的处理器支持。如果你没有乘法运算,那么它仍然可以完全相同的方式工作,但乘数的一侧(你没有)的宽度为1。

现在使用比特:

    abcd
   *1011
=======
    abcd   (abcd * 0b0001)
   abcd0   (abcd * 0b0010)
  000000   (abcd * 0b0000)
+abcd000   (abcd * 0b1000) 
========

a,b,c,d现在是位,1011是4位数,二进制每个数字只能是1或0所以0次任何东西都是零,1次任何东西本身都是这样乘以一个数字当你没有乘法运算时,只是对一个操作数中的每个非零位都意味着你将另一个操作数移动该数量并将其添加到累积结果中。几乎任何处理器都没有快速但很容易实现,它同样可以无限扩展。

现在将所有这些应用于32位* 32位= 64位乘法,您需要在任何使用的处理器上保留结果的上半部分和下半部分。

答案 1 :(得分:0)

某些ARM处理器(不确定ARM 9)有32x32 - &gt; 64位乘法指令,名为“UMULL”(无符号数)或“SMULL”(带符号数)。

结果放在两个寄存器中;一个寄存器将包含低32位,另一个寄存器将包含高32位,因此您甚至不必将低位和高位分开!

如果您的处理器没有“UMULL”指令,您必须在答案中执行“dwelch”所写的内容。