今天看了点汇编的东西,上面写着jmp指令后面为偏移地址,这与反汇编代码中看到的汇编语言不太相符啊?不管我们自己写汇编还是使用反编译器查看汇编代码,jmp指令后面写的都是绝对地址啊!其实之前也想过这个问题,在理解WTL Thunk机制时,jmp机器码后面接的是相对偏移地址,但当时没有深究。为了便于研究,写了如下代码
#include "stdafx.h"
int fun(int a, int b)
{
return a+b;
}
int _tmain(int argc, _TCHAR* argv[])
{
int i = 0;
int j=1;
__asm
{
jmp fun
}
i = 1;
j = 2;
__asm
{
jmp fun
}
return 0;
}
调试运行查看反汇编
int _tmain(int argc, _TCHAR* argv[])
{
00211010 55 push ebp
00211011 8B EC mov ebp,esp
00211013 83 EC 08 sub esp,8
int i = 0;
00211016 C7 45 FC 00 00 00 00 mov dword ptr [i],0
int j=1;
0021101D C7 45 F8 01 00 00 00 mov dword ptr [j],1
__asm
{
jmp fun
00211024 E9 D7 FF FF FF jmp fun (211000h)
}
i = 1;
00211029 C7 45 FC 01 00 00 00 mov dword ptr [i],1
j = 2;
00211030 C7 45 F8 02 00 00 00 mov dword ptr [j],2
__asm
{
jmp fun
00211037 E9 C4 FF FF FF jmp fun (211000h)
}
return 0;
0021103C 33 C0 xor eax,eax
}
0021103E 8B E5 mov esp,ebp
00211040 5D pop ebp
00211041 C3 ret
可以看到jmp虽然都是跳转到fun函数,但是机器码jmp(E9)后面的操作数是不同的。操作数就是跳转指令的结束地址与跳转函数间的偏移量。
另外,call指令也采用了同样的方法。
//这么快就有两个人读了本Blog了? 对不起了,哈哈哈,以上说的有毛病
call指令其实有很多种写法,可以是指定偏移,也可以是绝对地址
有一篇文章写得很好, 叫
CALL指令有多少种写法_百度文库, 请百度之并阅读之,反正我是没怎么看。
我有测试了一下,jmp和call指令一样,同样是生成多种多样的汇编码
例如上例中jmp被编译为E9, 后面操作数为偏移地址
而如果汇编语言为jmp dword ptr [k] 或者 jmp ecx, jmp就会被编译FF??,若有操作数的话,为绝对地址。