12

Is there an easy way to create Python bytecode from a list of 2-tuples with opcodes and their arguments?

For instance:

>>> bytecode_compile([
        ('LOAD_CONST', 2),
        ('STORE_FAST', 'a'),
        ('LOAD_FAST', 'a'),
        ('RETURN_VALUE',)])
'd\x01\x00}\x00\x00|\x00\x00S'
exupero
  • 9,136
  • 8
  • 47
  • 63

2 Answers2

4

I wrote at length about this here so I won't repeat that but will give some summary comments.

It is definitely doable, but I wonder how generally useful it will be. The link goes into how to run and write out such stuff.

Bytecode is subject to change both in terms of opcode, or opcode names, or semantics of the opcodes between versions. In fact, in Python 3.6 and beyond a bytecode becomes a wordcode.

If you however do decide to go down this path xdis recently added a list2bytecode() function to do just this.

If you prefer to work in a text file as most assembly code is written, I wrote xasm for this. Here is some sample assembly in the format that this can use:

# 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_VALUE
rocky
  • 7,226
  • 3
  • 33
  • 74
3

I don't think a Python "bytecode assembly" assembler exists, but it might not be that hard to build one yourself. In the python source code in Python-X.Y.Z/Include/opcode.h, all of the bytecodes for the opcodes are listed with what arguments they take.

GuillaumeDufay
  • 1,118
  • 9
  • 13
  • 1
    You can also get similar list with `dis` module, f.e. `len(dis.opmap)` returns 101 against 103 opcodes in `opcode.h` of Python 3.4.3. – ilyaigpetrov Jun 20 '15 at 13:44