You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于PDP-11指令编解码工具的Encode/Decode按钮actionPerformed方法开发咨询

从零实现PDP-11指定指令的编解码按钮逻辑

别担心,刚接触PDP-11指令集确实会懵,但咱们只聚焦你指定的这6条指令(ADD、SUB、MOV、MOVB、CMP、CMPB),拆解成解码和编码两个核心流程,一步步来实现。

第一步:先搞懂核心规则

首先必须明确PDP-11这几条指令的16位编码格式,这是编解码的基础:

16位指令字结构

15 14 13 12 | 11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
------------|---------|-------|-------|-------
  Opcode(4) | 源模式(3)|源寄存器(3)|目的模式(3)|目的寄存器(3)

关键对应关系

操作码(Opcode)映射

汇编指令4位二进制Opcode十六进制
ADD00011
SUB00102
CMP01117
MOV10019
CMPB01015
MOVB1011B

寻址模式与汇编格式映射(只处理单字支持的模式,避免多字扩展)

3位模式码汇编格式示例(以R0为例)说明
000R0寄存器直接寻址
001(R0)寄存器间接寻址
010(R0)+寄存器自增寻址
011-(R0)寄存器自减寻址

寄存器编号:0→R0,1→R1,...,7→R7(3位二进制对应)


第二步:实现Decode按钮的actionPerformed方法

解码的流程是:

  1. 获取用户输入的十六进制/二进制字符串
  2. 转换成16位的整数(处理输入合法性)
  3. 从整数中拆分出Opcode、源模式、源寄存器、目的模式、目的寄存器
  4. 把各部分映射成对应的汇编指令字符串
  5. 显示结果

代码示例(Java,适配Swing的actionPerformed场景)

private void decodeButtonActionPerformed(java.awt.event.ActionEvent evt) {
    String input = inputTextField.getText().trim();
    StringBuilder result = new StringBuilder();
    
    try {
        // 1. 把输入转换成16位整数
        int instruction;
        if (input.startsWith("0x") || input.matches("[0-9A-Fa-f]{4}")) {
            // 十六进制处理
            instruction = Integer.parseInt(input.replace("0x", ""), 16);
        } else if (input.matches("[01]{16}")) {
            // 二进制处理
            instruction = Integer.parseInt(input, 2);
        } else {
            throw new IllegalArgumentException("输入必须是4位十六进制或16位二进制");
        }
        
        // 2. 拆分指令各部分
        int opcode = (instruction >> 12) & 0xF; // 取高4位
        int srcMode = (instruction >> 9) & 0x7; // 源模式(3位)
        int srcReg = (instruction >> 6) & 0x7; // 源寄存器(3位)
        int destMode = (instruction >> 3) & 0x7; // 目的模式(3位)
        int destReg = instruction & 0x7; // 目的寄存器(3位)
        
        // 3. 映射Opcode到汇编指令
        String opStr;
        switch(opcode) {
            case 0x1: opStr = "ADD"; break;
            case 0x2: opStr = "SUB"; break;
            case 0x7: opStr = "CMP"; break;
            case 0x9: opStr = "MOV"; break;
            case 0x5: opStr = "CMPB"; break;
            case 0xB: opStr = "MOVB"; break;
            default: throw new IllegalArgumentException("不支持的操作码");
        }
        
        // 4. 映射寻址模式+寄存器到操作数字符串
        String srcOperand = getOperandString(srcMode, srcReg);
        String destOperand = getOperandString(destMode, destReg);
        
        // 5. 拼接最终汇编指令
        result.append(String.format("%s %s, %s", opStr, srcOperand, destOperand));
        
    } catch (Exception e) {
        result.append("解码错误:").append(e.getMessage());
    }
    
    // 显示结果
    resultTextArea.setText(result.toString());
}

// 辅助方法:把模式+寄存器转成汇编格式的操作数
private String getOperandString(int mode, int reg) {
    String regStr = "R" + reg;
    switch(mode) {
        case 0: return regStr; // 000: 直接寻址
        case 1: return "(" + regStr + ")"; // 001: 间接寻址
        case 2: return "(" + regStr + ")+"; // 010: 自增
        case 3: return "-(" + regStr + ")"; // 011: 自减
        default: return "不支持的寻址模式";
    }
}

第三步:实现Encode按钮的actionPerformed方法

编码的流程是:

  1. 获取用户输入的汇编指令(比如ADD (R0)+, R1)
  2. 解析指令:拆分出操作码、源操作数、目的操作数
  3. 把操作数解析成对应的模式码和寄存器编号
  4. 把各部分拼接成16位的整数
  5. 转换成二进制或十六进制字符串显示

代码示例

private void encodeButtonActionPerformed(java.awt.event.ActionEvent evt) {
    String input = inputTextField.getText().trim();
    StringBuilder result = new StringBuilder();
    
    try {
        // 1. 拆分汇编指令:按空格分割,处理逗号
        String[] parts = input.split("\\s+");
        if (parts.length < 2) {
            throw new IllegalArgumentException("指令格式错误,示例:ADD R0, R1");
        }
        
        // 提取操作码
        String opStr = parts[0].toUpperCase();
        int opcode = getOpcode(opStr);
        
        // 提取源和目的操作数(处理逗号)
        String[] operands = parts[1].split(",");
        if (operands.length != 2) {
            throw new IllegalArgumentException("必须包含两个操作数,用逗号分隔");
        }
        String srcOperand = operands[0].trim();
        String destOperand = operands[1].trim();
        
        // 解析操作数得到模式和寄存器
        int[] srcParts = parseOperand(srcOperand);
        int srcMode = srcParts[0];
        int srcReg = srcParts[1];
        
        int[] destParts = parseOperand(destOperand);
        int destMode = destParts[0];
        int destReg = destParts[1];
        
        // 2. 拼接成16位指令
        int instruction = 0;
        instruction |= (opcode << 12);       // 操作码占高4位
        instruction |= (srcMode << 9);       // 源模式
        instruction |= (srcReg << 6);        // 源寄存器
        instruction |= (destMode << 3);      // 目的模式
        instruction |= destReg;              // 目的寄存器
        
        // 3. 转换成二进制和十六进制输出
        String binary = String.format("%16s", Integer.toBinaryString(instruction)).replace(' ', '0');
        String hex = String.format("%04X", instruction);
        
        result.append("二进制:").append(binary).append("\n");
        result.append("十六进制:0x").append(hex);
        
    } catch (Exception e) {
        result.append("编码错误:").append(e.getMessage());
    }
    
    // 显示结果
    resultTextArea.setText(result.toString());
}

// 辅助方法:根据汇编指令字符串获取Opcode
private int getOpcode(String opStr) {
    switch(opStr) {
        case "ADD": return 0x1;
        case "SUB": return 0x2;
        case "CMP": return 0x7;
        case "MOV": return 0x9;
        case "CMPB": return 0x5;
        case "MOVB": return 0xB;
        default: throw new IllegalArgumentException("不支持的指令:" + opStr);
    }
}

// 辅助方法:解析操作数字符串,返回[模式码, 寄存器编号]
private int[] parseOperand(String operand) {
    int mode = -1;
    int reg = -1;
    
    // 处理自减:-(R0)
    if (operand.startsWith("-(") && operand.endsWith(")")) {
        mode = 3;
        String regStr = operand.substring(2, operand.length()-1);
        reg = Integer.parseInt(regStr.substring(1));
    }
    // 处理自增:(R0)+
    else if (operand.startsWith("(") && operand.endsWith(")+")) {
        mode = 2;
        String regStr = operand.substring(1, operand.length()-2);
        reg = Integer.parseInt(regStr.substring(1));
    }
    // 处理间接:(R0)
    else if (operand.startsWith("(") && operand.endsWith(")")) {
        mode = 1;
        String regStr = operand.substring(1, operand.length()-1);
        reg = Integer.parseInt(regStr.substring(1));
    }
    // 处理直接:R0
    else if (operand.startsWith("R")) {
        mode = 0;
        reg = Integer.parseInt(operand.substring(1));
    }
    else {
        throw new IllegalArgumentException("不支持的操作数格式:" + operand);
    }
    
    // 校验寄存器编号是否合法(0-7)
    if (reg < 0 || reg >7) {
        throw new IllegalArgumentException("寄存器编号必须是0-7");
    }
    
    return new int[]{mode, reg};
}

额外提示

  1. 输入合法性校验:上面的代码已经做了基础校验,但你可以进一步完善,比如处理大小写、多余空格等。
  2. 扩展支持:如果后续需要支持更多寻址模式(比如立即数#123),需要处理多字指令,但当前需求只需要单字,所以上面的代码足够。
  3. 测试用例:可以用已知的指令来测试,比如ADD R0, R1的十六进制是0x1001,二进制是0001000000000001,解码后应该还原成指令。

内容的提问来源于stack exchange,提问作者Daria Jones

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 07:31:41