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

如何用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")

关键细节说明

  1. 指令解析:逐行读取文本,跳过空行和注释,拆分助记符和操作数,支持大小写不敏感的指令匹配。
  2. 操作码处理:用struct.pack('>H', opcode_val)将8位的操作码值打包成16位大端字节(比如0x41变成0x00 0x41),完全匹配你给出的预期输出格式。
  3. 操作数处理:支持十六进制(0x前缀)和十进制输入,同样打包成16位大端字节,同时做范围校验确保不超出16位地址空间。
  4. 错误处理:添加了基础的错误提示,便于调试无效指令或非法操作数。

验证结果

对于输入文本:

LDA 0x1020
STA 0x1030

生成的二进制文件内容(十六进制查看)为:00 41 10 20 00 54 10 30,对应你预期的0x0041, 0x1020, 0x0054, 0x1030(每两个字节一组)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 10:01:57