【C  】还我们一个空白的函数!使用NAKED CALL
phpskycn2012/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
已屏蔽 原因:{{ notice.reason }}已屏蔽
{{notice.noticeContent}}
~~空空如也
phpskycn 作者
12年2个月前 IP:未同步
389002
Re:【C  】还我们一个空白的函数!使用NAKED CALL
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
phpskycn作者
12年2个月前 IP:未同步
390548
再来看看编译器生成的代码做了什么
首先
mov esi,esp
保存了栈顶地址
之后把变量pTYPE的地址压入了栈,顺便还压进两个数0x40  0x10,这里明显可以优化,两个push byte完全可以用push dword替代。
之后取了另外一个变量的值并入栈
还调用了一个内存管理函数
最后又保存了esp
很奇怪的是后面部分似乎没用的上面涉及的变量。。。。
难怪不对了,寄存器都动过了还没还原
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
婺源寻芳
12年2个月前 IP:未同步
390570
玩这是不是有点无聊?
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
phpskycn作者
12年2个月前 IP:未同步
391659
回 3楼(婺源寻芳) 的帖子
这个是实际需要
该函数的参数完全以寄存器传递。。。。得保证其未被改动
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
okingkoom
12年2个月前 IP:未同步
391888
Re:回 3楼(婺源寻芳) 的帖子
引用第4楼phpskycn于2012-04-29 22:29发表的 回 3楼(婺源寻芳) 的帖子 :
这个是实际需要
该函数的参数完全以寄存器传递。。。。得保证其未被改动

楼主能否从汇编的层面举例说明,函数的调用不需要使用寄存器?
函数调用返回后,预期以外的寄存器值发生了变化,只能说函数本身有缺陷。
当然也可能是写代码的劳工并不清楚该函数会影响哪些内容而莫名惊诧。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
phpskycn作者
12年2个月前 IP:未同步
392055
回 5楼(okingkoom) 的帖子
有一种情况叫寄存器的值可抛弃。
后面用不着了,改变一下无妨
like:
;1
movzx edx,al
;2
mov edx,pomap[edx *TYPE int]
;3
call edx
3时edx中的数据已经完成了使命,再也用不到了。
部分寄存器就是当缓存用的
陷在C++编译器中后是无可救药的。。。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
phpskycn作者
12年2个月前 IP:未同步
392058
前面已经说得很明白了,编译器自己生成了代码用于平衡堆栈,关函数毛事?
老老实实用C++编写当然没事,因为你不直接操作寄存器。
加上ASM后就不同了
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
okingkoom
12年2个月前 IP:未同步
392070
回 7楼(phpskycn) 的帖子
正常写代码,用到任何寄存器,函数开头都要先push,结束要pop,考虑到堆栈大小,可能有调用函数层数的限制。
何来惊诧?
倒是很诧异楼主为何惊诧。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
phpskycn作者
12年2个月前 IP:未同步
392076
回 8楼(okingkoom) 的帖子
这种行为就是在浪费时间。
寄存器之后有用的保留,无用的抛弃。或者干脆不动那些需要保留的。
具体的策略由需求决定,比如处理顶楼说的问题时后面的函数需要做的基本是处理eax中的数据之后写到特定位置中。写完后eax的里值的数据后面再也用不到了,保留它作什么?
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论

想参与大家的讨论?现在就 登录 或者 注册

所属专业
上级专业
同级专业
phpskycn
专家 老干部 学者 机友 笔友
文章
402
回复
4591
学术分
8
2009/03/15注册,11天16时前活动

CV

主体类型:个人
所属领域:无
认证方式:手机号
IP归属地:未同步
文件下载
加载中...
{{errorInfo}}
{{downloadWarning}}
你在 {{downloadTime}} 下载过当前文件。
文件名称:{{resource.defaultFile.name}}
下载次数:{{resource.hits}}
上传用户:{{uploader.username}}
所需积分:{{costScores}},{{holdScores}}下载当前附件免费{{description}}
积分不足,去充值
文件已丢失

当前账号的附件下载数量限制如下:
时段 个数
{{f.startingTime}}点 - {{f.endTime}}点 {{f.fileCount}}
视频暂不能访问,请登录试试
仅供内部学术交流或培训使用,请先保存到本地。本内容不代表科创观点,未经原作者同意,请勿转载。
音频暂不能访问,请登录试试
支持的图片格式:jpg, jpeg, png
插入公式
评论控制
加载中...
文号:{{pid}}
投诉或举报
加载中...
{{tip}}
请选择违规类型:
{{reason.type}}

空空如也

加载中...
详情
详情
推送到专栏从专栏移除
设为匿名取消匿名
查看作者
回复
只看作者
加入收藏取消收藏
收藏
取消收藏
折叠回复
置顶取消置顶
评学术分
鼓励
设为精选取消精选
管理提醒
编辑
通过审核
评论控制
退修或删除
历史版本
违规记录
投诉或举报
加入黑名单移除黑名单
查看IP
{{format('YYYY/MM/DD HH:mm:ss', toc)}}