C和汇编的对应—main之前之后的汇编到底在干什么

Posted on 2010年07月21日 by sstompkins

下面以一个非常简洁的C来进行讲解ASM的实现方式

查看汇编语言实现方法,把程序设置为debug,在int main()行首添加断点打开IDE集成开发工具的CUP视图,进行逐行的运行,和查看你的代码

用这种方法我们可以非常方便的弄清楚C,C++的语句在汇编下是怎么实现的这种方法可以非常方便的让我们学懂汇编指令

1.用C实现一个简单的函数调用功能

//filename: demo.c

//0x11=17, 0x21=33,17+23=50

//run value  add(9,20) is :50

#include

int add(int x,int y){return (x+y);}

int main()

{

int value;

value=add(0x11,0x21);

printf("add(9,20) is :%d",value);

return 0;

}

2.编译器自动实现的汇编代码如下:

代码左边               C函数体的运行位置

//int main(){

push  ebp

mov   ebp,esp

//value=add(0x11,0x21)

push  0x11

push  0x21

//call  add(int,int)

//int   add(int x,int y){

push  ebp

mov   ebp,esp

//return (x+y);

mov   eax,[ebp+ox08]

add    eax,[ebp+ox0c]

//}

pop    ebp

ret

//value=add(0x11,0x21)

add    esp,0x08

push  eax

push  0x0040a0e8

//call printf(const ….)

add    esp,0x08

//return 0;

xor     eax,eax

//}

pop    ebp

ret

3.汇编按行一一讲解明细

ebp基地址指针寄存器,常用于指向程序段的入口地址!

esp堆栈指针寄存器,常用于指向堆栈顶元素,也就是每条指令的操作对象,还记得我们之前用C++实现的堆栈吗?

esp简单的讲就是每次指令操作对象的内存地址,每执行一个指令它都会变化的

————————————————————————————————————–

//此代码未运行之前:ebp=0012FFB8,esp=0012FF90,堆栈数据未知

//int main(){

push  ebp      //是ebp的地址压入堆栈保存起来,esp跟踪堆栈顶元素,由于数据在内存是先从高地址往低地址存放数据

//esp减4位(0012FF90-4=0012FF8C)esp=0012FF8C

mov   ebp,esp  //esp的地址复制到ebp结果ebp,esp是存放同一地址

程序说明:从C的int main(){开始计算

//此代码未运行之后:ebp=0012FF8C,esp=0012FF8C,堆栈数据是0012FFB8

(push ebp),(mov ebp,esp)这两句是保存当前程序现场,以方便用pop        ebp,ret来恢复现场

堆栈压入0012FFB8,它是执行这个int main()之前的程序入口地址

————————————————————————————————————-

//value=add(0x11,0x21)

push  0x11              //把0x11(17)压入堆栈,esp减4位(0012FF8C-4=0012FF88)esp=0012FF88

//0x11存入地址:0012FF88

push  0x21              //把0x21(33)压入堆栈,esp减4位(0012FF88-4=0012FF84)esp=0012FF84

//0x21存入地址:0012FF84

程序说明:从C的value=add(0x11,0x21)开始计算

//以上两行读入参数顺序是先右边-后左,先读取0x11,再读取0x21

//就是著名的函数的参数调用是用堆栈来传递的实事证明

//此代码运行之前:ebp=0012FF8C,esp=0012FF8C,堆栈数据是0012FFB8

//此代码运行之后:ebp=0012FF8C,esp=0012FF84,堆栈数据是0012FFB8

————————————————————————————————————-

//call  add(int,int)  //esp自然减4位(0012FF84-4=0012FF80)esp=0012FF80

//int   add(int x,int y){

push  ebp          //ebp的地址压入堆栈,esp自然减4位(0012FF80-4=0012FF7C)esp=0012FF7C

mov   ebp,esp      //esp的地址复制到ebp结果ebp,esp是存放同一地址

程序说明:从C的int  add(int x,int y){开始计算

//此代码运行之前:ebp=0012FF7C,esp=0012FF90,堆栈数据是0012FFB8

//此代码运行之后:ebp=0012FF7C,esp=0012FF7C,堆栈数据是0012FF8C,0012FFB8

(push ebp),(mov ebp,esp)这两句是保存当前程序现场,以方便用pop        ebp,ret来恢复现场

堆栈压入0012FF8C,它是执行这个int add(int x,int y)之前的程序入口地址

————————————————————————————————————-

//用EAX进行两个数据的加法运算

//return (x+y);

mov   eax,[ebp+ox08]      //把数据0x21,移入eax

add   eax,[ebp+ox0c]     //把数据0x11,与eax原来数据进行累加之后再送入eax,结果eax=0x32也就是50

//[ebp+0x08]怎么得到0x21,计算如下[ebp+ox08]=0012FF7C+8=0012FF84,而0012FF84存放的是0x21,由之间的push 0x21

//[ebp+0x0c]怎么得到0x11,计算如下[ebp+ox0c]=0012FF7C+c=0012FF88,而0012FF88存放的是0x11,由之间的push 0x11

//因计算是针对eax,所以ebp,esp都没有变化

//此代码运行之前:ebp=0012FF7C,esp=0012FF7C,堆栈数据是0012FFB8

//此代码运行之后:ebp=0012FF7C,esp=0012FF7C,堆栈数据是0012FF8C,0012FFB8

————————————————————————————————————-

//}

pop    ebp               //把堆栈顶数据弹出到ebp,堆栈数据是0012FF8C,结果ebp=0012FF8C,

//esp+4位(0012FF7C+4=0012FF80)esp=0012FF80

ret                      //退出函数调用,返回到int main() 代码中来ret,

//value=add(0x11,0x21)

add    esp,0x08      //esp+8位(0012FF80+8=0012FF8C)esp=0012FF8C,现在ebp=esp=0012FF8C

//退出函数调用之后的收尾动作

//此代码运行之前:ebp=0012FF7C,esp=0012FF7C,堆栈数据是0012FFB8

//此代码运行之后:ebp=0012FF8C,esp=0012FF8C,堆栈数据是0012FFB8

————————————————————————————————————-

push  eax                   //把eax地址保存起来

push  0x0040a0e8            //把50的内存地址压入堆栈,让printf函数去调用并显示出来

//call printf(const ….)   //进行下面的printf函数调用,实现明细如上

add   esp,0x08             //把esp的内存地址和ebp对齐到一起esp=ebp

//return 0;

xor     eax,eax             //把eax复位为0,没有保存任何地址

//此代码运行之前:ebp=0012FF7C,esp=0012FF7C,堆栈数据是0012FFB8

//此代码运行之后:ebp=0012FF8C,esp=0012FF8C,堆栈数据是0012FFB8

————————————————————————————————————-

//}                         //在执行完int main(){}最后一个}后,把原来的地址复原

pop    ebp                  //把堆栈顶数据弹出到ebp,堆栈数据是0012FFB8,结果ebp=0012FFB8,

//esp+4位(0012FF8C+4=0012FF90)esp=0012FF90

ret                         //退出int main()函数调用

//最后此代码运行之后:ebp=0012FFB8,esp=0012FF90,堆栈数据未知

//首行此代码未运行之前:ebp=0012FFB8,esp=0012FF90,堆栈数据未知

调用完main()函数后,ebp,esp又得到原来的地址,它就可以继续执行原来未运行完的其它程序

调用各个函数时,ebp,esp的工作总结

1.ebp的工作方式调用一个程序的每一个函数时,都是调用之前用堆栈保存好ebp,调用之后,又恢复ebp

2.esp的工作方式也是跟着ebp的变化相互配合,都是调用之前用esp取函数指令地址,调用之后,又恢复到原来

esp总是动态的指向当前程序运行到的地址!它是随着程序运行时不断变化而变化的

汇编语言C什么意思,C和汇编的对应—main之前之后的汇编到底在干什么相关推荐

  1. ARM汇编基础详解(PS学习汇编的原因)

    目录 前言 1.GNU 汇编语法 2.Cortex-A7 常用汇编指令 2.1 处理器内部数据传输指令(内部寄存器数据非内存数据) 2.2 存储器访问指令(RAM) 2.3 压栈和出栈指令(了解) 2 ...

  2. 汇编和c语言混合编程缺点,汇编C语言混合编程经验总结

    ARM汇编语言和C语言混合编程 ATPCS规灾了一种模块化设计的观念,其基本内容是C模块(函数)和汇编模块(函数)相互的一套规?中还有类似的一套规晕腋芯谙呋惚喙δ芮看用有很多忌讳),厅知道(很寄几它/ ...

  3. 汇编与C/C++内联嵌入汇编

    汇编语言格式简介 汇编语言的指令格式,目前有两种不同的标准:Windows下的汇编语言基本上都遵循Intel风格的语法,比如:MASM.NASM;而Unix/Linux下的汇编语言基本上都遵循AT&a ...

  4. 8086汇编4位bcd码_逆向工程——汇编基础[一]

    什么是汇编 汇编语言是一种最接近计算机核心的编码语言.不同于任何高级语言,汇编语言几乎可以完全和机器语言一一对应. 汇编语言就是机器语言的一种可以被人读懂的形式,只不过它更容易记忆. 学习汇编语言,你 ...

  5. 简述arm汇编和c语言混合编程,ARM汇编C语言混合编程

    3.4 ARM汇编&C语言混合编程 3.4.1 C内联ARM汇编 先看一个例子: # cat add.c 1 // add.c for s3c2410c board 2 // arm-linu ...

  6. 【单片机】汇编指令入门学习|单片机启动代码汇编

     目录 汇编指令入门学习 [汇编指令]MSP430汇编指令 IAR下的汇编/单片机启动代码汇编 ARM 汇编&ARM 指令集 学习笔记 汇编指令入门学习   在进行汇编程序设计时,MSP430 ...

  7. mvn 汇编_2020年积极向上的班级口号汇编71条

    2020年积极向上的班级口号汇编71条 人是自身幸福的设计师.人生如戏但切不能戏弄人生.下面是小编收集整理的积极向上的班级口号71条,欢迎大家借鉴与参考,希望对大家有所帮助. 1.健康是最大的财富,知 ...

  8. 汇编代码调用main和分配内存

    C语言的main函数 int main() {unsigned int *pgpofcon = 0x56000050;unsigned int *pgpofdat = 0x56000054;*pgpo ...

  9. c语言 汇编中断程序,ARM7 C语言嵌入汇编开关中断

    __inline void IRQEnable(void) { int tmp; __asm { MRS tmp,CPSR       ///读取CPSR的值 BIC tmp,tmp,#0x80 // ...

最新文章

  1. 使用MyBatis集成阿里巴巴druid连接池(不使用spring)
  2. NotificationManagerService使用详解与原理分析(一)
  3. 我是如何解决gitlab 命令行上传需要输密码
  4. Elasticsearch——filter过滤查询
  5. 软件工程(2018)第3次团队作业
  6. 小程序入门学习13--云函数与数据库02
  7. kloxo 中php如何设置,Kloxo使用教程(5):〖网站设置〗——在Kloxo中设置伪静态...
  8. 【java笔记】线程(4):匿名内部类创建线程
  9. 豆瓣关于计算机视觉的书评及介绍
  10. WPS 破解宏 安装VBA VBA for WPS
  11. 房地产开发商崩盘样本:楼盘捂了两年,欠40亿巨债
  12. java操作Excel、PDF文件
  13. QCC512x QCC302x earbud工程 LED 配置
  14. 云服务器配置选择方法
  15. 关于微信表情及输入法emoji显示问题解决方案
  16. CF - 777D. Cloud of Hashtags 暴力
  17. 《Adobe Fireworks CS5中文版经典教程》——第1课 了解工作区 1.1 熟悉Adobe Fireworks...
  18. Win11系统怎么删除软件操作方法教程
  19. 计算机无法读取exe文件,详解EXE文件出错不能打开的修复方法
  20. 1272: 下载记忆  小明比较怀旧,想网上下载儿时武侠片,他用自己的血汗钱办理充值会员。会员是按月充的,每月的费用为15元。问小明充值多少元,才能将所有的武侠剧下载完。

热门文章

  1. android usb麦克风阵列,语音设备 SDK 麦克风阵列建议
  2. 计算机单片机考试作弊检讨书,关于大学生考试作弊检讨书1000字范文[共7页]
  3. 基于C语言设计的像素小鸟小游戏
  4. Postman使用newman命令执行
  5. 计算机打印中没有记录纸,打印机出来白纸没有字
  6. antd react table 嵌套子表格例子
  7. 微生物 Alpha多样性 作图 16S 菌群 R语言
  8. error: cannot open Packages database in /var/lib/rpm
  9. Lunix基础终端控制器操作
  10. 行人属性识别一:训练PA100k数据集