关于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 | 十六进制 |
|---|---|---|
| ADD | 0001 | 1 |
| SUB | 0010 | 2 |
| CMP | 0111 | 7 |
| MOV | 1001 | 9 |
| CMPB | 0101 | 5 |
| MOVB | 1011 | B |
寻址模式与汇编格式映射(只处理单字支持的模式,避免多字扩展)
| 3位模式码 | 汇编格式示例(以R0为例) | 说明 |
|---|---|---|
| 000 | R0 | 寄存器直接寻址 |
| 001 | (R0) | 寄存器间接寻址 |
| 010 | (R0)+ | 寄存器自增寻址 |
| 011 | -(R0) | 寄存器自减寻址 |
寄存器编号:0→R0,1→R1,...,7→R7(3位二进制对应)
第二步:实现Decode按钮的actionPerformed方法
解码的流程是:
- 获取用户输入的十六进制/二进制字符串
- 转换成16位的整数(处理输入合法性)
- 从整数中拆分出Opcode、源模式、源寄存器、目的模式、目的寄存器
- 把各部分映射成对应的汇编指令字符串
- 显示结果
代码示例(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方法
编码的流程是:
- 获取用户输入的汇编指令(比如
ADD (R0)+, R1) - 解析指令:拆分出操作码、源操作数、目的操作数
- 把操作数解析成对应的模式码和寄存器编号
- 把各部分拼接成16位的整数
- 转换成二进制或十六进制字符串显示
代码示例
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}; }
额外提示
- 输入合法性校验:上面的代码已经做了基础校验,但你可以进一步完善,比如处理大小写、多余空格等。
- 扩展支持:如果后续需要支持更多寻址模式(比如立即数
#123),需要处理多字指令,但当前需求只需要单字,所以上面的代码足够。 - 测试用例:可以用已知的指令来测试,比如
ADD R0, R1的十六进制是0x1001,二进制是0001000000000001,解码后应该还原成指令。
内容的提问来源于stack exchange,提问作者Daria Jones
相关产品推荐
相关产品推荐

