看着个别位

时间:2013-02-05 18:42:21

标签: assembly mips

在MIPS汇编中,是否可以仅提取字符串的第i和第j位,然后将这些单独的位放回原始位置。

考虑: 1100

提取:第二第三位并交换它们以获得结果 1010

2 个答案:

答案 0 :(得分:2)

查看AND真值表结果r = a AND b

ab r
00 0
01 0
10 0
11 1

看看这两种情况:

10 0
11 1

任何ANDed与1本身,现在这两个案例

00 0
01 0

任何与零相关的ANDed都为零。

用四位abcd提取c位,知道anding的这两个特征,任何一个零和任何一个anded的东西。

    abcd
AND 0010
=========
    00c0

我们已经隔离了位c,我们不关心它是零还是一位我们已经隔离了它。 用零填充的位被强制为零,以1为单位的位未改变。

同样和0100的abcd给我们0b00隔离位b。

所以现在我们有两个中间结果0b00和00c0。你想换掉他们的位置,移位就会这样做,这取决于你的指令集(我知道你说的是mips但只是请关注)一些指令集可能会在进位中旋转或移位而有些指令可能会旋转或移位为零或算术移位vs逻辑移位可以复制最高有效位而不是零移位。因此,您需要检查您正在使用的指令集中可用的移位,如果零解决方案中没有干净的移位,那么您需要添加更多操作来清除移位的任何副作用。在这种情况下,我们希望将b位向右移动一位,将c位向左移动一位,这样您需要查找和使用的操作是

0b00 >> 1 = 00b0
00c0 << 1 = 0c00

现在这些位在正确的位置我们有三件事

abcd
0c00
00b0

所以我们要检查两个真值表,一个是上面的AND真值表,我们知道任何与一个相关的东西,任何一个零的东西。另一个是OR真值表

ab r
00 0
01 1
10 1
11 1

特别是前两个

00 0
01 1

任何与零相关的OR本身。并注意第二个

10 1
11 1

任何与1的ORed为1。

我们如何使用AND和OR来获取位?好吧,我们有两个选择ORed与零本身,另一个是任何ANDed与1本身。我们需要做的是操纵原始数字abcd并使其成为a00d或a11d。这会调用AND和OR表的另一半。任何与0相关的东西都是0,任何与1相关的东西都是1.所以要将abcd变为a00d我们需要和它一起使用1001

    abcd
AND 1001
=========
    a00d

a和d与一个本身是b和c与0是0

另一个选择是

    abcd
OR  0110
=========
    a11d

a和d的值为0,因此它们不会改变b和c与1进行比较,因此这些位置变为1

最后一步是获取我们的其他中间值并将它们混合在

    a00d
OR  0c00
=========  
    ac0d

    ac0d
OR  00b0
=========  
    acbd

另一种选择更复杂,如果我们只是这样做

    a11d
AND 0c00
========
    0c00

为了使用该身份,我们需要修改0c00并将其设为1c11

0c00 OR 1011 = 1c11
1c11 AND a11d = ac1d
00b0 OR 1101 = 11b1
11b1 AND ac1d = acbd

简而言之,传统的解决方案是与之隔离,并使用零来清除位位置然后或在新值中:

abcd AND 0100 = 0b00
abcd AND 0010 = 00c0
0b00 >> 1 = 00b0
00c0 << 1 = 0c00
abcd AND 1001 = a00d
a00d OR 0c00 = ac0d
ac0d OR 00b0 = acbd

在C中,这将是这样的(这显示了你的临时变量)

//abcd is our original variable
tempb = abcd & 4;
tempc = abcd & 2;
tempb = tempb >> 1;
tempc = tempc << 1;
result = abcd & 9; 
result = result | tempc;
result = result | tempb;
//and finished, result contains the...result.

你已经从gusbro得到了一个完整的答案,这是答案的一半,我认为使用逻辑运算的任务是问题的一半,问题的另一半是选择有问题的指令集的指令和寄存器(注意我到目前为止如何解决问题而不需要指定一个指令集,因为此时我们可以使用任何指令集,每步可能需要多个指令,但这一点是通用的。)

注意这是一个四位解决方案,您可能会在寄存器中使用一个超过四位的指令集,因此您需要知道这些方程式中操作数左侧的哪些位要加以解决其他位。

gusbro使用的另一个我没有的身份,与其本身的异或是零。他的两个xor操作可以使用单个和带有常量的操作来实现,具体取决于可能需要多个指令或需要额外内存周期的指令集。

这类工作的关键是理解这些逻辑身份并应用它们。当有人说(掩码和移位)掩码意味着和一个常量在你想要保留的位位置时,然后移位将该位置于特定位置,例如你想取abcd并将c位隔离这样一种方式,结果是零或一个你将“掩盖和转移”

abcd AND 0010 = 00c0
00c0 >> 1 = 000c

和是掩码,移位是移位,如果c为0则结果为0,如果c为1则结果为1。

同样你可以

abcd >> 1 = 0abc
0abc AND 0001 = 000c

转移然后掩码。

您的家庭作业可以重新安排为

abcd >> 1 = 0abc
abcd << 1 = bcd0
0abc AND 0010 = 00b0
bcd0 AND 0100 = 0c00
abcd AND 1001 = a00d
00b0 OR 0c00 = 0cb0
a00d OR 0cb0 = acbd

您可以开始查看主题的其他变体。这些变化可以根据您所针对的指令集变为优化。

答案 1 :(得分:1)

您可以通过应用蒙版和班次来实现。 假设您的数据存储在寄存器中,要获得第i位,您将应用带有常数2 ^ i的AND来清除除第i位之外的所有位。 然后你就可以轻松地移动&#34;使用左移或右移位到其他位置。

现在,交换2位需要更多的摆弄。例如,您可以将两位提取到某些寄存器,从原始寄存器中清除这些位,然后将两个寄存器中的每一个移位以在&#34;交换&#34;中找到它们。位置,最后还是一切。

E.g:

  li $t0, 12         # Our constant, 1100b, is stored in $t0
  andi $t1, $t0, 2   # Mask the second bit and put it in $t1
  andi $t2, $t0, 4   # Mask the third bit and put it in $t2
  xor $t0, $t0, $t1  # Ensures the second bit $t0 is zero 
  xor $t0, $t0, $t2  # Ensures the third bit $t0 is zero 
  sll $t1, $t1, 1    # Moves $t1 one position to the left (second bit goes to third bit)
  srl $t2, $t2, 1    # Moves $t2 one position to the right (third bit goes to second bit)
  or $t1, $t1, $t2   # now we OR everything
  or $t0, $t0, $t1   # to get the final result, in this case 1010b