环境

vs2019 编译选项x86(32位) debug版本

float指令练习

//c++源码
#include<stdio.h>
int main(int argc,char* argv)
{
float f = (float)argc;//将int类型转换为float printf("%f",f); argc = (int)f;//在将float类型转换为int printf("%d",argc); return 0;
}

编译运行后,在return 0;语句打一个断点,右键可以看到切到汇编代码

对应的汇编代码如下

00183E40 55                   push        ebp
00183E41 8B EC mov ebp,esp
00183E43 81 EC CC 00 00 00 sub esp,0CCh
00183E49 53 push ebx
00183E4A 56 push esi
00183E4B 57 push edi
00183E4C 8D 7D F4 lea edi,[ebp-0Ch]
00183E4F B9 03 00 00 00 mov ecx,3
00183E54 B8 CC CC CC CC mov eax,0CCCCCCCCh
00183E59 F3 AB rep stos dword ptr es:[edi]
00183E5B B9 03 C0 18 00 mov ecx,offset _78F0D3D6_helloworld@c (018C003h)
00183E60 E8 A2 D4 FF FF call @__CheckForDebuggerJustMyCode@4 (0181307h)
4: float f = (float)argc;
00183E65 F3 0F 2A 45 08 cvtsi2ss xmm0,dword ptr [argc] //[argc]对应是[ebp+8] cvsi2ss指令:将整数转换为单精度数int强制转为float
00183E6A F3 0F 11 45 F8 movss dword ptr [f],xmm0//[f] 对应的是[ebp-4] //movss指令:用来传送单精度数,用来转送float
5: printf("%f",f);
00183E6F F3 0F 5A 45 F8 cvtss2sd xmm0,dword ptr [f]
00183E74 83 EC 08 sub esp,8
00183E77 F2 0F 11 04 24 movsd mmword ptr [esp],xmm0//movsd指令:传送双精度数
00183E7C 68 CC 7B 18 00 push offset string "%f" (0187BCCh)
00183E81 E8 17 D5 FF FF call _printf (018139Dh)
00183E86 83 C4 0C add esp,0Ch //外平栈
6: argc = (int)f;
00183E89 F3 0F 2C 45 F8 cvttss2si eax,dword ptr [f]//cvttss2si将float类型转换为int类型
00183E8E 89 45 08 mov dword ptr [argc],eax
7: printf("%d",argc);
00183E91 8B 45 08 mov eax,dword ptr [argc]
00183E94 50 push eax
00183E95 68 D0 7B 18 00 push offset string "%d" (0187BD0h)
00183E9A E8 FE D4 FF FF call _printf (018139Dh)
00183E9F 83 C4 08 add esp,8
8: return 0;
00183EA2 33 C0 xor eax,eax
9: }
00183EA4 5F pop edi
00183EA5 5E pop esi
00183EA6 5B pop ebx
00183EA7 81 C4 CC 00 00 00 add esp,0CCh
00183EAD 3B EC cmp ebp,esp
00183EAF E8 7C D3 FF FF call __RTC_CheckEsp (0181230h)
00183EB4 8B E5 mov esp,ebp
00183EB6 5D pop ebp
00183EB7 C3 ret

上面的代码:浮点数与整数、整数与浮点数的相互转换,从上面可以看到float类型占4字节,但是使用浮点栈将以8字节方式进行处理(movsd),而使用媒体寄存器则以4字节处理。当浮点数作为参数时,并不能直接入栈,PUSH指令只能传入4字节数据到栈。这样会丢失4字节数据。这就是使用printf函数以整数方式输出浮点数时会产生错误的原因。printf以整数方式输出时,将对应参数作为4字节数据长度,按补码范式解释,而真正压入的参数为浮点类型时,却是8字节长度,需要按浮点编码范式解释。

如何找到main函数

在大学中我们老师都教授我们一个函数的入口函数是main,但是呢今天我们来看看到底是不是。拿出工具x32dbug来进行测试

第一步

第二步进来以后初始的状态



是一个ntdll.dll是重要的Windows NT内核级文件。描述了windows本地NTAPI的接口。当Windows启动时,ntdll.dll就驻留在内存中特定的写保护区域,使别的程序无法占用这个内存区域。

第三步 快捷按F9



我们可以看到是一个._mainCRTStartup>,那么我们在进去(F9)

第三步



.__scrt_common main>,我们再次进去(F9)

第四步



_scrt_common_main_seh>

第五步



其中包含了.main函数,那么我们就算找到了main

00183E4 | 55                      | push ebp                                      | helloworld.c:3
00183E4 | 8BEC | mov ebp,esp |
00183E4 | 81EC CC000000 | sub esp,CC |
00183E4 | 53 | push ebx |
00183E4 | 56 | push esi | esi:__enc$textbss$end+23
00183E4 | 57 | push edi | edi:__enc$textbss$end+23
00183E4 | 8D7D F4 | lea edi,dword ptr ss:[ebp-C] | edi:__enc$textbss$end+23
00183E4 | B9 03000000 | mov ecx,3 |
00183E5 | B8 CCCCCCCC | mov eax,CCCCCCCC | eax:&"E:\\c++反汇编技术加密与解密\\shujutype\\Debug\\shujutype.exe"
00183E5 | F3:AB | rep stosd |
00183E5 | B9 03C01800 | mov ecx,<shujutype._78F0D3D6_helloworld@c> | helloworld.c:15732480
00183E6 | E8 A2D4FFFF | call shujutype.181307 |
00183E6 | F3:0F2A45 08 | cvtsi2ss xmm0,dword ptr ss:[ebp+8] | helloworld.c:4
00183E6 | F3:0F1145 F8 | movss dword ptr ss:[ebp-8],xmm0 | [ebp-8]:&"E:\\c++反汇编技术加密与解密\\shujutype\\Debug\\shujutype.exe"
00183E6 | F3:0F5A45 F8 | cvtss2sd xmm0,dword ptr ss:[ebp-8] | helloworld.c:5, [ebp-8]:&"E:\\c++反汇编技术加密与解密\\shujutype\\Debug\\shujutype.exe"
00183E7 | 83EC 08 | sub esp,8 |
00183E7 | F2:0F110424 | movsd qword ptr ss:[esp],xmm0 |
00183E7 | 68 CC7B1800 | push shujutype.187BCC |
00183E8 | E8 17D5FFFF | call shujutype.18139D |
00183E8 | 83C4 0C | add esp,C |
00183E8 | F3:0F2C45 F8 | cvttss2si eax,dword ptr ss:[ebp-8] | helloworld.c:6, [ebp-8]:&"E:\\c++反汇编技术加密与解密\\shujutype\\Debug\\shujutype.exe"
00183E8 | 8945 08 | mov dword ptr ss:[ebp+8],eax |
00183E9 | 8B45 08 | mov eax,dword ptr ss:[ebp+8] | helloworld.c:7
00183E9 | 50 | push eax | eax:&"E:\\c++反汇编技术加密与解密\\shujutype\\Debug\\shujutype.exe"
00183E9 | 68 D07B1800 | push shujutype.187BD0 |
00183E9 | E8 FED4FFFF | call shujutype.18139D |
00183E9 | 83C4 08 | add esp,8 |
00183EA | 33C0 | xor eax,eax | helloworld.c:8, eax:&"E:\\c++反汇编技术加密与解密\\shujutype\\Debug\\shujutype.exe"
00183EA | 5F | pop edi | helloworld.c:9, edi:__enc$textbss$end+23
00183EA | 5E | pop esi | esi:__enc$textbss$end+23
00183EA | 5B | pop ebx |
00183EA | 81C4 CC000000 | add esp,CC |
00183EA | 3BEC | cmp ebp,esp |
00183EA | E8 7CD3FFFF | call shujutype.181230 |
00183EB | 8BE5 | mov esp,ebp |
00183EB | 5D | pop ebp |
00183EB | C3 | ret |

与我们编译好的一摸一样,那么我们就可以确定是main函数

总结

main函数是语法规定的用户入口,而真正的入口函数是mainCRTStartup,mainCRTStarup再次调用main函数。

浮点指令之找main函数的更多相关文章

  1. 【逆向知识】VS程序反汇编找main函数

    工具:OllyICE 调试快捷键说明: F2键:设置断点,只要在光标定位的位置 F4键:程序运行到光标处 F7键:单步步入.功能同单步步过(F8)类似,区别是遇到 CALL 等子程序时会进入其中,进入 ...

  2. exe怎么找main函数

    先说DEBUG版本的命令行EXE main函数有两种,第一种是int main(),第二种是int main(int argc,char* argv[]) 不管哪种只要查找j___p___argc就能 ...

  3. 【逆向工具】IDA使用2-VS2015版本release查找main函数入口,局部变量

    VS2015版本release查找main函数入口 vc++开发的程序main或WinMain函数是语法规定的用户入口,而不是应用程序入口.入口代码是mainCRTstartup.wmainCRTSt ...

  4. 06_传智播客iOS视频教程_源文件后缀名和main函数

    OC与C语言的不同. 把OC程序运行起来,CPU只会找main函数.并且只会执行main函数当中的代码.当main函数的代码执行完毕之后这个程序就自动结束掉了. main函数的参数是可以让我们在运行程 ...

  5. 在有main函数的前提下 eclipse找不到主类

    有时候在测试类的时候eclipse会莫名奇妙的提示找不到主类   接下来分别有几种解决办法 1.在项目上右击> Builder Path -> Configure Build Path - ...

  6. [汇编与C语言关系]2. main函数与启动例程

    为什么汇编程序的入口是_start,而C程序的入口是main函数呢?以下就来解释这个问题 在<x86汇编程序基础(AT&T语法)>一文中我们汇编和链接的步骤是: $ as hell ...

  7. main函数和启动例程

    为什么汇编程序的入口是_start,而C程序的入口是main函数呢?本节就来解释这个问题.在讲例 18.1 “最简单的汇编程序”时,我们的汇编和链接步骤是: $ as hello.s -o hello ...

  8. 为什么c程序里一定要写main函数

    一. 学习过程 编写程序f.c: 对其进行编译,正常通过,再对其进行连接,出现错误: 显示的出错信息为: 翻译成中文是:在c0s模块没有定义符号’_main’. 那么这个错误信息可能与文件c0s.ob ...

  9. C语言编程漫谈——main函数

    写在前面 促使我写这篇文章是因为我这几天找了几个一样是大三的同学,与我相同专业相同方向(物联网)的人,除了@小胡同的诗,基本没有什么其他人会现在看起来很简单的编程题目了.问了一下其他同学,他们大部分都 ...

  10. 通过启动函数定位main()函数

      如下,通过vc6.0编写一个hello world程序.尝试结合汇编代码.分析启动函数找到main函数.   在printf(xxx)插入断点,调试执行.如下,在堆栈窗口中可见main()下的一个 ...

随机推荐

  1. 全平台数据(数据库)管理工具 DataCap 管理 Rainbond 上的所有数据库

    DataCap是用于数据转换.集成和可视化的集成软件,支持多种数据源.文件类型.大数据相关数据库.关系数据库.NoSQL数据库等.通过该 DataCap 可以实现对多个数据源的管理,对数据源下的数据进 ...

  2. js计算当前时间差

    1 function timesFun(timesData) { 2 //如果时间格式是正确的,那下面这一步转化时间格式就可以不用了 3 var dateBegin = new Date(timesD ...

  3. Python 变量作用域和列表

    变量作用域 变量由作用范围限制 分类:按照作用域分类 全局(global):在函数外部定义 局部(local):在函数内部定义 变量的作用范围: 全局变量:在整个全局范围有效 全局碧昂量在局部可以使用 ...

  4. 再解 [NOI2017] 整数

    提供一个来自 CF 大佬 adament 的有趣思路. 首先我们知道的是一个只增加的 \(b\) 进制整数计数器,如果 \(b\) 是常数那么复杂度是均摊 \(O(1)\) 的.证明只需要考虑将 \( ...

  5. P1014 [NOIP1999 普及组] Cantor 表

    题目链接:https://www.luogu.com.cn/problem/P1014 有理数可枚举 In 1873 Cantor proved the rational numbers counta ...

  6. OceanBase的学习与使用

    OceanBase的学习与使用 简介 1. OceanBase数据库 注意这一块下载的其实是rpm包. 一般是通过下面的OAT或者是OCP工具进行安装. 有x86还有ARM两种架构. 虽然是el7结尾 ...

  7. mapper中sql返回类型是integer,但是sql查询结果是null,报错

    1.出问题代码 当sql返回结果为null时报错    org.apache.ibatis.binding.BindingException: Mapper method 'com.yswl.scie ...

  8. 2022-12-25:etcd可以完全替代zookeeper,原因是k8s用的etcd,不用担心不成熟。请问etcd部署在k3s中,yaml如何写?

    2022-12-25:etcd可以完全替代zookeeper,原因是k8s用的etcd,不用担心不成熟.请问etcd部署在k3s中,yaml如何写? 答案2022-12-25: 用户名:root 密码 ...

  9. 2020-01-25:redis中,哨兵如何选举?

    福哥答案2020-01-25: [答案1:](https://bbs.csdn.net/topics/398982967)redis-sentinel故障转移的流程:1.当多个sentinel发现并确 ...

  10. 2020-01-20:mysql中,一张表里有3亿数据,未分表,要求是在这个大表里添加一列数据。数据库不能停,并且还有增删改操作。请问如何操作?

    2020-01-20:mysql中,一张表里有3亿数据,未分表,要求是在这个大表里添加一列数据.数据库不能停,并且还有增删改操作.请问如何操作?福哥答案2020-01-20: 陌陌答案:用pt_onl ...