如何从寄存器中提取位的值并使用它们来替换不同寄存器中的位? (MIP汇编语言)

时间:2016-09-25 06:41:46

标签: mips mips32

我需要从寄存器$ t0中将位22中的值提取到4,计算该值的一半(假设无符号整数),并使用新值将寄存器$ t1中的位24替换为6而不更改$ t1中的其他位。价值没有给出但我不认为这应该是一个问题。每个寄存器有32位

我对MIP有点新意,所以我不确定如何解决这个问题

1 个答案:

答案 0 :(得分:0)

我已经分解了算法的各个步骤。然后我创建了一个C原型/测试程序。最后,我创建了一个mips asm程序。

这些是我为你[或其他任何人]推荐的步骤,特别是在开始使用时。

首先在C中编写代码[或者至少使用类似C的伪代码对其进行原型设计],可以更轻松地调试算法

从C程序中,我能够为mips程序创建测试数据。测试数据包括C程序获得的解决方案。

mips程序会将此视为通过/失败诊断。这似乎有点矫枉过正,但在asm程序的第一个版本中,有一个错误。我在srlv指令的第三个参数中使用了错误的寄存器,诊断实际上未通过测试(例如,我使用$t0代替$t1 )。

<强>术语:

这是术语的匹配:

xval:   $t0
xhi:    22
xlo:    4

yval:   $t1
yhi:    24
ylo:    6

提取步骤(1):

给定值xval,每当您看到&#34; 提取xhixlo&#34;时,首先要做的是xval右移xlo

xshf = xval >> xlo

但现在,xshf仍然位于xhi左侧的位,因此我们需要屏蔽它们。

<强>公式:

&#34;包含&#34;的位宽位范围是:

wid = (hi - lo) + 1

所以,&#34;右对齐&#34;面具是:

rmsk = (0xFFFFFFFF >> (32 - wid))

&#34;左对齐&#34;面具是:

lmsk = (rmsk << lo)

注意:上述方程式动态[如上]。或者,如果我们有固定的数字,我们可以手动计算最终值以产生常数。

提取步骤(2):

因此,为了获得位范围的隔离值,我们现在应用掩码:

xshf &= xrmsk

这是问题的第一部分。我们已经隔离了必要的位,因此它们现在位于xshf的最右边位(即位(xwid-1)0)。

提取步骤(3):

以上是一般的比特提取。具体问题要求我们除以2:

xshf >>= 1

合并步骤(1):

问题的第二部分是我们必须将xshf应用于目标值yval

yval的范围不同:yhiylo。我们应用公式来获取yval的适当值。

我们必须清除yval中的旧位:

yval &= ~ylmsk

合并步骤(2):

我们需要对xshf做两件事:

  1. &#34;清理&#34; xshf以便{em>仅 yval中的正确位被修改
  2. xshf转移到与yval
  3. 合并的正确位置

    我们可以通过两种方式之一来实现这一目标。以下两个序列是等效的:

    xshf &= yrmsk
    xshf <<= ylo
    

    或者:

    xshf <<= ylo
    xshf &= ylmsk
    

    注意:因为特定问题中的 width 位是相同的,所以屏蔽步骤可以是已消除(即xshf已被xrmsk屏蔽,且与yrmsk相同。因此, 屏蔽步骤必填)。

    合并步骤(3):

    现在,我们合并了移位值:

    yval |= xshf
    

    那是 - 我们已经完成了......

    <强>原型:

    这里有一些结合了所有这些的C代码。

    由于位范围值已固定,因此掩码值预先计算。如果它们必须变化,则掩码代码必须在每次合并调用时重新计算它们。

    另请注意,蒙版是常量,因为范围是固定的。

    #include <stdio.h>
    #include <stdlib.h>
    
    int opt_v;
    
    typedef unsigned int u32;
    
    u32 xval;
    #define XHI     22
    #define XLO     4
    
    u32 yval;
    #define YHI     24
    #define YLO     6
    
    u32 xrmsk;
    u32 xlmsk;
    u32 yrmsk;
    u32 ylmsk;
    
    #define WID(_hi,_lo)    (((_hi) - (_lo)) + 1)
    #define RMSK(_hi,_lo)   (0xFFFFFFFF >> (32 - WID(_hi,_lo)))
    #define LMSK(_hi,_lo)   (RMSK(_hi,_lo) << (_lo))
    
    #define SHOW(_sym) \
        show(_sym,#_sym)
    
    #define SHOWX(_sym) \
        if (opt_v) \
            SHOW(_sym)
    
    void
    show(u32 val,const char *sym)
    {
        u32 bitmsk;
        u32 bitval;
    
        printf("%8.8X ",val);
    
        for (bitmsk = 1u << 31;  bitmsk != 0;  bitmsk >>= 1) {
            bitval = val & bitmsk;
            printf("%d",bitval ? 1 : 0);
        }
    
        printf(" %s\n",sym);
    }
    
    void
    merge(void)
    {
        u32 xshf;
    
        SHOW(xval);
        SHOW(yval);
    
        // extract (1):
        xshf = xval >> XLO;
        SHOW(xshf);
    
        // extract (2):
        SHOWX(xrmsk);
        xshf &= xrmsk;
        SHOW(xshf);
    
        // extract (3):
        xshf >>= 1;
        SHOW(xshf);
    
        // merge (1):
        SHOWX(yrmsk);
        SHOWX(ylmsk);
        yval &= ~ylmsk;
        SHOW(yval);
    
        // merge (2):
        xshf &= yrmsk;  // belt and ...
        SHOW(xshf);
        xshf <<= YLO;
        SHOW(xshf);
        xshf &= ylmsk;  // ... suspenders
        SHOW(xshf);
    
        // merge (3)
        yval |= xshf;
        SHOW(yval);
    }
    
    void
    test(u32 y,u32 x)
    {
    
        printf("\n");
        yval = y;
        xval = x;
        merge();
    }
    
    // main -- main program
    int
    main(int argc,char **argv)
    {
        char *cp;
    
        --argc;
        ++argv;
    
        for (;  argc > 0;  --argc, ++argv) {
            cp = *argv;
            if (*cp != '-')
                break;
    
            switch (cp[1]) {
            case 'v':
                opt_v = ! opt_v;
                break;
    
            default:
                break;
            }
        }
    
        xrmsk = RMSK(XHI,XLO);
        SHOW(xrmsk);
    
        xlmsk = LMSK(XHI,XLO);
        SHOW(xlmsk);
    
        yrmsk = RMSK(YHI,YLO);
        SHOW(yrmsk);
    
        ylmsk = LMSK(YHI,YLO);
        SHOW(ylmsk);
    
        test(0,~0);
        test(~0,0);
    
        for (int idx = 0;  idx <= 5;  ++idx)
            test(rand(),rand());
    
        return 0;
    }
    

    <强>输出:

    0007FFFF 00000000000001111111111111111111 xrmsk
    007FFFF0 00000000011111111111111111110000 xlmsk
    0007FFFF 00000000000001111111111111111111 yrmsk
    01FFFFC0 00000001111111111111111111000000 ylmsk
    
    FFFFFFFF 11111111111111111111111111111111 xval
    00000000 00000000000000000000000000000000 yval
    0FFFFFFF 00001111111111111111111111111111 xshf
    0007FFFF 00000000000001111111111111111111 xshf
    0003FFFF 00000000000000111111111111111111 xshf
    00000000 00000000000000000000000000000000 yval
    0003FFFF 00000000000000111111111111111111 xshf
    00FFFFC0 00000000111111111111111111000000 xshf
    00FFFFC0 00000000111111111111111111000000 xshf
    00FFFFC0 00000000111111111111111111000000 yval
    
    00000000 00000000000000000000000000000000 xval
    FFFFFFFF 11111111111111111111111111111111 yval
    00000000 00000000000000000000000000000000 xshf
    00000000 00000000000000000000000000000000 xshf
    00000000 00000000000000000000000000000000 xshf
    FE00003F 11111110000000000000000000111111 yval
    00000000 00000000000000000000000000000000 xshf
    00000000 00000000000000000000000000000000 xshf
    00000000 00000000000000000000000000000000 xshf
    FE00003F 11111110000000000000000000111111 yval
    
    6B8B4567 01101011100010110100010101100111 xval
    327B23C6 00110010011110110010001111000110 yval
    06B8B456 00000110101110001011010001010110 xshf
    0000B456 00000000000000001011010001010110 xshf
    00005A2B 00000000000000000101101000101011 xshf
    32000006 00110010000000000000000000000110 yval
    00005A2B 00000000000000000101101000101011 xshf
    00168AC0 00000000000101101000101011000000 xshf
    00168AC0 00000000000101101000101011000000 xshf
    32168AC6 00110010000101101000101011000110 yval
    
    643C9869 01100100001111001001100001101001 xval
    66334873 01100110001100110100100001110011 yval
    0643C986 00000110010000111100100110000110 xshf
    0003C986 00000000000000111100100110000110 xshf
    0001E4C3 00000000000000011110010011000011 xshf
    66000033 01100110000000000000000000110011 yval
    0001E4C3 00000000000000011110010011000011 xshf
    007930C0 00000000011110010011000011000000 xshf
    007930C0 00000000011110010011000011000000 xshf
    667930F3 01100110011110010011000011110011 yval
    
    74B0DC51 01110100101100001101110001010001 xval
    19495CFF 00011001010010010101110011111111 yval
    074B0DC5 00000111010010110000110111000101 xshf
    00030DC5 00000000000000110000110111000101 xshf
    000186E2 00000000000000011000011011100010 xshf
    1800003F 00011000000000000000000000111111 yval
    000186E2 00000000000000011000011011100010 xshf
    0061B880 00000000011000011011100010000000 xshf
    0061B880 00000000011000011011100010000000 xshf
    1861B8BF 00011000011000011011100010111111 yval
    
    2AE8944A 00101010111010001001010001001010 xval
    625558EC 01100010010101010101100011101100 yval
    02AE8944 00000010101011101000100101000100 xshf
    00068944 00000000000001101000100101000100 xshf
    000344A2 00000000000000110100010010100010 xshf
    6200002C 01100010000000000000000000101100 yval
    000344A2 00000000000000110100010010100010 xshf
    00D12880 00000000110100010010100010000000 xshf
    00D12880 00000000110100010010100010000000 xshf
    62D128AC 01100010110100010010100010101100 yval
    
    238E1F29 00100011100011100001111100101001 xval
    46E87CCD 01000110111010000111110011001101 yval
    0238E1F2 00000010001110001110000111110010 xshf
    0000E1F2 00000000000000001110000111110010 xshf
    000070F9 00000000000000000111000011111001 xshf
    4600000D 01000110000000000000000000001101 yval
    000070F9 00000000000000000111000011111001 xshf
    001C3E40 00000000000111000011111001000000 xshf
    001C3E40 00000000000111000011111001000000 xshf
    461C3E4D 01000110000111000011111001001101 yval
    
    3D1B58BA 00111101000110110101100010111010 xval
    507ED7AB 01010000011111101101011110101011 yval
    03D1B58B 00000011110100011011010110001011 xshf
    0001B58B 00000000000000011011010110001011 xshf
    0000DAC5 00000000000000001101101011000101 xshf
    5000002B 01010000000000000000000000101011 yval
    0000DAC5 00000000000000001101101011000101 xshf
    0036B140 00000000001101101011000101000000 xshf
    0036B140 00000000001101101011000101000000 xshf
    5036B16B 01010000001101101011000101101011 yval
    

    MIPS计划:

    这是为mars模拟器设置的。特别是,以{十六进制打印值的syscall 34仅存在mars中的spim 中。spim。因此,要么获取火星:http://courses.missouristate.edu/KenVollmar/mars/或[使用 # these work for the mars simulator .eqv XHI 22 .eqv XLO 4 .eqv YHI 24 .eqv YLO 6 # these work for the spim simulator ###XHI = 22 ###XLO = 4 ###YHI = 24 ###YLO = 6 .data testdata: .word 0xFFFFFFFF,0x00000000,0x00FFFFC0 .word 0x00000000,0xFFFFFFFF,0xFE00003F .word 0x6B8B4567,0x327B23C6,0x32168AC6 .word 0x643C9869,0x66334873,0x667930F3 .word 0x74B0DC51,0x19495CFF,0x1861B8BF .word 0x2AE8944A,0x625558EC,0x62D128AC .word 0x238E1F29,0x46E87CCD,0x461C3E4D .word 0x3D1B58BA,0x507ED7AB,0x5036B16B edata: msg_nl: .asciiz "\n" msg_xrmsk: .asciiz "xrmsk " msg_xlmsk: .asciiz "xlmsk " msg_yrmsk: .asciiz "yrmsk " msg_ylmsk: .asciiz "ylmsk " msg_xval: .asciiz "xval " msg_yval: .asciiz "yval " msg_pass: .asciiz "pass " msg_fail: .asciiz "FAIL " msg_ans: .asciiz "answ " .text .globl main main: jal setup2 la $s6,testdata la $s7,edata main_loop: jal test addiu $s6,$s6,12 blt $s6,$s7,main_loop li $v0,10 syscall # test -- test the merge test: subu $sp,$sp,4 sw $ra,0($sp) li $v0,4 la $a0,msg_nl syscall lw $t0,0($s6) # get source value lw $t1,4($s6) # get destination value lw $t2,8($s6) # get solution value # print the X value la $a0,msg_xval move $a1,$t0 jal print # print the Y value la $a0,msg_yval move $a1,$t1 jal print # do the operation jal merge bne $t1,$t2,test_fail la $a0,msg_pass move $a1,$t1 jal print j test_done test_fail: la $a0,msg_fail move $a1,$t1 jal print # print the result la $a0,msg_ans move $a1,$t2 jal print test_done: lw $ra,0($sp) addu $sp,$sp,4 jr $ra # print -- print number # # arguments: # a0 -- string # a1 -- value print: # output the string li $v0,4 syscall li $v0,34 # syscall print hex move $a0,$a1 syscall li $v0,4 la $a0,msg_nl syscall jr $ra # merge -- merge the data # # arguments: # t0 -- source value # t1 -- target value # # registers: # t7 -- xshf # t6 -- ~ylmsk merge: srl $t7,$t0,XLO # E1: xshf = xval >> xlo and $t7,$t7,$s0 # E2: xshf &= xrmsk srl $t7,$t7,1 # E3: xshf >>= 1 not $t6,$s3 # M1: get ~ylmsk and $t1,$t1,$t6 # M1: yval &= ~ylmsk sll $t7,$t7,YLO # M2: xshf <<= ylo and $t7,$t7,$s3 # M2: xshf &= ylmsk or $t1,$t1,$t7 # M3: yval |= xshf jr $ra # return # setup2 -- set up the mask values # # RETURNS: # s0 -- xrmsk # s1 -- xlmsk # s2 -- yrmsk # s3 -- ylmsk # # registers: # a0 -- hi bit value # a1 -- lo bit value setup2: subu $sp,$sp,4 sw $ra,0($sp) # set up the xval masks li $a0,XHI li $a1,XLO jal setup1 move $s0,$v0 move $s1,$v1 la $a0,msg_xrmsk move $a1,$s0 jal print la $a0,msg_xlmsk move $a1,$s1 jal print # set up the yval masks li $a0,YHI li $a1,YLO jal setup1 move $s2,$v0 move $s3,$v1 la $a0,msg_yrmsk move $a1,$s2 jal print la $a0,msg_ylmsk move $a1,$s3 jal print lw $ra,0($sp) addu $sp,$sp,4 jr $ra # return # setup1 -- set up the mask values # # RETURNS: # v0 -- rmsk # v1 -- lmsk # # arguments: # a0 -- hi bit value # a1 -- lo bit value # # registers: # t0 -- wid # t1 -- 32 - wid setup1: sub $t0,$a0,$a1 # wid = hi - lo addi $t0,$t0,1 # wid += 1 li $v0,0xFFFFFFFF # rmsk = 0xFFFFFFFF # get 32 - wid li $t1,32 sub $t1,$t1,$t0 srlv $v0,$v0,$t1 # rmsk >>= (32 - wid) sllv $v1,$v0,$a1 # lmsk = rmsk << lo jr $ra # return ]将34更改为1以十进制打印

    {{1}}