Package: xasm
xasmNOTE: this is in betaA Cross-Python bytecode AssemblerIntroductionThe Pythonxasmmodule has routines for assembly, and has a command to
assemble bytecode for several different versions of Python.Here are some potential uses:Make small patches to existing Python bytecode when you don’t have sourceCraft custom and efficient bytecodeWrite an instruction-level optimizing compilerExperiment with and learn about Python bytecodeFoiluncompyle6so that it can’t disassemble bytecode (at least for now)This will support bytecodes from Python version 1.0 to 3.8 or so.The code requires Python 2.7 or later.Assembly filesMore detail will be filled in, but some principles:Preferred extension for Python assembly is.pyasmassembly is designed to work with the output ofpydisasm –asmAssembly file labels are at the beginning of the line
and end in a colon, e.g.END_IFinstruction offsets in the assembly file are ignored and don’t need
to be enteredin those instructions that refer to offsets, if the if the
operand is an int, exactly that value will be used for the operand. Otherwise
we will look for labels and match up with thatInstallationThe standard Python routine:pip install -e .
pip install -r requirements-dev.txtA GNU makefile is also provided somake install(possibly as root or
sudo) will do the steps above.Testingmake checkA GNU makefile has been added to smooth over setting running the right
command, and running tests from fastest to slowest.If you haveremakeinstalled, you can see the list of all tasks
including tests viaremake --tasks.Example Assembly FileFor this Python source code:def five():
    return 5

print(five())Here is an assembly for the above:# Python bytecode 3.6 (3379)

# Method Name:       five
# Filename:          /tmp/five.pl
# Argument count:    0
# Kw-only arguments: 0
# Number of locals:  0
# Stack size:        1
# Flags:             0x00000043 (NOFREE | NEWLOCALS | OPTIMIZED)
# First Line:        1
# Constants:
#    0: None
#    1: 5
  2:
            LOAD_CONST           (5)
            RETURN_VALUE


# Method Name:       <module>
# Filename:          /tmp/five.pl
# Argument count:    0
# Kw-only arguments: 0
# Number of locals:  0
# Stack size:        2
# Flags:             0x00000040 (NOFREE)
# First Line:        1
# Constants:
#    0: <code object five at 0x0000>
#    1: 'five'
#    2: None
# Names:
#    0: five
#    1: print
  1:
            LOAD_CONST           0 (<code object five at 0x0000>)
            LOAD_CONST           ('five')
            MAKE_FUNCTION        0
            STORE_NAME           (five)

  3:
            LOAD_NAME            (print)
            LOAD_NAME            (five)
            CALL_FUNCTION        0
            CALL_FUNCTION        1
            POP_TOP
            LOAD_CONST           (None)
            RETURN_VALUEThe above can be created automatically from Python source code using thepydisasmcommand fromxdis:pydisasm --format xasm /tmp/five.pycIn the example above though, I have shortend and simplified the result.UsageTo create a python bytecode file from an assemble file, run:pyc-xasm [OPTIONS] ASM_PATHFor usage help, typepyc-xasm –help.To convert a python bytecode from one bytecode to another, run:pyc-convert [OPTIONS] INPUT_PYC [OUTPUT_PYC]For usage help, typepyc-convert –help.See Alsohttps://github.com/rocky/python-xdis: Cross Python version disassemblehttps://github.com/rocky/x-python: Cross Python version interpreterhttps://github.com/rocky/python-xasm/blob/master/HOW-TO-USE.rst: How to write an assembler filehttps://rocky.github.io/pycon2018-light.co/: Pycolumbia 2018 Lightning talk showing how to use the assembler