2016-12-01 40 views
0

我在C中執行了一些asm代碼中的相對跳轉。我已經按照預期進行了跳躍工作,但在跳轉發生並完成代碼運行後,它會回到正確的位置。C asm jmp在執行jmp後返回jmp

#include <stdio.h> 

void function() { 
    asm("jmp .+0x31"); //this happens to be where I want to jump to from the function call 
} 

void main(int argc, char* argv[]) { 
    int x; 
    x = 0; 
    function(); 
    x = 1; 
    x = x + 1; 
    printf("%d\n", x); 
} 

0x000000000040053f <+0>:  push %rbp 
0x0000000000400540 <+1>:  mov %rsp,%rbp 
0x0000000000400543 <+4>:  sub $0x20,%rsp 
0x0000000000400547 <+8>:  mov %edi,-0x14(%rbp) 
0x000000000040054a <+11>: mov %rsi,-0x20(%rbp) 
0x000000000040054e <+15>: movl $0x0,-0x4(%rbp) 
0x0000000000400555 <+22>: mov $0x0,%eax 
0x000000000040055a <+27>: callq 0x400536 <function> 
0x000000000040055f <+32>: movl $0x1,-0x4(%rbp) 
0x0000000000400566 <+39>: addl $0x1,-0x4(%rbp) 
0x000000000040056a <+43>: mov -0x4(%rbp),%eax 
0x000000000040056d <+46>: mov %eax,%esi 
0x000000000040056f <+48>: mov $0x400620,%edi 
0x0000000000400574 <+53>: mov $0x0,%eax 
0x0000000000400579 <+58>: callq 0x400410 <[email protected]> 
0x000000000040057e <+63>: nop 
0x000000000040057f <+64>: leaveq 
0x0000000000400580 <+65>: retq 

function()調用,它將打印按預期爲0,但隨後又回到通過代碼function()被稱爲並打印2以及之後。我是否缺少jmp的工作原理?有沒有辦法通過asm代碼退出?

這樣做的目的是爲了跳過

x = 1; 
x = x + 1; 

,只是打印0,然後退出文件。

+0

你可以提供反編譯的編譯代碼嗎?另外,你是否嘗試過在程序集級別的調試器中調試,比如gdb?這些東西都應該給你答案。如果你沒有做任何這些事情,你怎麼知道什麼抵消可以跳到,考慮到它可能隨時改變? –

+2

查看生成的代碼,以及函數和跳轉指令與您真正想要跳轉的位置的關係。並且請注意,根據編譯器,編譯器版本以及您傳遞給編譯器的標誌,該位置可能會在沒有警告的情況下更改。 –

+0

看起來像故意破壞你的代碼。你打算用這個代碼做什麼?你認爲跳躍在哪裏?那個地方實際上是什麼?你爲什麼認爲你應該寫這樣的代碼? – Olaf

回答

2

由於function不執行ret指令,其返回地址仍然在堆棧中。也就是說,當main執行ret時,它使用的返回地址實際上是function所留下的地址,並且返回到x = 1;行。

爲了實現您的目標,function在跳轉之前必須調整堆棧指針,就像它從未被調用一樣。

也就是說,不要在家裏試這個

+0

更像是「在家中試用*僅用於實驗」。不要在代碼中使用它,這將成爲任何人都可以用於任何事情的真實程序的一部分,因爲一旦啓用優化,它就會中斷,或者使用不同的編譯器版本來生成甚至稍有不同的asm。 –