使用IF语句的ABSOLUTE? Python 2.5

我一直在使用'dis'模块来重新编写一些编译脚本(.pyc)。 我了解JUMP_FORWARD和JUMP_ABSOLUTE之间的区别。 据我所知,IF声明将由JUMP_FORWARD关闭:

>>> def f():
        if a:
                print ''
>>> from dis import dis
>>> dis(f)
  2           0 LOAD_GLOBAL              0 (a)
              3 JUMP_IF_FALSE            9 (to 15)
              6 POP_TOP             

  3           7 LOAD_CONST               1 ('')
             10 PRINT_ITEM          
             11 PRINT_NEWLINE       
             12 JUMP_FORWARD             1 (to 16)
        >>   15 POP_TOP             
        >>   16 LOAD_CONST               0 (None)
             19 RETURN_VALUE    

如果IF语句位于另一个循环的末尾,则会出现JUMP_ABSOLUTE。 例如:

>>> def f1():
    if a:
        if b:
            print ''
>>> dis(f1)
  2           0 LOAD_GLOBAL              0 (a)
              3 JUMP_IF_FALSE           20 (to 26)
              6 POP_TOP             

  3           7 LOAD_GLOBAL              1 (b)
             10 JUMP_IF_FALSE            9 (to 22)
             13 POP_TOP             

  4          14 LOAD_CONST               1 ('')
             17 PRINT_ITEM          
             18 PRINT_NEWLINE       
             19 JUMP_ABSOLUTE           27
        >>   22 POP_TOP             
             23 JUMP_FORWARD             1 (to 27)
        >>   26 POP_TOP             
        >>   27 LOAD_CONST               0 (None)
             30 RETURN_VALUE        

从我读的代码中读回的Bytecode,有一个令我惊讶的JUMP_ABSOLUTE:

121         228 LOAD_FAST               11 (a)
            231 LOAD_CONST               9 (100)
            234 COMPARE_OP               0 (<)
            237 JUMP_IF_FALSE           23 (to 263)
            240 POP_TOP             
            241 LOAD_FAST               11 (b)
            244 LOAD_CONST              11 (10)
            247 COMPARE_OP               4 (>)
            250 JUMP_IF_FALSE           10 (to 263)
            253 POP_TOP             

122         254 LOAD_CONST               3 (1)
            257 STORE_FAST               4 (ok)
            260 JUMP_ABSOLUTE           27
        >>  263 POP_TOP      

我会认为代码如下:

if a<100 and b>10:
            ok=1

但它引发了JUMP_FORWARD而不是JUMP_ABSOLUTE。 我知道它不是WHILE循环,也不是FOR语句,因为它们都在字节码中创建了一条SETUP_LOOP行。

我的问题是:我错过了什么? 为什么我得到FORWARD而不是ABSOLUTE跳转?

编辑:绝对跳转到索引27指向这两条线121和122所属的(WHILE?)循环的开始:

106          24 SETUP_LOOP             297 (to 324)
        >>   27 LOAD_FAST                4 (ok)
             30 LOAD_CONST               1 (0)
             33 COMPARE_OP               2 (==)
             36 JUMP_IF_FALSE          283 (to 322)
             39 POP_TOP   

这些行之前有一个IF语句和另一个语句。 这是之前的代码,使用相同的JUMP_ABSOLUTE关闭语句。

115         170 LOAD_FAST                3 (q)
            173 LOAD_CONST              10 (1)
            176 COMPARE_OP               0 (<)
            179 JUMP_IF_FALSE           45 (to 227)
            182 POP_TOP             
            183 LOAD_FAST               11 (z)
            186 LOAD_CONST              11 (10)
            189 COMPARE_OP               4 (>)
            192 JUMP_IF_FALSE           32 (to 227)
            195 POP_TOP             

116         196 LOAD_CONST               1 (0)
            199 STORE_FAST               4 (ok)

117         202 LOAD_FAST                5 (u)
            205 LOAD_CONST               3 (1)
            208 BINARY_ADD          
            209 STORE_FAST               5 (u)

118         212 LOAD_CONST               1 (0)
            215 STORE_FAST               3 (k)

119         218 LOAD_CONST               3 (10)
            221 STORE_FAST               6 (dv)
            224 JUMP_ABSOLUTE           27
        >>  227 POP_TOP             

JUMP_FORWARD表示“转到下一行”,JUMP_ABSOLUTE表示“返回到WHILE循环的开始处”。 问题是我不知道如何复制一个能够提供与上面相同的字节码的代码。

谢谢 !


我接受了挑战,在你的帮助下,你可以使用下面的(无意义的)函数重现你的情况(或者类似的东西):

>>> def f():
...    while ok==0:
...      if q<1 and z>10:
...        ok=0
...        u=u+1
...        k=0
...        dv=10
...      elif a<100 and b>10:
...        ok=1
...
>>> dis(f)
  2           0 SETUP_LOOP             112 (to 115)
        >>    3 LOAD_FAST                0 (ok)
              6 LOAD_CONST               1 (0)
              9 COMPARE_OP               2 (==)
             12 JUMP_IF_FALSE           98 (to 113)
             15 POP_TOP

  3          16 LOAD_GLOBAL              0 (q)
             19 LOAD_CONST               2 (1)
             22 COMPARE_OP               0 (<)
             25 JUMP_IF_FALSE           45 (to 73)
             28 POP_TOP
             29 LOAD_GLOBAL              1 (z)
             32 LOAD_CONST               3 (10)
             35 COMPARE_OP               4 (>)
             38 JUMP_IF_FALSE           32 (to 73)
             41 POP_TOP

  4          42 LOAD_CONST               1 (0)
             45 STORE_FAST               0 (ok)

  5          48 LOAD_FAST                1 (u)
             51 LOAD_CONST               2 (1)
             54 BINARY_ADD
             55 STORE_FAST               1 (u)

  6          58 LOAD_CONST               1 (0)
             61 STORE_FAST               2 (k)

  7          64 LOAD_CONST               3 (10)
             67 STORE_FAST               3 (dv)
             70 JUMP_ABSOLUTE            3
        >>   73 POP_TOP

  8          74 LOAD_GLOBAL              2 (a)
             77 LOAD_CONST               4 (100)
             80 COMPARE_OP               0 (<)
             83 JUMP_IF_FALSE           23 (to 109)
             86 POP_TOP
             87 LOAD_GLOBAL              3 (b)
             90 LOAD_CONST               3 (10)
             93 COMPARE_OP               4 (>)
             96 JUMP_IF_FALSE           10 (to 109)
             99 POP_TOP

  9         100 LOAD_CONST               2 (1)
            103 STORE_FAST               0 (ok)
            106 JUMP_ABSOLUTE            3
        >>  109 POP_TOP
            110 JUMP_ABSOLUTE            3
        >>  113 POP_TOP
            114 POP_BLOCK
        >>  115 LOAD_CONST               0 (None)
            118 RETURN_VALUE

第8行和第11行具有您要求的JUMP_ABSOLUTE 。 像LOAD_GLOBALLOAD_FAST类的轻微差异是由变量的范围引起的。

请注意,我不得不切换到Python 2.5来重现这一点。 较新的版本会产生不同的结果。

如果continue似乎不适用于您的情况,我建议您在Python的源代码中进行一些研究,并在Python/compile.c中查找ADDOP_JABS以了解在其他情况下是否插入了绝对跳转。

如果你的目标是“只”反编译这个.pyc ,那么你应该尝试uncompyle2 ,它将自己描述为“用Python 2.7编写的Python uncompyle2字节代码反编译器”

链接地址: http://www.djcxy.com/p/12847.html

上一篇: ABSOLUTE with IF statement ? Python 2.5

下一篇: Firebase import users from existing app