Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 符号位移位_Assembly_Bit Manipulation - Fatal编程技术网

Assembly 符号位移位

Assembly 符号位移位,assembly,bit-manipulation,Assembly,Bit Manipulation,我正在尝试将十六进制转换为十进制,同时移动并保留符号。让我的'simm'变量正确反汇编签名指令时出现问题 void disassembleInstr(uint32_t pc, uint32_t instr) { uint32_t opcode; // opcode field uint32_t rs, rt, rd; // register specifiers uint32_t shamt; // shift amount (R-type)

我正在尝试将十六进制转换为十进制,同时移动并保留符号。让我的'simm'变量正确反汇编签名指令时出现问题

void disassembleInstr(uint32_t pc, uint32_t instr) {
    uint32_t opcode;      // opcode field
    uint32_t rs, rt, rd;  // register specifiers
    uint32_t shamt;       // shift amount (R-type)
    uint32_t funct;       // funct field (R-type)
    uint32_t uimm;        // unsigned version of immediate (I-type)
    int32_t simm;         // signed version of immediate (I-type)
    uint32_t addr;        // jump address offset field (J-type)

    opcode = instr >> 26;
    rs = (instr >> 21) & 0x1f;
    rt = (instr >> 16) & 0x1f;
    rd = (instr >> 11) & 0x1f;
    shamt = (instr >> 6) & 0x1f;
    funct = (instr & 0x3f);
    uimm = instr & 0xffff;
    simm = (instr << 16) >> 16; // shift sign bit to left to 
    addr = instr & 0x3ffffff; //masked with one

    cout << hex << setw(8) << pc << ": ";
    switch(opcode) {
        case 0x00:
        switch(funct) {
            case 0x00: cout << "sll " << regNames[rd] << ", " <<               regNames[rs] << ", " << dec << shamt; break;
            case 0x03: cout << "sra " << regNames[rd] << ", " << regNames[rs] << ", " << dec << shamt; break;
            case 0x08: cout << "jr " << regNames[rs]; break;
            case 0x10: cout <<  "mfhi " << regNames[rd]; break;
            case 0x12: cout << "mflo " << regNames[rd]; break;
            case 0x18: cout << "mult " << regNames[rs] << ", " << regNames[rt]; break;
            case 0x1a: cout << "div " << regNames[rs] << ", " << regNames[rt]; break;
            case 0x21: cout << " addu " << regNames[rd] << ", " << regNames[rs] << ", " << regNames[rt]; break;
            case 0x23: cout << " subu " << regNames[rd] << ", " << regNames[rs] << ", " << regNames[rt]; break;
            case 0x2a: cout << " slt " << regNames[rd] << ", " << regNames[rs] << ", " << regNames[rt]; break;
            default: cout << "unimplemented";
        }
        break;
        case 0x02: cout << "j " << hex << ((pc + 4) & 0xf0000000) + addr * 4; break;
        case 0x03: cout << "jal " << hex << ((pc + 4) & 0xf0000000) + addr * 4; break;
//        case 0x04: cout << "beq " << regNames[rs] << ", " << regNames[rt] << ", " <<  + uimm;   break;
//        case 0x05: cout << "bne " << regNames[rs] << ", " << regNames[rt] << ", " <<  + uimm;   break;
//        case 0x09: cout << "addiu " << regNames[rt] << ", " << regNames[rs] << dec << simm; break;
//        case 0x0c: cout << "andi " <<  regNames[rt] << ", " << regNames[rs] << dec << simm; break;
        case 0x0f: /* lui */ break;
      case 0x1a: cout << "trap " << hex << addr; break;
        case 0x23: /* lw */ break;
        case 0x2b: /* sw */ break;
       default: cout << "unimplemented";
    }
    cout << endl;
}
以下是预期输出:

400000: j 400114
400004: sw $ra, -4($sp)
400008: sw $fp, -8($sp)
40000c: addiu $fp, $sp, -8
400010: addiu $sp, $fp, -412
400014: addiu $k1, $zero, 1
编辑:带有已实施建议的新输出:

400000: j 400114
400004: sw $ra, fffffffc($sp)
400008: sw $fp, fffffff8($sp)
40000c: addiu $fp, $sp, -8
400010: addiu $sp, $fp, -412
400014: addiu $k1, $zero, 1

instr
是一种无符号类型(
uint32\u t
),因此将其向左移位,然后向右移位,只需清除最高有效位即可。它不会做你希望的标志扩展

事实上,根据C标准,将1左移到有符号整数的符号位是未定义的行为。因此,即使
instr
是一个有符号的数字,左移/右移技巧也不被允许(尽管它可以在任何一台合理的机器上工作)

要在不违反任何规则的情况下完成任务,请替换以下内容:

uimm = instr & 0xffff;
simm = (instr << 16) >> 16; // shift sign bit to left to 

伊萨?汇编程序?也使用c++将二进制文件转换为汇编:
simm=(int16_t)uimm这可能会生成更好的程序集。我尝试了你的建议,几乎所有偏移量都是0。。。有什么想法吗?还有,我很好奇你为什么建议使用整数65536?@Nathan1324也许我不清楚。我已经更新了答案。您的问题有四个示例,您可以手动尝试每一个示例,例如
65124-65536=-412
。而且您可以,因为在0x8000和0xffff之间只有32768个值。@fuz True在2的补码机器上,但通常不可移植。根据C标准,§6.3.1.3/3(增加强调):“否则,新类型被签名,并且值不能在其中表示;结果是实现定义的,或者是提出了实现定义的信号。”因此,如果每纳秒都很关键,并且可移植性不是一个问题,那么我同意你的建议。然而,考虑到OPs代码主要是一堆
cout
语句,我看不出节省几纳秒有什么用处。
uimm = instr & 0xffff;
simm = (instr << 16) >> 16; // shift sign bit to left to 
uimm = instr & 0xffff;
simm = uimm;   
if ( simm & 0x8000 )
    simm -= 65536;