ABSOLUTE with IF statement ? Python 2.5

I have been using 'dis' module in order to re-write some compiled script (.pyc). I understand the difference between JUMP_FORWARD and JUMP_ABSOLUTE. To my knowledge an IF statement will be closed by a 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    

And the JUMP_ABSOLUTE will appear if the IF statement is at the end of another loop. For instance:

>>> 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        

From the Bytecode I am reading to write back the code, there is a JUMP_ABSOLUTE that surprises me:

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      

I would think the code is the following:

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

but it provokes a JUMP_FORWARD and not a JUMP_ABSOLUTE. I know it is not a WHILE loop, nor a FOR statement because they both create a SETUP_LOOP line in the Bytecode.

My question is: what am I missing ? why do I get a FORWARD instead of ABSOLUTE jump ?

EDIT: The absolute jump to index 27 points to the beginning of a (WHILE?) loop in which these two lines 121 and 122 belong to:

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   

There is an IF-statement before and another one after these lines. Here is the code before, with the same JUMP_ABSOLUTE closing the statement.

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             

The JUMP_FORWARD says "go to the next line" and the JUMP_ABSOLUTE says "go back to the beginning of the WHILE loop". Problem is I don't know how to replicate a code that would give the same bytecode as above.

Thank you !


I took the challenge and with your help was able to reproduce your situation (or something very similar) using the following (nonsense) function:

>>> 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

Lines 8 and 11 have the JUMP_ABSOLUTE that you were asking for. Slight differences like LOAD_GLOBAL versus LOAD_FAST are caused by the scope of the variables.

Note that I had to switch to Python 2.5 to reproduce this. Newer versions produce different results.

If continue does not seem to be applicable to your situation, I suggest you do some research in the source code of Python and look for ADDOP_JABS in Python/compile.c to find out in what other cases an absolute jump is inserted.

If your goal is to "just" decompile this .pyc , then you should try uncompyle2 , which describes itself as "A Python 2.5, 2.6, 2.7 byte-code decompiler, written in Python 2.7"

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

上一篇: 我怎样才能让setHeader覆盖现有的头文件?

下一篇: 使用IF语句的ABSOLUTE? Python 2.5