环境

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. Linux 阶段二

    1.2 安装JDK JDK具体安装步骤如下: 1). 上传安装包 使用FinalShell自带的上传工具将jdk的二进制发布包上传到Linux 由于上述在进行文件上传时,选择的上传目录为根目录 /,上 ...

  2. Django简介 安装下载 app概念 主要目录介绍

    目录 Django简介 前戏 Django是一个开放源代码的Web应用框架,由Python写成.采用了MTV的框架模式,即模型M,视图V和模版T.这套框架是以比利时的吉普赛爵士吉他手Django Re ...

  3. Java方法的返回值及注意事项

    方法的返回值 为什么要有带返回值的方法呢? 调用处拿到方法的结果之后,才能根据结果进行下一步操作 带返回值方法的定义和调用: 如果在调用处,要根据方法的结果去编写另一段代码逻辑 为了在调用处拿到方法产 ...

  4. xcode历史版本下载

    一.背景 较早之前做过一个项目,当时使用swift 3.x开发. 项目结束后就没再有新需求与更新. 但最近呢需要对项目的某些功能进行调整,项目又重新被拾了起来. 我们知道现在的swift 版本已经到了 ...

  5. Mac + IOS + Safari 抓取网络请求

    第一步:打开苹果手机 设置>Safari浏览器>高级>网页检查器 第二步:打开 Mac 上的Safari浏览器>偏好设置>高级>在菜单栏中显示"开发&qu ...

  6. 互异关系容斥&集合幂级数小记

    最近碰见了一些互异关系容斥的题目,而这类题目往往要配合集合幂级数的一些技术使用,所以简单记记. 内容很杂,行文很乱,作者水平很低,酌情观看. 互异关系容斥 思想其实很基本,应用范围其实很广. 原论文. ...

  7. 【Azure Developer】Azure AD 注册应用的 OAuth 2.0 v2 终结点获取的 Token 解析出来依旧为v1.0, 这是什么情况!

    问题描述 使用 Azure AD 注册应用 Oauth2 v2.0的终结点(OAuth 2.0 token endpoint (v2):https://login.partner.microsofto ...

  8. ai问答:使用vite如何配置多入口页面

    Vite 是一个 web 开发构建工具,它可以用于开发单页应用和多页应用.要在 Vite 中配置多入口,可以: 在 vite.config.js 中定义多个 entry 入口: export defa ...

  9. 2022-12-01:从不订购的客户。找出所有从不订购任何东西的客户,以下数据的答案输出是Henry和Max,sql语句如何写? DROP TABLE IF EXISTS `customers`; C

    2022-12-01:从不订购的客户.找出所有从不订购任何东西的客户,以下数据的答案输出是Henry和Max,sql语句如何写? DROP TABLE IF EXISTS `customers`; C ...

  10. 2022-08-25:以下go语言代码输出什么?A:1 0;B:1 2;C:不能编译;D:0 0。 package main import “fmt“ func named() (n, _ int

    2022-08-25:以下go语言代码输出什么?A:1 0:B:1 2:C:不能编译:D:0 0. package main import "fmt" func named() ( ...