标题: Python3利用opcode模块获取指令信息 创建: 2023-05-19 10:39 更新: 2023-05-24 10:21 链接: https://scz.617.cn/python/202305191039.txt -------------------------------------------------------------------------- import opcode exinfo = [attr for attr in dir(opcode) if attr.startswith("has")] def getex ( op ) : if op >= opcode.HAVE_ARGUMENT : for ex in exinfo : if op in getattr( opcode, ex ) : return ex return None def get_stack_effect ( op ) : if op < opcode.HAVE_ARGUMENT : se = '%d' % opcode.stack_effect( op ) else : if op in opcode.hasjrel or op in opcode.hasjabs : se = '%d %d' % \ ( opcode.stack_effect( op, 0, jump=True ), opcode.stack_effect( op, 0, jump=False ) ) else : se = '%d' % opcode.stack_effect( op, 4 ) return se for k, v in opcode.opmap.items() : ex = getex( v ) se = get_stack_effect( v ) if ex is None : print( '0x%02x (%3d) %s (%s)' % ( v, v, k, se ) ) else : print( '0x%02x (%3d) %s (%s) (%s)' % ( v, v, k, ex, se ) ) -------------------------------------------------------------------------- 以Python 3.9为例,执行上述代码,输出如下 0x01 ( 1) POP_TOP (-1) 0x02 ( 2) ROT_TWO (0) 0x03 ( 3) ROT_THREE (0) 0x04 ( 4) DUP_TOP (1) 0x05 ( 5) DUP_TOP_TWO (2) 0x06 ( 6) ROT_FOUR (0) 0x09 ( 9) NOP (0) 0x0a ( 10) UNARY_POSITIVE (0) 0x0b ( 11) UNARY_NEGATIVE (0) 0x0c ( 12) UNARY_NOT (0) 0x0f ( 15) UNARY_INVERT (0) 0x10 ( 16) BINARY_MATRIX_MULTIPLY (-1) 0x11 ( 17) INPLACE_MATRIX_MULTIPLY (-1) 0x13 ( 19) BINARY_POWER (-1) 0x14 ( 20) BINARY_MULTIPLY (-1) 0x16 ( 22) BINARY_MODULO (-1) 0x17 ( 23) BINARY_ADD (-1) 0x18 ( 24) BINARY_SUBTRACT (-1) 0x19 ( 25) BINARY_SUBSCR (-1) 0x1a ( 26) BINARY_FLOOR_DIVIDE (-1) 0x1b ( 27) BINARY_TRUE_DIVIDE (-1) 0x1c ( 28) INPLACE_FLOOR_DIVIDE (-1) 0x1d ( 29) INPLACE_TRUE_DIVIDE (-1) 0x30 ( 48) RERAISE (-3) 0x31 ( 49) WITH_EXCEPT_START (1) 0x32 ( 50) GET_AITER (0) 0x33 ( 51) GET_ANEXT (1) 0x34 ( 52) BEFORE_ASYNC_WITH (1) 0x36 ( 54) END_ASYNC_FOR (-7) 0x37 ( 55) INPLACE_ADD (-1) 0x38 ( 56) INPLACE_SUBTRACT (-1) 0x39 ( 57) INPLACE_MULTIPLY (-1) 0x3b ( 59) INPLACE_MODULO (-1) 0x3c ( 60) STORE_SUBSCR (-3) 0x3d ( 61) DELETE_SUBSCR (-2) 0x3e ( 62) BINARY_LSHIFT (-1) 0x3f ( 63) BINARY_RSHIFT (-1) 0x40 ( 64) BINARY_AND (-1) 0x41 ( 65) BINARY_XOR (-1) 0x42 ( 66) BINARY_OR (-1) 0x43 ( 67) INPLACE_POWER (-1) 0x44 ( 68) GET_ITER (0) 0x45 ( 69) GET_YIELD_FROM_ITER (0) 0x46 ( 70) PRINT_EXPR (-1) 0x47 ( 71) LOAD_BUILD_CLASS (1) 0x48 ( 72) YIELD_FROM (-1) 0x49 ( 73) GET_AWAITABLE (0) 0x4a ( 74) LOAD_ASSERTION_ERROR (1) 0x4b ( 75) INPLACE_LSHIFT (-1) 0x4c ( 76) INPLACE_RSHIFT (-1) 0x4d ( 77) INPLACE_AND (-1) 0x4e ( 78) INPLACE_XOR (-1) 0x4f ( 79) INPLACE_OR (-1) 0x52 ( 82) LIST_TO_TUPLE (0) 0x53 ( 83) RETURN_VALUE (-1) 0x54 ( 84) IMPORT_STAR (-1) 0x55 ( 85) SETUP_ANNOTATIONS (0) 0x56 ( 86) YIELD_VALUE (0) 0x57 ( 87) POP_BLOCK (0) 0x59 ( 89) POP_EXCEPT (-3) 0x5a ( 90) STORE_NAME (hasname) (-1) 0x5b ( 91) DELETE_NAME (hasname) (0) 0x5c ( 92) UNPACK_SEQUENCE (3) 0x5d ( 93) FOR_ITER (hasjrel) (-1 1) 0x5e ( 94) UNPACK_EX (4) 0x5f ( 95) STORE_ATTR (hasname) (-2) 0x60 ( 96) DELETE_ATTR (hasname) (-1) 0x61 ( 97) STORE_GLOBAL (hasname) (-1) 0x62 ( 98) DELETE_GLOBAL (hasname) (0) 0x64 (100) LOAD_CONST (hasconst) (1) 0x65 (101) LOAD_NAME (hasname) (1) 0x66 (102) BUILD_TUPLE (-3) 0x67 (103) BUILD_LIST (-3) 0x68 (104) BUILD_SET (-3) 0x69 (105) BUILD_MAP (-7) 0x6a (106) LOAD_ATTR (hasname) (0) 0x6b (107) COMPARE_OP (hascompare) (-1) 0x6c (108) IMPORT_NAME (hasname) (-1) 0x6d (109) IMPORT_FROM (hasname) (1) 0x6e (110) JUMP_FORWARD (hasjrel) (0 0) 0x6f (111) JUMP_IF_FALSE_OR_POP (hasjabs) (0 -1) 0x70 (112) JUMP_IF_TRUE_OR_POP (hasjabs) (0 -1) 0x71 (113) JUMP_ABSOLUTE (hasjabs) (0 0) 0x72 (114) POP_JUMP_IF_FALSE (hasjabs) (-1 -1) 0x73 (115) POP_JUMP_IF_TRUE (hasjabs) (-1 -1) 0x74 (116) LOAD_GLOBAL (hasname) (1) 0x75 (117) IS_OP (-1) 0x76 (118) CONTAINS_OP (-1) 0x79 (121) JUMP_IF_NOT_EXC_MATCH (hasjabs) (-2 -2) 0x7a (122) SETUP_FINALLY (hasjrel) (6 0) 0x7c (124) LOAD_FAST (haslocal) (1) 0x7d (125) STORE_FAST (haslocal) (-1) 0x7e (126) DELETE_FAST (haslocal) (0) 0x82 (130) RAISE_VARARGS (-4) 0x83 (131) CALL_FUNCTION (-4) 0x84 (132) MAKE_FUNCTION (-2) 0x85 (133) BUILD_SLICE (-1) 0x87 (135) LOAD_CLOSURE (hasfree) (1) 0x88 (136) LOAD_DEREF (hasfree) (1) 0x89 (137) STORE_DEREF (hasfree) (-1) 0x8a (138) DELETE_DEREF (hasfree) (0) 0x8d (141) CALL_FUNCTION_KW (-5) 0x8e (142) CALL_FUNCTION_EX (-1) 0x8f (143) SETUP_WITH (hasjrel) (6 1) 0x91 (145) LIST_APPEND (-1) 0x92 (146) SET_ADD (-1) 0x93 (147) MAP_ADD (-2) 0x94 (148) LOAD_CLASSDEREF (hasfree) (1) 0x90 (144) EXTENDED_ARG (0) 0x9a (154) SETUP_ASYNC_WITH (hasjrel) (5 0) 0x9b (155) FORMAT_VALUE (-1) 0x9c (156) BUILD_CONST_KEY_MAP (-4) 0x9d (157) BUILD_STRING (-3) 0xa0 (160) LOAD_METHOD (hasname) (1) 0xa1 (161) CALL_METHOD (-5) 0xa2 (162) LIST_EXTEND (-1) 0xa3 (163) SET_UPDATE (-1) 0xa4 (164) DICT_MERGE (-1) 0xa5 (165) DICT_UPDATE (-1) 部分指令第4列出现hasconst、hasname这类信息,编写反汇编器、反编译器时需要 -------------------------------------------------------------------------- hasconst co_consts[] // oparg是co_consts[]的索引 hasname co_names[] // oparg是co_names[]的索引 haslocal co_varnames[] hasfree co_cellvars[]+co_freevars[] hasjrel 相对跳转 // oparg是相对偏移 hasjabs 绝对跳转 // oparg是绝对地址 hascompare 比较指令 -------------------------------------------------------------------------- 所有指令最后一列反映该指令对数据栈的影响,编写反编译器时需要。1表示有一个 压栈动作,-1表示有一个弹栈动作。若是跳转类指令,第1个数字对应跳转时栈变化, 第2个数字对应未跳转时栈变化。也可从解释器源码ceval.c、compile.c获取栈变化 信息,只不过利用opcode模块获取更便捷。 如下指令的栈变化随oparg而变化,前述结果只是oparg为4时的情形 -------------------------------------------------------------------------- 0x5c ( 92) UNPACK_SEQUENCE (oparg-1) 0x5e ( 94) UNPACK_EX ((oparg & 0xff)+(oparg>>8)) 0x66 (102) BUILD_TUPLE (1-oparg) 0x67 (103) BUILD_LIST (1-oparg) 0x68 (104) BUILD_SET (1-oparg) 0x69 (105) BUILD_MAP (1-2*oparg) 0x82 (130) RAISE_VARARGS (-oparg) 0x83 (131) CALL_FUNCTION (-oparg) 0x84 (132) MAKE_FUNCTION (-1-((oparg & 0x01)!=0)-((oparg & 0x02)!=0)-((oparg & 0x04)!=0)-((oparg & 0x08)!=0)) 0x85 (133) BUILD_SLICE (oparg==3 ? -2 : -1) 0x8d (141) CALL_FUNCTION_KW (-oparg-1) 0x8e (142) CALL_FUNCTION_EX (-1-((oparg & 0x01)!=0)) 0x9b (155) FORMAT_VALUE ((oparg & 4)==4 ? -1 : 0) 0x9c (156) BUILD_CONST_KEY_MAP (-oparg) 0x9d (157) BUILD_STRING (1-oparg) 0xa1 (161) CALL_METHOD (-oparg-1) --------------------------------------------------------------------------