汇编的艺术(01)sizeof operator

以前在百度的博客里面学习了逆向一些基本的C语言知识。一方面不能让学习的汇编知识荒废,另外一方面是由于经常碰到一些细节性的问题,需要温故而知新。

学习汇编对于我自己的感觉是:可以从更加底层的角度来窥视C语言以及其他高层语言的细节。这是一件很舒服的事情~

同时一些特殊的工作,比如内核调试,内存错误,函数调用等问题,用汇编的角度来看待会更加方便,更加深刻的理解其机制。

废话不多说,作为开篇《汇编的艺术》,是我今天更巧碰到的一个问题,想记下来,先从最简单的入手,感觉是慢慢来的~

先看一段代码:

int main()  
{  char a = 255;  printf("%d\n",sizeof(++a));  printf("%d\n",a);  return 0;  
}  

出乎意料的是,输出的值是:1,-1

难道是sizeof里面的++a没有执行么?带着这样的疑问,看看反汇编代码是啥样的:

int main()  
{  char a = 255;  
00000000  push        ebp  
00000001  mov         ebp,esp 
00000003  sub         esp,8 
00000006  cmp         dword ptr ds:[00192E14h],0 
0000000d  je          00000014 
0000000f  call        696E67F9 
00000014  xor         edx,edx 
00000016  mov         dword ptr [ebp-4],edx 
00000019  mov         dword ptr [ebp-8],0 
00000020  xor         edx,edx 
00000022  mov         dword ptr [ebp-4],edx 
00000025  mov         dword ptr [ebp-8],0FFFFFFFFh printf("%d\n",sizeof(++a));  
0000002c  push        1B31B8h 
00000031  push        1    
00000033  push        4F01B8h 
00000038  call        FEEA58CC 
0000003d  add         esp,0Ch 
00000040  nop              printf("%d\n",a);  
00000041  push        1B31BCh 
00000046  push        dword ptr [ebp-8] 
00000049  push        4F01C8h 
0000004e  call        FEEA58CC 
00000053  add         esp,0Ch 
00000056  nop              return 0;  
00000057  xor         edx,edx 
00000059  mov         dword ptr [ebp-4],edx 
}  
0000005c  mov         eax,dword ptr [ebp-4] 
0000005f  mov         esp,ebp 
00000061  pop         ebp  
00000062  ret              

看到橙黄色标注的部分,果然传参的时候是直接push了1,而++a这个指令在没有在汇编中出现的痕迹。

但是sizeof操作符并不像#define这样的宏一样在预处理阶段就把其替换掉了,sizeof是在编译阶段替换的。

于是理解了,sizeof里面的expression都是不执行的,只关心里面类型的大小。

类似的问题还有sizeof('a'),貌似不同的编译器说法不一,C标准应该是把'a'看成了97,也就是int类型,等于4,

如果里面的数字再大的话,超过了int范围,则是8了,以此类推。

还有是sizeof("a"),这个问题不该有争议,因为传进去的是字符串a的地址,就是一个指针的大小了,32位机器上面是4,64位机器上面应该是8.

btw:

很久没有看过反汇编代码了,很多东西都生疏了。

比如说里面不理解的是,main()函数明明只申请了一个char 的却把栈空间抬高了8个字节,边界对齐为char开辟4字节还能理解。

那另外的4个字节又是什么意思呢?函数最后返回的代码利用到了这4个字节,把里面的值传给eax。

这是汇编的风格,函数的返回值是传给eax的。但是不清楚为什么还要“多此一举”。

我的理解是,因为函数最终要返回的,对于一般的函数如果返回比如 return ans; ans变量肯定要开辟字节空间的,于是return 0; 也按照这个思路照做了?有时间再探究。

第二个问题就是又一次的复习了函数传参时堆栈的情况。感觉都有点生疏了。

printf 第一个参数压入的是格式化字符串的地址,后面压入的几个参数则是变量。对于这类参数可变的函数,平衡堆栈的工作要交给母函数来处理的。

关于这方面详细的介绍请看:http://bbs.pediy.com/showthread.php?t=56518

转载于:https://www.cnblogs.com/kedebug/archive/2012/12/03/2800225.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/262181.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

堆和栈地址——eclipse linux实践

chara[]"as";栈,或全局常量char*a2"das";字符常量 string*snewstring("da");堆 printf("%p %p %p %p",a,a2,s,&"as"字符常量); 0xbfa9b994栈或0x8049d88全局常量 0x8048a50字符常量 0x85ea008堆 0x8048a57字…

java single instance_java单例模式(具体代码显现)两种方法

判断是否存在/*** 懒汉式*/public class LazySingleInstance {// 私有构造方法private LazySingleInstance(){};// 私有的类对象private static LazySingleInstance instance null;// 缺点:// 1 每次都需要去判断instance 是否为空// 2 调用时才去new对象&#xff…

python界面编程和网口通信_Python—网络通信编程之tcp通信编程

服务端代码 import socket # 1.创建流式套接字实例 # server socket.socket() server socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) # 2.使用bind方法绑定端口号。服务端绑定的ip和port(参数是元组) server.bind(("127.0.0.1", 88…

判断是否是控制字符

#include <stdio.h> #include <ctype.h>/* 判断是控制字符&#xff08;ASCII 0-31和127&#xff09;的库函数&#xff1a; 满足指定的条件&#xff0c;返回非0&#xff1b;否则返回0. iscntrl(c) *//**************** 输入&#xff1a;要判断的字符。* 输出&#x…

感冒了

1 浑身发冷 2 大腿酸痛&#xff0c;无力 3 口腔溃疡。在舌头尖上有一个小白点&#xff0c;周围有点红色。 4 有点咳嗽。 5 有浓痰。 转载于:https://www.cnblogs.com/sdgxbooy/archive/2010/01/27/8902970.html

php代码加注释_怎么在php中添加注释

注释在写代码的过程中非常重要&#xff0c;好的注释能让你的代码读起来更轻松&#xff0c;在写代码的时候一定要注意注释的规范。php里面常见的几种注释方式&#xff1a;1.文件头的注释&#xff0c;介绍文件名&#xff0c;功能以及作者版本号等信息/***文件名简单介绍**文件功能…

数据库整理

转载于:https://www.cnblogs.com/cuikang/p/5131531.html

python保存模型_MNIST数据集训练完如何保存成模型文件?

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data # In[12]: #载入数据集 mnist input_data.read_data_sets("E://YangBen//MNIST_data",one_hotTrue) #每个批次的大小 batch_siz…

GridControl动态添加 颜色列

设计器&#xff1a; 核心代码&#xff1a; DataTable dt new DataTable("UniqueValue");dt.Columns.Add("symbol", typeof(Color));dt.Columns.Add("label",typeof(string));dt.Columns.Add("count",typeof(int));for (int i 0; i &…

代码托管使用指南

2019独角兽企业重金招聘Python工程师标准>>> 开源中国 登录https://git.oschina.net/ 点击 “” 增加新的项目出现创建项目界面&#xff0c;按照提示&#xff0c;输入相应内容点击“管理”显示如下界面 启用svn&#xff0c;输入你所设置的地址。 svn://git.oschin…

python3.6.5怎么下载_windows下如何下载并安装Python 3.6.4 ?

点击Download中的Windows&#xff0c;如下图所示&#xff1a; 2、下载exe后缀的可执行文件&#xff0c;根据自己系统选择32位还是64位。 3、32位和64位的版本安装起来没有区别&#xff0c;双击打开后&#xff0c;第一步要记得勾上Add python to Path 选项&#xff0c;意思是把P…

php中接口验证失败,php短信验证失败的原因

随着国民经济的高速发展&#xff0c;短信的应用也逐渐商业化&#xff0c;很多企业、商家开始使用php短信接口来进行推广、营销或内部管理&#xff0c;只是个别的商家在应用php短信接口的时候却遇到了短信发送失败的现象&#xff0c;这到底是因为商家操作有误&#xff0c;还是因…

数据库无法保存中文的解决

1. ALTER DATABASE dbname COLLATE CHINESE_PRC_CS_AI 2. 使用nvarchar, ntext.转载于:https://www.cnblogs.com/cnblogsfans/archive/2010/01/29/1659264.html

1 用存储过程实现分页,除了上一页,下一页,第一页,和末页外还要有go按钮,以及go到那里的文本框。另外还要在Lable显示“当前x页,一共y页”。注意验证控件的使用和 链接存储过程的内容。...

前台部分 <% Page Xlanguage"C#" AutoEventWireup"true" CodeBehind"USEsp_page.aspx.cs" Inherits"12_7" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml…

CentOS6.3中挂载NTFS移动硬盘的经历

2019独角兽企业重金招聘Python工程师标准>>> 鄙人当年用PC硬盘做了一个移动硬盘&#xff08;其实并不方便移动&#xff0c;只是外边包装了一个壳子&#xff0c;可以用USB口访问而已&#xff09;&#xff0c;移动硬盘上存放了一些学习资料。某日想把一部分学习资料拿…

如何在vsc上下载php扩展包,正确的 Composer 扩展包安装方法

问题说明我们经常要往现有的项目中添加扩展包&#xff0c;有时候因为文档的错误引导&#xff0c;如下图来自 这个文档 的&#xff1a;composer update 这个命令在我们现在的逻辑中&#xff0c;可能会对项目造成巨大伤害。因为 composer update 的逻辑是按照 composer.json 指定…

python之33个关键字详解_Python解析、提取url关键字的实例详解

解析url用的类库: python2版本&#xff1a; from urlparse import urlparse import urllib python3版本&#xff1a; from urllib.parse import urlparse import urllib.request 研究了不同的url规则发现&#xff1a;只要在搜索关键字是用嫁接的&#xff0c;查询的关键在解析后…

Apache专用笔记贴

有关apache的一些知识点(例如配置,参数设置等)每每有什么问题都要到google,baidu半天. 其实这些问题自己以前也碰到过很多回,结果就浪费了大量的时候在每次的网上搜索答案上, 而且每次通过搜索得到的答案都不尽相同,有几乎是最优答案的,也有勉强可用的,想再找到以前 认为写的很…

Lodash 中文文档 (v3.10.1) - “Number” 方法

Lodash 中文文档 (v3.10.1) - “Number” 方法 Translated by PeckZegOriginal Docs: Lodash v3.10.1 Docs“Number” 方法 _.inRange(n, [start0], end) 检查 n 是否位于 start 和 end 之间&#xff08;包含 start&#xff0c;但不包含 end&#xff09;。如果未指定 end&#…

给定某年日期及该年第一天是星期几然后显示该年的日历

package lyt; import javax.swing.*; public class Lyt5 { public static void main(String[] args) { // TODO Auto-generated method stub String yearJOptionPane.showInputDialog(null,"请输入年份:","梁燕婷",JOptionPane.QUESTION_MESSAGE); Stri…