Thunk,thunk,thunk
Thunk,thunk,thunk
---------------------------
作 者:intret
时 间:2011年3月13日星期日
源码格式: VS2008 工程,其实无所谓版本
源码下载:Thunk v0.4 by intret
---------------------------
【摘要】
Thunk是一种技术,你觉得它是不是Knuth(Donald.E.Knuth 爷爷的名字)反过来而得的呢?它做了运行时函数行为的更改,即当执行了Thunk代码,Thunk代码会转而执行类成员函数代码,而这段Thunk代码是精心构造的,包括参数入栈和堆栈平衡工作,当然ATL有ATL的Thunk,我也写了一段。
【用处】
在需要把类成员函数当做普通回调函数来使用的时候,比如窗口过程、线程的Proc、计时器的Proc等),请放心,几行汇编代码并不会影响窗口过程的调用速率。
目录
【摘要】 1
【用处】 1
『一』函数调用约定(Call convention) 2
1.普通回调函数__stdcall方式的调用 2
2.类成员函数__stdcall方式调用 2
『二』汇编指令 3
1.CALL指令 3
2.JMP指令 3
『一』函数调用约定(Call convention)
1.普通回调函数__stdcall方式的调用
CALLBACK在默认情况下被宏定义定义为:__stdcall.我们看窗口过程函数的实现和被调用:
LRESULT CALLBACK WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
return 5;
}
void main()
{
//…主函数的准备工作
WindowProc(NULL, 1, 2, 3);
01361C8E push 3 // 第4个参数入栈
01361C90 push 2 // 第3个参数入栈
01361C92 push 1 // 第2个参数入栈
01361C94 push 0 // 第1个参数入栈
01361C96 call WindowProc (136128Fh) // 调用窗口过程函数,call导致下一条指令地址01361C96+6入栈
}
// …主函数的收尾工作
2.类成员函数__stdcall方式调用
class Wnd
{
public:
int __stdcall WndProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
return 0;
};
};
void main()
{
Wnd wnd;
wnd.WndProc( NULL, 2, 3, 4);
000F13EB push 4
000F13ED push 3
000F13EF push 2
000F13F1 push 0
000F13F3 lea eax,[wnd] // this指针地址
000F13F6 push eax // 至此压入了5个参数,编译器添加了this指针参数
000F13F7 call Wnd::WndProc (0F104Bh)
}
『二』汇编指令
1.CALL指令
call指令会导致『返回地址』(即call的下一条指令的地址)入栈,然后跳转到目标地址执行代码。
2.JMP指令
JMP指令因为有短跳和长跳:可以只修改IP,也可以同时修改CS和IP。
查询Intel80x86 OPCODES.pdf文件,无条件跳转有如下类型,引用如下:
JMP-Unconditional Jump (to sam segment)
short |
1110 1011 : 8-bit displacement |
direct |
1110 1001 : full displacement |
register indirect |
1111 1111 : 11 100 reg |
memory indirect |
1111 1111 : mod 100 r/m |
JMP – Unconditional Jump (to other segment)
direct intersegment |
1110 1010 : unsigned full offset, selector |
indirect intersegment |
1111 1111 : mod 101 r/m |
我们可以获取Wnd::WndProc类成员函数的地址0x0F104B,然后jmp至该地址,jmp之前,堆栈需要满足的条件是:
- 相对于参数入栈前,入栈后堆栈里面多了6个数。(当然call指令导致返回地址入栈也算在其中)
- 第5个入栈的参数是Wnd对象的地址,即this指针。(然后才到call导致的返回地址入栈)
但是,消息处理函数总是会这样调用窗口过程函数,使得窗口过程可以得到消息处理机会:
此时要jmp到Wnd::WndProc之前,堆栈状态不能满足以上条件。
call指令导致的结果是什么呢?我翻开王爽的《汇编语言》,确认了一下它做两件事:
- IP或CS:IP入栈。(导致堆栈状态的变化)
- 转移。(导致目标地址的代码得到执行)
也就是说,返回地址(下一条指令的地址)的入栈是call导致的,那么this指针在call指令之前就可以自由入栈,而且函数局部变量的寻址是根据EBP的偏移定位的。this入栈导致的栈顶指针ESP的变化不会影响局部变量的定位。
回调函数为__stdcall,类成员函数为__stdcall的Thunk code如下:
pthunk |
FF 34 24 |
push |
dword ptr [esp] |
pthunk+3 |
C7 44 24 04 44 33 22 00 |
mov |
dword ptr [esp+4],223344h |
pthunk+11 |
E9 33 22 11 00 |
jmp |
0x00112233 |
I can write no longer…去年非常用心地写,现在已没有兴趣写了,那就共享之,CSDN源码下载地址在上面。
Thunk,thunk,thunk相关推荐
- 在React中加载数据:redux-thunk,redux-saga,suspense,hooks
目录 介绍 初始设置 模拟服务器 项目和API调用 Redux-thunk Redux-saga Suspense Hooks 结论 介绍 React是一个用于构建用户界面的JavaScript库.经 ...
- 关于 redux-thunk 的作用,认识,理解
关于 redux-thunk 的作用,认识,理解 看这篇文章之前,如果你已经看到一些 redux-thunk 的教程,是不是觉得一头雾水,redux-thunk 到底有什么作用,用在哪里,代码不仅没有 ...
- Mysql,SqlServer,Oracle主键自动增长的设置
Mysql,SqlServer,Oracle主键自动增长的设置 参考文献 http://blog.csdn.net/andyelvis/article/details/2446865 1.把主键定义为 ...
- linux启动,重启,停止 jar,.sh脚本
linux启动,重启,停止 jar,.sh脚本 #配置jar名称 APP_NAME=receiver.jar#使用说明,用来提示输入参数 usage() { echo "Usage: sh ...
- 堆栈,数据,文本,heap,bss,text data,stack
堆栈,数据,文本,heap,bss,text data,stack text data bss stack heap 段 根据APUE,程序分为下面的段:.text, data (initialize ...
- TVM示例展示 README.md,Makefile,CMakeLists.txt
TVM示例展示 README.md,Makefile,CMakeLists.txt TVM/README.md Open Deep Learning Compiler Stack Documentat ...
- TVM,Relay,Pass
TVM,Relay,Pass Relay介绍 主要结合TVM的文档(https://tvm.apache.org/docs/dev/relay_intro.html),介绍一下NNVM的第二代Rela ...
- LED芯片,应用品,蓝宝石衬底,集成电路,UV
LED芯片,应用品,蓝宝石衬底,集成电路,UV 三安主要从事全色系超高亮度LED芯片的研发,生产与销售,产品性能稳定,品质优异. 产品覆盖 三安能够提供全波长范围的LED,产品可覆盖全部可见光和不可见 ...
- CPU,GPU,Memory调度
CPU,GPU,Memory调度 HDD&Memory&CPU调度机制(I/O硬件性能瓶颈) 图1. HDD&Memory&CPU调度图 CPU主要就是三部分:计算单元 ...
- 自动驾驶QNX,Linux,Autosar概述
自动驾驶QNX,Linux,Autosar概述 QNX是一个分布式.嵌入式.可规模扩展的实时操作系统.遵循POSIX.1 (程序接口)和POSIX.2 (Shell和工具).部分遵循POSIX.1b( ...
最新文章
- 贪心:expedition 最优加油方法
- 南农Nature Microbiology一作顾少华:我与铁载体的这5年
- 【笔记】与Android酱的第一周
- 第16天学习Java的笔记(标准类,Scanner)
- 100米队伍,从队伍后到前_我们的队伍
- Ubuntu13下调试USB AUDIO的一些记录
- mysql插入日期_初识MySQL
- docker部署redis集群_Docker部署Redis集群----第九节(docker-redis哨兵集群“轮询分流”篇实例一)...
- arraylist扩容是创建新数组吗 java_Java集合干货——ArrayList源码分析
- 最新快手JS逆向分析
- matlab gui怎样将结果保存_Processing将串行数据保存用作matlab数据分析
- python优先级排序_用Python实现优先级队列的3种方法
- python项目代做_ECS 170代做、代写Python、data代做、代做Python程序代写Web开发|代写Database...
- 协同oa办公系统在线演示下载地址
- 阿里月饼事件,猿方怎么看?
- 利用INFOPATH2007VS2005开发MOSS工作流详解 --收藏
- Php 类似coffeescript,有什么东西像CoffeeScript for PHP吗?
- 2020最新版python基础入门学习视频教程
- MOSFET原理与应用
- 5G LAN — 技术实现原理