Toggle navigation
科创
{{ getSearchSuggestionLabel(suggestion) }}
{{ part.text }}
查看更多
登录
 
注册
电波
论坛
专栏
应用
登录
注册
{{ getSearchSuggestionLabel(suggestion) }}
{{ part.text }}
查看更多
论坛
>
计算机科学
>
软件综合
文号
t43442
阅读
5415
回复
10
收藏
3
【C  】还我们一个空白的函数!使用NAKED CALL
phpskycn
2012/04/20
软件综合
IP:浙江
TAG:naked call|naked function|VC|空函数
今天继续调试代码,发现一个奇怪的问题:寄存器里的值在call后会立刻改变,让人百思不得其解,于是只好使用反汇编,发现VC++居然在不知不觉中给一个void型且未使用任何变量的函数添加了一些指令:
0122B2D5 8B F4 mov esi,esp
0122B2D7 68 A0 10 2B 01 push offset pTYPE (12B10A0h)
0122B2DC 6A 40 push 40h
0122B2DE 6A 10 push 10h
0122B2E0 8B 45 F8 mov eax,dword ptr [pintcache]
0122B2E3 50 push eax
0122B2E4 FF 15 10 92 2C 01 call dword ptr [__imp__VirtualProtect@16 (12C9210h)]
0122B2EA 3B F4 cmp esi,esp
0122B2EC E8 D2 D1 FF FF call @ILT+5310(__RTC_CheckEsp) (12284C3h
__asm{...}
难怪,寄存器已经被动过了,当然不对了。
好在MS设计的编译器不是太傻,留了后路,可以使用naked function(naked call)调用
首先得在程序开头加上一句:
#define Naked __declspec( naked )
之后,修改函数定义,在之前加上__declspec( naked )
如
void vmload(){...}
__declspec( naked )void vmload(){...}
注意,必须在函数定义处使用__declspec( naked ),不能再声明处。
好了,这下函数开头处就是空白的。
不过要注意,加上__declspec( naked )后得自己进行一些工作,处理堆栈。
另外return;也不能使用,得自己加上ret。
ENDL
来自:
计算机科学
/
软件综合
10
0
全部
只看作者
phpskycn
作者
14年8个月前
IP:未同步
389002
1楼
Re:【C  】还我们一个空白的函数!使用NAKED CALL
MSDN上关于Naked call的内容:
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
加载全文
引用
评论
0
phpskycn
作者
14年8个月前
IP:未同步
390548
2楼
再来看看编译器生成的代码做了什么
首先
mov esi,esp
保存了栈顶地址
之后把变量pTYPE的地址压入了栈,顺便还压进两个数0x40 0x10,这里明显可以优化,两个push byte完全可以用push dword替代。
之后取了另外一个变量的值并入栈
还调用了一个内存管理函数
最后又保存了esp
很奇怪的是后面部分似乎没用的上面涉及的变量。。。。
难怪不对了,寄存器都动过了还没还原
加载全文
引用
评论
0
phpskycn
作者
14年8个月前
IP:未同步
391659
4楼
回 3楼(婺源寻芳) 的帖子
这个是实际需要
该函数的参数完全以寄存器传递。。。。得保证其未被改动
加载全文
引用
评论
0
phpskycn
作者
14年8个月前
IP:未同步
392055
6楼
回 5楼(okingkoom) 的帖子
有一种情况叫寄存器的值可抛弃。
后面用不着了,改变一下无妨
like:
;1
movzx edx,al
;2
mov edx,pomap[edx *TYPE int]
;3
call edx
3时edx中的数据已经完成了使命,再也用不到了。
部分寄存器就是当缓存用的
陷在C++编译器中后是无可救药的。。。
加载全文
引用
评论
0
phpskycn
作者
14年8个月前
IP:未同步
392058
7楼
前面已经说得很明白了,编译器自己生成了代码用于平衡堆栈,关函数毛事?
老老实实用C++编写当然没事,因为你不直接操作寄存器。
加上ASM后就不同了
加载全文
引用
评论
0
phpskycn
作者
14年8个月前
IP:未同步
392076
9楼
回 8楼(okingkoom) 的帖子
这种行为就是在浪费时间。
寄存器之后有用的保留,无用的抛弃。或者干脆不动那些需要保留的。
具体的策略由需求决定,比如处理顶楼说的问题时后面的函数需要做的基本是处理eax中的数据之后写到特定位置中。写完后eax的里值的数据后面再也用不到了,保留它作什么?
加载全文
引用
评论
0
全部
只看作者
在列表中查看
笔记
{{note.content}}
{{n.user.username}}
{{fromNow(n.toc)}} {{n.status === noteStatus.disabled ? "已屏蔽" : ""}} {{n.status === noteStatus.unknown ? "正在审核" : ""}} {{n.status === noteStatus.deleted ? '已删除' : ''}}
编辑
删除
{{n.status === 'disabled' ? "解除屏蔽" : "屏蔽" }}
保存
取消
我也是有底线的
保存中...
保存