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

如何用Ghidra Python脚本获取带符号的格式化反汇编代码?

Ghidra 68000二进制反汇编脚本优化:恢复符号与无符号值格式化

问题场景

正在用Ghidra分析68000架构二进制,自带的“另存为”输出格式不满足需求,自己写Python脚本遍历代码单元后得到的结果是:

move.w #-0x5d56,(0xffffa602).w
bsr.b 0x000002c2

但Ghidra列表窗口显示的是带符号和无符号值的规整格式:

move.w #0xA2AA ,(ptr_to_last_updatable_bg_area).w
bsr.b  set_reg_values_2e2

需要实现至少恢复地址对应符号,最好同时把带符号值转为无符号十六进制的效果。

解决方案

核心技巧:复用Ghidra内置格式化逻辑

最省心的方式是直接调用Ghidra API里已经实现的指令格式化方法,它会自动处理符号替换和无符号值转换,和列表窗口输出完全一致。

完整脚本示例

from ghidra.program.model.listing import Listing
from ghidra.util.task import TaskMonitor

# 获取当前程序和列表对象
program = getCurrentProgram()
listing = program.getListing()
monitor = TaskMonitor.DUMMY

# 确定要遍历的地址范围:优先选中区域,否则取已加载内存
addr_set = currentSelection
if addr_set.isEmpty():
    addr_set = program.getMemory().getLoadedAndInitializedAddressSet()

# 遍历每个地址的指令并输出格式化结果
for addr in addr_set.getAddresses(True):
    instr = listing.getInstructionAt(addr)
    if not instr:
        continue
    # 直接调用toString()得到和Ghidra列表一致的格式
    print(instr.toString())

手动定制格式(按需使用)

如果需要自定义输出样式,可以手动解析每个操作数:

from ghidra.program.model.listing import Listing
from ghidra.program.model.symbol import SymbolTable
from ghidra.util.task import TaskMonitor

program = getCurrentProgram()
listing = program.getListing()
symbol_table = program.getSymbolTable()
monitor = TaskMonitor.DUMMY

addr_set = currentSelection if not currentSelection.isEmpty() else program.getMemory().getLoadedAndInitializedAddressSet()

for addr in addr_set.getAddresses(True):
    instr = listing.getInstructionAt(addr)
    if not instr:
        continue
    
    mnemonic = instr.getMnemonicString()
    operands = []
    
    for i in range(instr.getNumOperands()):
        op = instr.getOperand(i)
        
        # 处理立即数:转无符号十六进制
        if op.isImmediate():
            val = op.getValue()
            size = instr.getOperandSize(i)
            if size == 2:  # 16位立即数
                unsigned_val = val & 0xFFFF
                operands.append(f"#{hex(unsigned_val).upper()}")
            elif size == 4:  # 32位立即数
                unsigned_val = val & 0xFFFFFFFF
                operands.append(f"#{hex(unsigned_val).upper()}")
            else:
                operands.append(op.toString())
        
        # 处理地址操作数:替换为符号
        elif op.isAddress():
            op_addr = op.getAddress()
            symbol = symbol_table.getPrimarySymbol(op_addr)
            if symbol and symbol.getName():
                # 根据操作数类型调整格式(比如内存操作加.w后缀)
                operands.append(f"({symbol.getName()}).w")
            else:
                operands.append(f"({hex(op_addr.getOffset()).upper()}).w")
        
        # 其他操作数直接用默认格式
        else:
            operands.append(op.toString())
    
    # 拼接成最终指令字符串
    full_instr = f"{mnemonic} {' ,'.join(operands)}"
    print(full_instr)

关键API说明

  • instr.toString(): 直接复用Ghidra的内置格式化逻辑,一键得到符号化、无符号值的规整输出
  • symbol_table.getPrimarySymbol(op_addr): 根据地址查询对应的主符号,用于手动替换地址为符号名
  • 位运算val & 0xFFFF/0xFFFFFFFF: 将带符号立即数转为无符号,适配68000的16/32位数据宽度

内容的提问来源于stack exchange,提问作者T. Tournesol

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 15:46:35