Python的pyc字节码反编译反汇编相关知识_pycdc-程序员宅基地

技术标签: python  安全  逆向研究  

常用pyc转py的工具

pycdc Decompyle++

Decompyle++旨在将编译后的Python字节码转换回有效的、人类可读的Python源代码。虽然其他项目取得了不同程度的成功,但Decompyle++的独特之处在于,它寻求支持来自任何版本的Python的字节码。

Decompyle++包含一个字节码反汇编器(pycda)和一个反编译器(pycdc)。

该工具需要手动编译,使用kali编译以后的样本:https://pan.baidu.com/s/1tAzVPMzFmhWko915yguOUg?pwd=ekgi 提取码:ekgi

decompyle3 仅支持3.8及以下版本

原生Python跨版本反编译器和片段反编译器。是改进版本的uncompille6。

pip install decompyle3

常用exe转pyc的工具

pyinstxtractor.py

将exe解压成pyc文件夹,内含各种资源以及pyc文件

https://pan.baidu.com/s/1tAzVPMzFmhWko915yguOUg?pwd=ekgi 提取码:ekgi

使用dis.dis

该工具是python自带的库,可将已经编译为pyc的文件反编译为汇编

例如源程序
def main():
    a = 1
    b = 2
    c = a + b
    d = [c]*3
    d2 = enumerate(d)
    e = [x[0] + x[1] for x in d2]
    return e


r = main()
print(len(r))
print(r)

反汇编方式
import dis
s = open('test.py').read()
co = compile(s, 'test.py', 'exec')
dis.dis(co, file=open('./test.txt', 'w'))
反汇编结果
  1           0 LOAD_CONST               0 (<code object main at 0x0000018F5DECC5B0, file "test.py", line 1>)
              2 LOAD_CONST               1 ('main')
              4 MAKE_FUNCTION            0
              6 STORE_NAME               0 (main)

 11           8 LOAD_NAME                0 (main)
             10 CALL_FUNCTION            0
             12 STORE_NAME               1 (r)

 12          14 LOAD_NAME                2 (print)
             16 LOAD_NAME                3 (len)
             18 LOAD_NAME                1 (r)
             20 CALL_FUNCTION            1
             22 CALL_FUNCTION            1
             24 POP_TOP

 13          26 LOAD_NAME                2 (print)
             28 LOAD_NAME                1 (r)
             30 CALL_FUNCTION            1
             32 POP_TOP
             34 LOAD_CONST               2 (None)
             36 RETURN_VALUE

Disassembly of <code object main at 0x0000018F5DECC5B0, file "test.py", line 1>:
  2           0 LOAD_CONST               1 (1)
              2 STORE_FAST               0 (a)

  3           4 LOAD_CONST               2 (2)
              6 STORE_FAST               1 (b)

  4           8 LOAD_FAST                0 (a)
             10 LOAD_FAST                1 (b)
             12 BINARY_ADD
             14 STORE_FAST               2 (c)

  5          16 LOAD_FAST                2 (c)
             18 BUILD_LIST               1
             20 LOAD_CONST               3 (3)
             22 BINARY_MULTIPLY
             24 STORE_FAST               3 (d)

  6          26 LOAD_GLOBAL              0 (enumerate)
             28 LOAD_FAST                3 (d)
             30 CALL_FUNCTION            1
             32 STORE_FAST               4 (d2)

  7          34 LOAD_CONST               4 (<code object <listcomp> at 0x0000018F5DECC500, file "test.py", line 7>)
             36 LOAD_CONST               5 ('main.<locals>.<listcomp>')
             38 MAKE_FUNCTION            0
             40 LOAD_FAST                4 (d2)
             42 GET_ITER
             44 CALL_FUNCTION            1
             46 STORE_FAST               5 (e)

  8          48 LOAD_FAST                5 (e)
             50 RETURN_VALUE

Disassembly of <code object <listcomp> at 0x0000018F5DECC500, file "test.py", line 7>:
  7           0 BUILD_LIST               0
              2 LOAD_FAST                0 (.0)
        >>    4 FOR_ITER                10 (to 26)
              6 STORE_FAST               1 (x)
              8 LOAD_FAST                1 (x)
             10 LOAD_CONST               0 (0)
             12 BINARY_SUBSCR
             14 LOAD_FAST                1 (x)
             16 LOAD_CONST               1 (1)
             18 BINARY_SUBSCR
             20 BINARY_ADD
             22 LIST_APPEND              2
             24 JUMP_ABSOLUTE            2 (to 4)
        >>   26 RETURN_VALUE

dis — Python 字节码反汇编器

Source code: Lib/dis.py


dis 模块通过反汇编支持CPython的 bytecode 分析。该模块作为输入的 CPython 字节码在文件 Include/opcode.h 中定义,并由编译器和解释器使用。

CPython implementation detail: 字节码是 CPython 解释器的实现细节。不保证不会在Python版本之间添加、删除或更改字节码。不应考虑将此模块的跨 Python VM 或 Python 版本的使用。

在 3.6 版更改: 每条指令使用2个字节。以前字节数因指令而异。

示例:给出函数 myfunc():

def myfunc(alist):
    return len(alist)

可以使用以下命令显示 myfunc() 的反汇编

>>>>>>

>>> dis.dis(myfunc)
  2           0 LOAD_GLOBAL              0 (len)
              2 LOAD_FAST                0 (alist)
              4 CALL_FUNCTION            1
              6 RETURN_VALUE

(“2” 是行号)。

字节码分析

3.4 新版功能.

字节码分析 API 允许将 Python 代码片段包装在 Bytecode 对象中,以便轻松访问已编译代码的详细信息。

  • class dis.``Bytecode(x, ***, first_line=None, current_offset=None)

    分析的字节码对应于函数、生成器、异步生成器、协程、方法、源代码字符串或代码对象(由 compile() 返回)。这是下面列出的许多函数的便利包装,最值得注意的是 get_instructions() ,迭代于 Bytecode 的实例产生字节码操作 Instruction 的实例。如果 first_line 不是 None ,则表示应该为反汇编代码中的第一个源代码行报告的行号。否则,源行信息(如果有的话)直接来自反汇编的代码对象。如果 current_offset 不是 None ,则它指的是反汇编代码中的指令偏移量。设置它意味着 dis() 将针对指定的操作码显示“当前指令”标记。classmethod from_traceback(tb)从给定回溯构造一个 Bytecode 实例,设置 current_offset 为异常负责的指令。codeobj已编译的代码对象。first_line代码对象的第一个源代码行(如果可用)dis()返回字节码操作的格式化视图(与 dis.dis() 打印相同,但作为多行字符串返回)。info()返回带有关于代码对象的详细信息的格式化多行字符串,如 code_info() 。在 3.7 版更改: 现在可以处理协程和异步生成器对象。

示例:

>>>>>>

>>> bytecode = dis.Bytecode(myfunc)
>>> for instr in bytecode:
...     print(instr.opname)
...
LOAD_GLOBAL
LOAD_FAST
CALL_FUNCTION
RETURN_VALUE

分析函数

dis 模块还定义了以下分析函数,它们将输入直接转换为所需的输出。如果只执行单个操作,它们可能很有用,因此中间分析对象没用:

  • dis.``code_info(x)

    返回格式化的多行字符串,其包含详细代码对象信息的用于被提供的函数、生成器、异步生成器、协程、方法、源代码字符串或代码对象。请注意,代码信息字符串的确切内容是高度依赖于实现的,它们可能会在Python VM或Python版本中任意更改。3.2 新版功能.在 3.7 版更改: 现在可以处理协程和异步生成器对象。

  • dis.``show_code(x, ***, file=None)

    将提供的函数、方法。源代码字符串或代码对象的详细代码对象信息打印到 file (如果未指定 file ,则为 sys.stdout )。这是 print(code_info(x), file= file) 的便捷简写,用于在解释器提示符下进行交互式探索。3.2 新版功能.在 3.4 版更改: 添加 file 参数。

  • dis.``dis(x=None, ***, file=None, depth=None)

    反汇编 x 对象。 x 可以表示模块、类、方法、函数、生成器、异步生成器、协程、代码对象、源代码字符串或原始字节码的字节序列。对于模块,它会反汇编所有功能。对于一个类,它反汇编所有方法(包括类和静态方法)。对于代码对象或原始字节码序列,它每字节码指令打印一行。它还递归地反汇编嵌套代码对象(推导式代码,生成器表达式和嵌套函数,以及用于构建嵌套类的代码)。在被反汇编之前,首先使用 compile() 内置函数将字符串编译为代码对象。如果未提供任何对象,则此函数会反汇编最后一次回溯。如果提供的话,反汇编将作为文本写入提供的 file 参数,否则写入 sys.stdout 。递归的最大深度受 depth 限制,除非它是 Nonedepth=0 表示没有递归。在 3.4 版更改: 添加 file 参数。在 3.7 版更改: 实现了递归反汇编并添加了 depth 参数。在 3.7 版更改: 现在可以处理协程和异步生成器对象。

  • dis.``distb(tb=None, ***, file=None)

    如果没有传递,则使用最后一个回溯来反汇编回溯的堆栈顶部函数。 指示了导致异常的指令。如果提供的话,反汇编将作为文本写入提供的 file 参数,否则写入 sys.stdout 。在 3.4 版更改: 添加 file 参数。

  • dis.``disassemble(code, lasti=-1, ***, file=None)

  • dis.``disco(code, lasti=-1, ***, file=None)

    反汇编代码对象,如果提供了 lasti ,则指示最后一条指令。输出分为以下几列:行号,用于每行的第一条指令当前指令,表示为 --> ,一个标记的指令,用 >> 表示,指令的地址,操作码名称,操作参数,和括号中的参数解释。参数解释识别本地和全局变量名称、常量值、分支目标和比较运算符。如果提供的话,反汇编将作为文本写入提供的 file 参数,否则写入 sys.stdout 。在 3.4 版更改: 添加 file 参数。

  • dis.``get_instructions(x, ***, first_line=None)

    在所提供的函数、方法、源代码字符串或代码对象中的指令上返回一个迭代器。迭代器生成一系列 Instruction ,命名为元组,提供所提供代码中每个操作的详细信息。如果 first_line 不是 None ,则表示应该为反汇编代码中的第一个源代码行报告的行号。否则,源行信息(如果有的话)直接来自反汇编的代码对象。3.4 新版功能.

  • dis.``findlinestarts(code)

    此生成器函数使用代码对象 codeco_firstlinenoco_lnotab 属性来查找源代码中行开头的偏移量。它们生成为 (offset, lineno) 对。请参阅 :source:objects/lnotab_notes.txt ,了解 ``co_lnotab 格式以及如何解码它。在 3.6 版更改: 行号可能会减少。 以前,他们总是在增加。

  • dis.``findlabels(code)

    检测作为跳转目标的原始编译后字节码字符串 code 中的所有偏移量,并返回这些偏移量的列表。

  • dis.``stack_effect(opcode[, oparg])

    使用参数 oparg 计算 opcode 的堆栈效果。3.4 新版功能.

Python字节码说明

get_instructions() 函数和 Bytecode 类提供字节码指令的详细信息的 Instruction 实例:

  • class dis.``Instruction

    字节码操作的详细信息opcode操作的数字代码,对应于下面列出的操作码值和 操作码集合 中的字节码值。opname人类可读的操作名称arg操作的数字参数(如果有的话),否则为 None``argval已解析的 arg 值(如果已知),否则与 arg 相同argrepr人类可读的操作参数描述offset在字节码序列中启动操作索引starts_line行由此操作码(如果有)启动,否则为 None``is_jump_target如果其他代码跳到这里,则为 True ,否则为 False3.4 新版功能.

Python编译器当前生成以下字节码指令。

一般指令

  • NOP

    什么都不做。 用作字节码优化器的占位符。

  • POP_TOP

    删除堆栈顶部(TOS)项。

  • ROT_TWO

    交换两个最顶层的堆栈项。

  • ROT_THREE

    将第二个和第三个堆栈项向上提升一个位置,顶项移动到位置三。

  • DUP_TOP

    复制堆栈顶部的引用。3.2 新版功能.

  • DUP_TOP_TWO

    复制堆栈顶部的两个引用,使它们保持相同的顺序。3.2 新版功能.

一元操作

一元操作获取堆栈顶部元素,应用操作,并将结果推回堆栈。

  • UNARY_POSITIVE

    实现 TOS = +TOS

  • UNARY_NEGATIVE

    实现 TOS = -TOS

  • UNARY_NOT

    实现 TOS = not TOS

  • UNARY_INVERT

    实现 TOS = ~TOS

  • GET_ITER

    实现 TOS = iter(TOS)

  • GET_YIELD_FROM_ITER

    如果 TOS 是一个 generator iteratorcoroutine 对象则保持原样。否则实现 TOS = iter(TOS) 。3.5 新版功能.

二元操作

二元操作从堆栈中删除堆栈顶部(TOS)和第二个最顶层堆栈项(TOS1)。 它们执行操作,并将结果放回堆栈。

  • BINARY_POWER

    实现 TOS = TOS1 ** TOS

  • BINARY_MULTIPLY

    实现 TOS = TOS1 * TOS

  • BINARY_MATRIX_MULTIPLY

    实现 TOS = TOS1 @ TOS 。3.5 新版功能.

  • BINARY_FLOOR_DIVIDE

    实现 TOS = TOS1 // TOS

  • BINARY_TRUE_DIVIDE

    实现 TOS = TOS1 / TOS

  • BINARY_MODULO

    实现 TOS = TOS1 % TOS

  • BINARY_ADD

    实现 TOS = TOS1 + TOS

  • BINARY_SUBTRACT

    实现 TOS = TOS1 - TOS

  • BINARY_SUBSCR

    实现 TOS = TOS1[TOS]

  • BINARY_LSHIFT

    实现 TOS = TOS1 << TOS

  • BINARY_RSHIFT

    实现 TOS = TOS1 >> TOS

  • BINARY_AND

    实现 TOS = TOS1 & TOS

  • BINARY_XOR

    实现 TOS = TOS1 ^ TOS

  • BINARY_OR

    实现 TOS = TOS1 | TOS

就地操作

就地操作就像二元操作,因为它们删除了TOS和TOS1,并将结果推回到堆栈上,但是当TOS1支持它时,操作就地完成,并且产生的TOS可能是(但不一定) 原来的TOS1。

  • INPLACE_POWER

    就地实现 TOS = TOS1 ** TOS

  • INPLACE_MULTIPLY

    就地实现 TOS = TOS1 * TOS

  • INPLACE_MATRIX_MULTIPLY

    就地实现 TOS = TOS1 @ TOS 。3.5 新版功能.

  • INPLACE_FLOOR_DIVIDE

    就地实现 TOS = TOS1 // TOS

  • INPLACE_TRUE_DIVIDE

    就地实现 TOS = TOS1 / TOS

  • INPLACE_MODULO

    就地实现 TOS = TOS1 % TOS

  • INPLACE_ADD

    就地实现 TOS = TOS1 + TOS

  • INPLACE_SUBTRACT

    就地实现 TOS = TOS1 - TOS

  • INPLACE_LSHIFT

    就地实现 TOS = TOS1 << TOS

  • INPLACE_RSHIFT

    就地实现 TOS = TOS1 >> TOS

  • INPLACE_AND

    就地实现 TOS = TOS1 & TOS

  • INPLACE_XOR

    就地实现 TOS = TOS1 ^ TOS

  • INPLACE_OR

    就地实现 TOS = TOS1 | TOS

  • STORE_SUBSCR

    实现 TOS1[TOS] = TOS2

  • DELETE_SUBSCR

    实现 del TOS1[TOS]

协程操作码

  • GET_AWAITABLE

    实现 TOS = get_awaitable(TOS) ,其中 get_awaitable(o) 返回 o 如果 o 是一个有 CO_ITERABLE_COROUTINE 标志的协程对象或生成器对象,否则解析 o.__await__ 。3.5 新版功能.

  • GET_AITER

    实现 TOS = TOS.__aiter__() 。3.5 新版功能.在 3.7 版更改: 已经不再支持从 __aiter__ 返回可等待对象。

  • GET_ANEXT

    实现 PUSH(get_awaitable(TOS.__anext__())) 。参见 GET_AWAITABLE 获取更多 get_awaitable 的细节3.5 新版功能.

  • BEFORE_ASYNC_WITH

    从栈顶元素解析 __aenter____aexit__ 。将 __aexit____aenter__() 的结果推入堆栈。3.5 新版功能.

  • SETUP_ASYNC_WITH

    创建一个新的帧对象。3.5 新版功能.

其他操作码

  • PRINT_EXPR

    实现交互模式的表达式语句。TOS从堆栈中被移除并打印。在非交互模式下,表达式语句以 POP_TOP 终止。

  • BREAK_LOOP

    Terminates a loop due to a break statement.

  • CONTINUE_LOOP(target)

    Continues a loop due to a continue statement. target is the address to jump to (which should be a FOR_ITER instruction).

  • SET_ADD(i)

    调用 set.add(TOS1[-i], TOS) 。 用于实现集合推导。

  • LIST_APPEND(i)

    调用 list.append(TOS[-i], TOS) 。 用于实现列表推导。

  • MAP_ADD(i)

    Calls dict.setitem(TOS1[-i], TOS, TOS1). Used to implement dict comprehensions.3.1 新版功能.

对于所有 SET_ADDLIST_APPENDMAP_ADD 指令,当弹出添加的值或键值对时,容器对象保留在堆栈上,以便它可用于循环的进一步迭代。

  • RETURN_VALUE

    返回 TOS 到函数的调用者。

  • YIELD_VALUE

    弹出 TOS 并从一个 generator 生成它。

  • YIELD_FROM

    弹出 TOS 并将其委托给它作为 generator 的子迭代器。3.3 新版功能.

  • SETUP_ANNOTATIONS

    检查 __annotations__ 是否在 locals() 中定义,如果没有,它被设置为空 dict 。只有在类或模块体静态地包含 variable annotations 时才会发出此操作码。3.6 新版功能.

  • IMPORT_STAR

    将所有不以 '_' 开头的符号直接从模块 TOS 加载到本地名称空间。加载所有名称后弹出该模块。这个操作码实现了 from module import *

  • POP_BLOCK

    Removes one block from the block stack. Per frame, there is a stack of blocks, denoting nested loops, try statements, and such.

  • POP_EXCEPT

    从块堆栈中删除一个块。 弹出的块必须是异常处理程序块,在进入 except 处理程序时隐式创建。除了从帧堆栈弹出无关值之外,最后三个弹出值还用于恢复异常状态。

  • END_FINALLY

    Terminates a finally clause. The interpreter recalls whether the exception has to be re-raised, or whether the function returns, and continues with the outer-next block.

  • LOAD_BUILD_CLASS

    builtins .__ build_class__() 推到堆栈上。它之后被 CALL_FUNCTION 调用来构造一个类。

  • SETUP_WITH(delta)

    This opcode performs several operations before a with block starts. First, it loads __exit__() from the context manager and pushes it onto the stack for later use by WITH_CLEANUP. Then, __enter__() is called, and a finally block pointing to delta is pushed. Finally, the result of calling the enter method is pushed onto the stack. The next opcode will either ignore it (POP_TOP), or store it in (a) variable(s) (STORE_FAST, STORE_NAME, or UNPACK_SEQUENCE).3.2 新版功能.

  • WITH_CLEANUP_START

    Cleans up the stack when a with statement block exits. TOS is the context manager’s __exit__() bound method. Below TOS are 1–3 values indicating how/why the finally clause was entered:SECOND = None(SECOND, THIRD) = (WHY_{RETURN,CONTINUE}), retvalSECOND = WHY_*; no retval below it(SECOND, THIRD, FOURTH) = exc_info()In the last case, TOS(SECOND, THIRD, FOURTH) is called, otherwise TOS(None, None, None). Pushes SECOND and result of the call to the stack.

  • WITH_CLEANUP_FINISH

    Pops exception type and result of ‘exit’ function call from the stack.If the stack represents an exception, and the function call returns a ‘true’ value, this information is “zapped” and replaced with a single WHY_SILENCED to prevent END_FINALLY from re-raising the exception. (But non-local gotos will still be resumed.)

以下所有操作码均使用其参数。

  • STORE_NAME(namei)

    实现 name = TOSnameiname 在代码对象的 co_names 属性中的索引。 在可能的情况下,编译器会尝试使用 STORE_FASTSTORE_GLOBAL

  • DELETE_NAME(namei)

    实现 del name ,其中 namei 是代码对象的 co_names 属性的索引。

  • UNPACK_SEQUENCE(count)

    将 TOS 解包为 count 个单独的值,它们将按从右至左的顺序被放入堆栈。

  • UNPACK_EX(counts)

    实现使用带星号的目标进行赋值:将 TOS 中的可迭代对象解包为单独的值,其中值的总数可以小于可迭代对象中的项数:新值之一将是由所有剩余项构成的列表。counts 的低字节是列表值之前的值的数量,counts 中的高字节则是之后的值的数量。 结果值会按从右至左的顺序入栈。

  • STORE_ATTR(namei)

    实现 TOS.name = TOS1,其中 namei 是 name 在 co_names 中的索引号。

  • DELETE_ATTR(namei)

    实现 del TOS.name,使用 namei 作为 co_names 中的索引号。

  • STORE_GLOBAL(namei)

    类似于 STORE_NAME 但会将 name 存储为全局变量。

  • DELETE_GLOBAL(namei)

    类似于 DELETE_NAME 但会删除一个全局变量。

  • LOAD_CONST(consti)

    co_consts[consti] 推入栈顶。

  • LOAD_NAME(namei)

    将与 co_names[namei] 相关联的值推入栈顶。

  • BUILD_TUPLE(count)

    创建一个使用了来自栈的 count 个项的元组,并将结果元组推入栈顶。

  • BUILD_LIST(count)

    类似于 BUILD_TUPLE 但会创建一个列表。

  • BUILD_SET(count)

    类似于 BUILD_TUPLE 但会创建一个集合。

  • BUILD_MAP(count)

    将一个新字典对象推入栈顶。 弹出 2 * count 项使得字典包含 count 个条目: {..., TOS3: TOS2, TOS1: TOS}。在 3.5 版更改: 字典是根据栈中的项创建而不是创建一个预设大小包含 count 项的空字典。

  • BUILD_CONST_KEY_MAP(count)

    BUILD_MAP 版本专用于常量键。 弹出的栈顶元素包含一个由键构成的元组,然后从 TOS1 开始从构建字典的值中弹出 count 个值。3.6 新版功能.

  • BUILD_STRING(count)

    拼接 count 个来自栈的字符串并将结果字符串推入栈顶。3.6 新版功能.

  • BUILD_TUPLE_UNPACK(count)

    从栈中弹出 count 个可迭代对象,将它们合并为单个元组,并将结果推入栈顶。 实现可迭代对象解包为元组形式 (*x, *y, *z)。3.5 新版功能.

  • BUILD_TUPLE_UNPACK_WITH_CALL(count)

    这类似于 BUILD_TUPLE_UNPACK 但专用于 f(*x, *y, *z) 调用语法。 栈中 count + 1 位置上的项应当是相应的可调用对象 f。3.6 新版功能.

  • BUILD_LIST_UNPACK(count)

    这类似于 BUILD_TUPLE_UNPACK 但会将一个列表而非元组推入栈顶。 实现可迭代对象解包为列表形式 [*x, *y, *z]。3.5 新版功能.

  • BUILD_SET_UNPACK(count)

    这类似于 BUILD_TUPLE_UNPACK 但会将一个集合而非元组推入栈顶。 实现可迭代对象解包为集合形式 {*x, *y, *z}。3.5 新版功能.

  • BUILD_MAP_UNPACK(count)

    从栈中弹出 count 个映射对象,将它们合并为单个字典,并将结果推入栈顶。 实现字典解包为字典形式 {**x, **y, **z}。3.5 新版功能.

  • BUILD_MAP_UNPACK_WITH_CALL(count)

    这类似于 BUILD_MAP_UNPACK 但专用于 f(**x, **y, **z) 调用语法。 栈中 count + 2 位置上的项应当是相应的可调用对象 f。3.5 新版功能.在 3.6 版更改: 可迭代对象的位置的确定方式是将操作码参数加 2 而不是将其编码到参数的第二个字节。

  • LOAD_ATTR(namei)

    将 TOS 替换为 getattr(TOS, co_names[namei])

  • COMPARE_OP(opname)

    执行布尔运算操作。 操作名称可在 cmp_op[opname] 中找到。

  • IMPORT_NAME(namei)

    导入模块 co_names[namei]。 会弹出 TOS 和 TOS1 以提供 fromlistlevel 参数给 __import__()。 模块对象会被推入栈顶。 当前命名空间不受影响:对于一条标准 import 语句,会执行后续的 STORE_FAST 指令来修改命名空间。

  • IMPORT_FROM(namei)

    从在 TOS 内找到的模块中加载属性 co_names[namei]。 结果对象会被推入栈顶,以便由后续的 STORE_FAST 指令来保存。

  • JUMP_FORWARD(delta)

    将字节码计数器的值增加 delta

  • POP_JUMP_IF_TRUE(target)

    如果 TOS 为真值,则将字节码计数器的值设为 target。 TOS 会被弹出。3.1 新版功能.

  • POP_JUMP_IF_FALSE(target)

    如果 TOS 为假值,则将字节码计数器的值设为 target。 TOS 会被弹出。3.1 新版功能.

  • JUMP_IF_TRUE_OR_POP(target)

    如果 TOS 为真值,则将字节码计数器的值设为 target 并将 TOS 留在栈顶。 否则(如 TOS 为假值),TOS 会被弹出。3.1 新版功能.

  • JUMP_IF_FALSE_OR_POP(target)

    如果 TOS 为假值,则将字节码计数器的值设为 target 并将 TOS 留在栈顶。 否则(如 TOS 为真值),TOS 会被弹出。3.1 新版功能.

  • JUMP_ABSOLUTE(target)

    将字节码计数器的值设为 target

  • FOR_ITER(delta)

    TOS 是一个 iterator。 可调用它的 __next__() 方法。 如果产生了一个新值,则将其推入栈顶(将迭代器留在其下方)。 如果迭代器提示已耗尽则 TOS 会被弹出,并将字节码计数器的值增加 delta

  • LOAD_GLOBAL(namei)

    加载名称为 co_names[namei] 的全局对象推入栈顶。

  • SETUP_LOOP(delta)

    Pushes a block for a loop onto the block stack. The block spans from the current instruction with a size of delta bytes.

  • SETUP_EXCEPT(delta)

    Pushes a try block from a try-except clause onto the block stack. delta points to the first except block.

  • SETUP_FINALLY(delta)

    Pushes a try block from a try-except clause onto the block stack. delta points to the finally block.

  • LOAD_FAST(var_num)

    将指向局部对象 co_varnames[var_num] 的引用推入栈顶。

  • STORE_FAST(var_num)

    将 TOS 存放到局部变量 co_varnames[var_num]

  • DELETE_FAST(var_num)

    移除局部对象 co_varnames[var_num]

  • LOAD_CLOSURE(i)

    将一个包含在单元的第 i 个空位中的对单元的引用推入栈顶并释放可用的存储空间。 如果 i 小于 co_cellvars 的长度则变量的名称为 co_cellvars[i]。 否则为 co_freevars[i - len(co_cellvars)]

  • LOAD_DEREF(i)

    加载包含在单元的第 i 个空位中的单元并释放可用的存储空间。 将一个对单元所包含对象的引用推入栈顶。

  • LOAD_CLASSDEREF(i)

    类似于 LOAD_DEREF 但在查询单元之前会首先检查局部对象字典。 这被用于加载类语句体中的自由变量。3.4 新版功能.

  • STORE_DEREF(i)

    将 TOS 存放到包含在单元的第 i 个空位中的单元内并释放可用存储空间。

  • DELETE_DEREF(i)

    清空包含在单元的第 i 个空位中的单元并释放可用存储空间。 被用于 del 语句。3.2 新版功能.

  • RAISE_VARARGS(argc)

    使用 raise 语句的 3 种形式之一引发异常,具体形式取决于 argc 的值:0: raise (重新引发之前的异常)1: raise TOS (在 TOS 上引发异常实例或类型)2: raise TOS1 from TOS (在 TOS1 上引发异常实例或类型并将 __cause__ 设为 TOS)

  • CALL_FUNCTION(argc)

    调用一个可调用对象并传入位置参数。 argc 指明位置参数的数量。 栈顶包含位置参数,其中最右边的参数在最顶端。 在参数之下是一个待调用的可调用对象。 CALL_FUNCTION 会从栈中弹出所有参数以及可调用对象,附带这些参数调用该可调用对象,并将可调用对象所返回的返回值推入栈顶。在 3.6 版更改: 此操作码仅用于附带位置参数的调用。

  • CALL_FUNCTION_KW(argc)

    调用一个可调用对象并传入位置参数(如果有的话)和关键字参数。 argc 指明位置参数和关键字参数的总数量。 栈顶元素包含一个关键字参数名称的元组。 在元组之下是根据元组排序的关键字参数。 在关键字参数之下是位置参数,其中最右边的参数在最顶端。 在参数之下是一个待调用的可调用对象。 CALL_FUNCTION_KW 会从栈中弹出所有参数以及可调用对象,附带这些参数调用该可调用对象,并将可调用对象所返回的返回值推入栈顶。在 3.6 版更改: 关键字参数会被打包为一个元组而非字典,argc 指明参数的总数量。

  • CALL_FUNCTION_EX(flags)

    调用一个可调用对象并附带位置参数和关键字参数变量集合。 如果设置了 flags 的最低位,则栈顶包含一个由额外关键字参数组成的映射对象。 在该对象之下是一个包含位置参数的可迭代对象和一个待调用的可调用对象。 BUILD_MAP_UNPACK_WITH_CALLBUILD_TUPLE_UNPACK_WITH_CALL 可用于合并多个映射对象和包含参数的可迭代对象。 在该可调用对象被调用之前,映射对象和可迭代对象会被分别“解包”并将它们的内容分别作为关键字参数和位置参数传入。 CALL_FUNCTION_EX 会从栈中弹出所有参数以及可调用对象,附带这些参数调用该可调用对象,并将可调用对象所返回的返回值推入栈顶。3.6 新版功能.

  • LOAD_METHOD(namei)

    从 TOS 对象加载一个名为 co_names[namei] 的方法。 TOS 将被弹出。 此字节码可区分两种情况:如果 TOS 有一个名称正确的方法,字节码会将未绑定方法和 TOS 推入栈顶。 TOS 将在调用未绑定方法时被用作 CALL_METHOD 的第一个参数 (self)。 否则会将 NULL 和属性查找所返回的对象推入栈顶。3.7 新版功能.

  • CALL_METHOD(argc)

    调用一个方法。 argc 是位置参数的数量。 关键字参数不受支持。 此操作码被设计用于配合 LOAD_METHOD 使用。 位置参数放在栈顶。 在它们之下放在栈中的是由 LOAD_METHOD 所描述的两个条目(或者是 self 和一个未绑定方法对象,或者是 NULL 和一个任意可调用对象)。 它们会被全部弹出并将返回值推入栈顶。3.7 新版功能.

  • MAKE_FUNCTION(flags)

    将一个新函数对象推入栈顶。 从底端到顶端,如果参数带有指定的旗标值则所使用的栈必须由这些值组成。0x01 是一个默认值的元组,用于按位置排序的仅限位置形参以及位置或关键字形参0x02 是一个仅限关键字形参的默认值的字典0x04 是一个标注字典0x08 一个包含用于自由变量的单元的元组,生成一个闭包与函数 (在 TOS1) 相关联的代码函数的 qualified name (在 TOS)

  • BUILD_SLICE(argc)

    将一个切片对象推入栈顶。 argc 必须为 2 或 3。 如果为 2,则推入 slice(TOS1, TOS);如果为 3,则推入 slice(TOS2, TOS1, TOS)。 请参阅 slice() 内置函数了解详细信息。

  • EXTENDED_ARG(ext)

    为任意带有大到无法放入默认的单字节的参数的操作码添加前缀。 ext 存放一个附加字节作为参数中的高比特位。 对于每个操作码,最多允许三个 EXTENDED_ARG 前缀,构成两字节到三字节的参数。

  • FORMAT_VALUE(flags)

    用于实现格式化字面值字符串(f-字符串)。 从栈中弹出一个可选的 fmt_spec,然后是一个必须的 valueflags 的解读方式如下:(flags & 0x03) == 0x00: value 按原样格式化。(flags & 0x03) == 0x01: 在格式化 value 之前调用其 str()(flags & 0x03) == 0x02: 在格式化 value 之前调用其 repr()(flags & 0x03) == 0x03: 在格式化 value 之前调用其 ascii()(flags & 0x04) == 0x04: 从栈中弹出 fmt_spec 并使用它,否则使用空的 fmt_spec。使用 PyObject_Format() 执行格式化。 结果会被推入栈顶。3.6 新版功能.

  • HAVE_ARGUMENT

    这不是一个真正的操作码。 它用于标明使用参数和不使用参数的操作码 (分别为 < HAVE_ARGUMENT>= HAVE_ARGUMENT) 之间的分隔线。在 3.6 版更改: 现在每条指令都带有参数,但操作码 < HAVE_ARGUMENT 会忽略它。 之前仅限操作码 >= HAVE_ARGUMENT 带有参数。

操作码集合

提供这些集合用于字节码指令的自动内省:

  • dis.``opname

    操作名称序列,可使用字节码来索引。

  • dis.``opmap

    映射操作名称到字节码的字典

  • dis.``cmp_op

    所有比较操作名称的序列。

  • dis.``hasconst

    访问常量的字节码序列。

  • dis.``hasfree

    访问自由变量的字节码序列(请注意这里所说的‘自由’是指在当前作用域中被内部作用域所引用的名称,或在外部作用域中被此作用域所引用的名称。 它 并不 包括对全局或内置作用域的引用)。

  • dis.``hasname

    按名称访问属性的字节码序列

  • dis.``hasjrel

    具有相对跳转目标的字节码序列。

  • dis.``hasjabs

    具有绝对跳转目标的字节码序列。

  • dis.``haslocal

    访问局部变量的字节码序列。

  • dis.``hascompare

    布尔运算的字节码序列

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/m0_37157335/article/details/124121928

智能推荐

教程 | 使用WeBASE开发智能合约Java应用-程序员宅基地

文章浏览阅读3.3k次,点赞5次,收藏30次。区块链中间件平台WeBASE功能丰富、操作友好,备受社区关注。WeBASE也不断迭代优化,致力于为社区带来更好的开发体验。在 WeBASE 的合约IDE中,“Java项目导出”功能除了提供..._fisco webasefront 导出java项目使用

MATLAB2019b安装详细教程_matlab2019要求配置-程序员宅基地

文章浏览阅读2.9w次,点赞46次,收藏137次。MATLAB2019b安装详细教程 W10 64位Matlab是由美国MathWorks公司出品的著名数学软件,软件的功能性十分强大。其中,MATLAB/Simulink也被某些推文称之万物皆可仿的工具。近年来,自动代码生成在人工智能、深度学习和汽车行业的快速发展,Matlab也变得热度很高,在这里将详细介绍一下Matlab的详细安装步骤和注意点,仅供大家学习交流使用。安装要求和注意点1.安装全程须断网,安装前先关闭360等所有杀毒软件,防止误杀补丁,否则可能安装不成功;2.Matlab2019b适_matlab2019要求配置

CrossOver 22 for Mac/Linux版 v22.1.1中文激活版_crossover22linux下载-程序员宅基地

文章浏览阅读3.2k次,点赞8次,收藏10次。使用 CROSSOVER,在 MAC 运行 WINDOWS 软件是如此容易 CrossOver 可以在 Mac/Linux 上运行成千上万的 Windows 程序。从办公软件、实用工具、游戏到设计软件,您只需在 Mac 的 dock 轻按一下便可运行。您可以 Windows 程序和 Mac 程序之间随意切换,而这一切无需重启、无需虚拟机,也无需购买 Windows 授权。Windows 软件就像 Mac 软件一样运行着,实现跨平台的复制粘贴、文件互通、快捷键和窗口管理。_crossover22linux下载

jdk1.8下载与安装教程(2023最新版)-程序员宅基地

文章浏览阅读4.2w次,点赞36次,收藏120次。JDK是 Java 语言的软件开发工具包,主要用于移动设备、嵌入式设备上的java应用程序。jdk1.8又称jdk8.0,是目前相对比较稳定的版本,不建议下载最新的jdk版本,因为最新版的jdk不稳定,在Java的学习中可能会出现各种各样的问题。_jdk1.8下载

Work Scheduling URAL - 1099 一般图的最大匹配(带花树)_work scheduling二分图-程序员宅基地

文章浏览阅读390次。做了很多二分图了,但是给出的都是没有环的,如果有了环,就不能转化为二分图。所以这就需要一个全新的算法,带花树算法;反正也看不懂,直接套板子把/* ***********************************************Author :kuangbinCreated Time :2013/8/21 22:56:05File Name :_work scheduling二分图

补码与符号位_补码 符号位-程序员宅基地

文章浏览阅读6.7k次。补码与符号位计算机数据的存储使用二进制补码形式存储,并且最高位是符号位,1是负数,0是正数。规定:正数的补码与反码、原码一样,称为三码合一;​ 负数的补码与反码、原码不一样:​ 负数的原码:把十进制转为二进制,然后最高位设置为1​ 负数的反码:在原码的基础上,最高位不变,其余位取反(0变1,1变0)​ 负数的补码:反码+1例如:byte类型(1个字节,8位)25 ==> 原码 0001 1001 ==> 反码 0001 1001 -->补码 _补码 符号位

随便推点

环境光重要性采样_重要性采样 球面采样-程序员宅基地

文章浏览阅读758次。重要性采样概述计算积分需要利用蒙特卡洛方法去近似,蒙特卡洛方法我这里就不讲了,有兴趣的可以看看我的知乎:蒙特卡洛方法的简单总结 - 知乎重要性采样的目的就是加快收敛速度,所以选择pdf比较重要。所以对于环境光采样,我们需要知道环境光每个方向上的概率密度。环境光贴图环境光贴图能用整个球的所有方向去采样,球面方向能转成极坐标θ[0, π]和φ[0, 2π]表示,所以我们用经纬图(long_latitude_map)来做环境光贴图。维度可以用θ,经度用φ,例如地球仪的贴图展开:采样_重要性采样 球面采样

Kettle连接Oracle(Oracle19c&Oracle11g)-程序员宅基地

文章浏览阅读5.2k次,点赞4次,收藏8次。Kettle连接Oracle19c&Oracle11g_kettle连接oracle

WebDav-Milton之一_java webdav milton-程序员宅基地

文章浏览阅读1.6k次。这几篇主要介绍下Milton,一个用java实现了WebDav协议的开源软件,并且可以集成Spring(貌似是唯一一个实现WebDav协议支持Spring) 原文地址:http://milton.io/programs/milton/anno/anno1/pgetting-started-with-annotations.html (原文地址时不时的访问不了) 我的例子是在官网例子上修改的(主_java webdav milton

SpringBoot接收参数的三种方式,SpringBoot访问静态资源。_springboot接收路参-程序员宅基地

文章浏览阅读988次。接收:1、在路由处写好要参数2、参数列表用注解,如果路径上写的参数名称与函数接收的名称不一致可以使用value参数来与路径上的保持一致。_springboot接收路参

vue.config.js 完整配置_vueconfig.js配置文件完整-程序员宅基地

文章浏览阅读936次,点赞2次,收藏5次。vue-cli 3.x 及以上const path = require("path");const resolve = dir => path.join(__dirname, dir);//用于生产环境去除多余的cssconst PurgecssPlugin = require("purgecss-webpack-plugin");//全局文件路径const glob = require("glob-all");//压缩代码并去掉consoleconst UglifyJsPlugin _vueconfig.js配置文件完整

MyBatis-Plus——MyBatis-Plus概述与集成_mybatisplus gitee-程序员宅基地

文章浏览阅读2.2k次,点赞3次,收藏6次。MyBatis-Plus——MyBatis-Plus概述与集成1、MyBatis-Plus概述MyBatis-Plus 是什么MyBatis-Plus(简称MP)是一个 MyBatis的增强工具,在 MyBatis的基础上只做增强( 提供了一些高效、有用、开箱即用的功能)不做改变,为简化开发、提高效率而生。那么它是怎么增强的呢?其实就是它已经封装好了一些crud方法,我们不需要再写xml了,直接调用这些方法就行,就类似于JPA和 tk-mapper。特征与 MyBatis 完全兼容_mybatisplus gitee

推荐文章

热门文章

相关标签