如何用Python以字典为查找表将汇编文本转为二进制文件?
实现自研CPU汇编器:文本指令转二进制文件的最佳方式
核心思路
实现流程分为三步:文本指令解析、操作码映射、二进制序列化与写入,针对你的需求,重点要处理16位操作码(高位补0)和16位地址的大端字节序存储。
完整实现代码
import struct # 定义给定的操作码字典 opcodes = { "BRK": 0x01, "RFG": 0x02, "LFG": 0x03, "JMP": 0x10, "JMC": 0x11, "JMZ": 0x12, "JNZ": 0x13, "JEQ": 0x14, "JNE": 0x15, "JPG": 0x16, "JPL": 0x17, "JSR": 0x18, "RSR": 0x19, "ADE": 0x20, "ADI": 0x21, "AAB": 0x22, "AAX": 0x23, "AAY": 0x24, "ABX": 0x25, "ABY": 0x26, "AXY": 0x27, "INC": 0x28, "INB": 0x29, "INX": 0x2A, "INY": 0x2B, "SUE": 0x2C, "SUI": 0x2D, "SAB": 0x2E, "SAX": 0x2F, "SAY": 0x30, "SBX": 0x31, "SBY": 0x32, "SXY": 0x33, "DEC": 0x34, "DEB": 0x35, "DEX": 0x36, "DEY": 0x37, "BSL": 0x38, "BSR": 0x39, "LDI": 0x40, "LDA": 0x41, "LIB": 0x42, "LDB": 0x43, "LIX": 0x44, "LDX": 0x45, "LIY": 0x46, "LDY": 0x47, "TAB": 0x48, "TAX": 0x49, "TAY": 0x4A, "TBA": 0x4B, "TBX": 0x4C, "TBY": 0x4D, "TXA": 0x4E, "TXB": 0x4F, "TXY": 0x50, "TYA": 0x51, "TYB": 0x52, "TYX": 0x53, "STA": 0x54, "STB": 0x55, "STX": 0x56, "STY": 0x57, "SCB": 0x58, "SCX": 0x59, "SCY": 0x5A, "CAB": 0x60, "CAX": 0x61, "CAY": 0x62, "CBA": 0x63, "CBX": 0x64, "CBY": 0x65, "CXA": 0x66, "CXB": 0x67, "CXY": 0x68, "CYA": 0x69, "CYB": 0x6A, "CYX": 0x6B } def assemble(input_file, output_file): binary_data = bytearray() with open(input_file, 'r') as f: for line_num, line in enumerate(f, 1): # 去除空白和注释(如果有的话) line = line.strip() if not line or line.startswith(';'): continue # 拆分指令和操作数 parts = line.split(maxsplit=1) if len(parts) < 1: print(f"警告:第{line_num}行无效,跳过") continue mnemonic = parts[0].upper() operand = parts[1] if len(parts) > 1 else None # 验证操作码存在 if mnemonic not in opcodes: print(f"错误:第{line_num}行未知指令 '{mnemonic}'") continue # 处理操作码:转成16位大端字节(高位补0) opcode_val = opcodes[mnemonic] binary_data.extend(struct.pack('>H', opcode_val)) # >H 表示大端16位无符号整数 # 处理操作数:转成16位大端字节 if operand: try: # 支持十六进制(0x前缀)和十进制 operand_val = int(operand, 0) # 确保操作数是16位范围内 if not (0 <= operand_val <= 0xFFFF): print(f"错误:第{line_num}行操作数 '{operand}' 超出16位范围") continue binary_data.extend(struct.pack('>H', operand_val)) except ValueError: print(f"错误:第{line_num}行无效操作数 '{operand}'") continue # 写入二进制文件 with open(output_file, 'wb') as f: f.write(binary_data) print(f"汇编完成,二进制文件已保存到 {output_file}") # 使用示例 if __name__ == "__main__": assemble("input.asm", "output.bin")
关键细节说明
- 指令解析:逐行读取文本,跳过空行和注释,拆分助记符和操作数,支持大小写不敏感的指令匹配。
- 操作码处理:用
struct.pack('>H', opcode_val)将8位的操作码值打包成16位大端字节(比如0x41变成0x00 0x41),完全匹配你给出的预期输出格式。 - 操作数处理:支持十六进制(
0x前缀)和十进制输入,同样打包成16位大端字节,同时做范围校验确保不超出16位地址空间。 - 错误处理:添加了基础的错误提示,便于调试无效指令或非法操作数。
验证结果
对于输入文本:
LDA 0x1020 STA 0x1030
生成的二进制文件内容(十六进制查看)为:00 41 10 20 00 54 10 30,对应你预期的0x0041, 0x1020, 0x0054, 0x1030(每两个字节一组)。
内容的提问来源于stack exchange,提问作者TheBearSlicer
相关产品推荐
相关产品推荐

