找回密码
 立即注册

QQ登录

只需一步,快速开始

帖子
查看: 2766|回复: 0
打印 上一主题 下一主题
收起左侧

总结-c语言与汇编

[复制链接]
跳转到指定楼层
楼主
ID:107189 发表于 2016-3-5 17:02 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
1. c语言的函数调用与对应的汇编代码 1.1 调用规则
比如调用函数 function(parameter1, parameter2, parameter3)
Pascal调用规则
_cdecl调用规则
_stdcall调用规则
PUSH     parameter1
PUSH     parameter2
PUSH     parameter3
CALL      function
PUSH     parameter3
PUSH     parameter2
PUSH     parameter1
CALL      function
ADD       ESP, 0CH
PUSH     parameter3
PUSH     parameter2
PUSH     parameter1
CALL      function
参数从左到右传递压栈,由被调用函数清理堆栈 参数从右到左传递压栈,由调用函数负责清理堆栈 参数从右到左传递压栈,由被调用函数负责清理堆栈
用于Win16平台
C/C++调用标准
Windows API 使用


1.2 汇编代码 对调用的方式,举一个例子,对c语言常用的printf:

printf(“%d", a);
解析成汇编代码如:
PUSH  a
PUSH  OFFSET String "%d"
CALL  printf
ADD ESP, 8

CALL指令和RET指令
段内调用
对CALL指令来说,其执行的步骤一般包括:
  • 将IP压入栈(即寄存器EIP的值,指向CALL指令之后的第一条指令)
  • 将IP置为跳转到的地址,开始执行

对应 的RET指令为:
  • IP出栈
  • 执行下一条指令

段间调用
如果是段间函数调用,则CALL的执行过程一般是:


  • 将CS(段地址)压入栈
  • 将IP(即EIP的值)压入栈
  • 将IP置为跳转到的函数地址,开始执行
对应的RET指令执行步骤:
  • IP出栈
  • CS出栈
  • 执行下一条指令


被调用函数的执行步骤
PUSH  EBP ; 保存当前堆栈基址ebp,以作返回用
MOVE EBP, ESP ; 将当前esp的值赋给ebp,作为新的基址,即进入函数内部
SUB ESP, 0CCH ; 将esp往下移动一个范围,开辟一片新的堆栈空间给当前函数使用
; 这是由于堆栈从高地址往低地址增长,所以,减一个值意味着开辟了
; 新的空间
................. ; 保存其他寄存器的值
.................
................. ; 恢复压栈的其他寄存器的值
MOVE ESP, EBP ; 恢复esp的值为原来的堆栈栈顶值
POP EBP ; 恢复堆栈基址为原基址位置
RET

一般来说,函数的返回值会放在EAX寄存器中返回。

2. c语言特殊语句块的汇编代码
1)For循环的汇编代码模板
mov <循环变量>, <初始值> ; 循环变量赋初值
jmp B ; 直接跳转到循环控制测试部分代码
A: (改动循环变量) ; 修改循环变量值的部分代码
......
B: cmp <循环变量>, <限制变量> ; 将循环变量的值进行测试、跳转
jge 跳出循环 ; 符合终止条件,则跳出循环体 ; (注意,这里的jl指令可以是其他的jge等,一具判断条件而定)
(循环体代码) ; 否则,进入循环体代码执行
...
jmp A ; 循环体结束的最后,是一个无条件跳转语句,调回直接
; 修改循环变量的代码
2)do循环的汇编代码模板
A: (循环体) ; 直接是循环体代码
....
cmp <循环变量>, <限制变量> ; 判断是否需要终止循环
jl <循环开始处> ; 如果不符合终止条件,直接调回循环体开始处继续执行循环体
; 代码(注意,这里的jl指令可以是其他的jge等,一具判断条件而定)


3) while循环的汇编代码模板
A: cmp <循环变量>, <限制变量> ; 先比较循环变量,是否需要进行循环
jge B ; 如果满足停止循环,则直接跳到B,即循环体后的第一个指令
(循环体)
……
jmp A ; 循环体的最后一条指令,是无条件跳转到循环控制判断指令A处
B: (循环结束了)

4)if-else的汇编代码模板(待续...)
理解调用栈最重要的两点是:栈的结构,EBP寄存器的作用。

首先要认识到这样两个事实:
   1、一个函数调用动作可分解为:零到多个PUSH指令(用于参数入栈),一个CALL指令。CALL指令内部其实还暗含了一个将返回地址(即CALL指令下一条指令的地址)压栈的动作。
   2、几乎任何本地编译器都会在每个函数体之前插入类似如下指令:PUSH EBP; MOV EBP ESP;
即,在程序执行到一个函数的真正函数体时,已有以下数据顺序入栈:参数,返回地址,EBP。
   由此得到类似如下的栈结构(参数入栈顺序跟调用方式有关,这里以C语言默认的CDECL为例):

+| (栈底方向,高位地址) |
| ....................|
| ....................|
| 参数3                |
| 参数2                |
| 参数1                |
| 返回地址             |
-| 上一层[EBP]         |
| 局部变量1            |
| 局部变量2            |
|.....................|

   补充:栈一直随着函数调用的深入,一直想栈顶方向压下去。每次调用函数时候,先压函数参数(从右往左顺序压),再压入函数调用下条指令的地址(由call完成)。接着进入调用函数体中先执行PUSH EBP; MOV EBP ESP;(一般已经由编译器加入到函数头中了),接着就是吧函数体中的局部变量压入栈中。再遇到函数的调用的嵌套则依此类推。(added by smsong)

  “PUSH EBP”“MOV EBP ESP”这两条指令实在大有深意:首先将EBP入栈,然后将栈顶指针ESP赋值给EBP。“MOV EBP ESP”这条指令表面上看是用ESP把EBP原来的值覆盖了,其实不然——因为给EBP赋值之前,原EBP值已被压栈(位于栈顶),而新的EBP又恰恰指向栈顶。
   此时EBP寄存器就已处于一个很重要的地位,该寄存器中存储着栈中的一个地址(原EBP入栈后的栈顶),从该地址为基准,向上(栈底方向)能获取返回地址、参数值,向下(栈顶方向)能获取函数局部变量值,而该地址处又存储着上一层函数调用时的EBP值!
   一般而言,ss:[ebp+4]处为返回地址,ss:[ebp+8]处为第一个参数值(最后一个入栈的参数值,此处假设其占用4字节内存),ss:[ebp-4]处为第一个局部变量,ss:[ebp]处为上一层EBP值。
    由于EBP中的地址处总是“上一层函数调用时的EBP值”,而在每一层函数调用中,都能通过当时的EBP值“向上(栈底方向)能获取返回地址、参数值,向下(栈顶方向)能获取函数局部变量值”。
如此形成递归,直至到达栈底。这就是函数调用栈。
编译器对EBP的使用实在太精妙了。
从当前EBP出发,逐层向上找到任何的EBP是很容易的:
unsigned int _ebp;
__asm _ebp, ebp;
while (not stack bottom)
{
    //...
    _ebp = *(unsigned int*)_ebp;
}
假如要写一个简单的调试器的话,注意需在被调试进程(而非当前进程——调试器进程)中读取内存数据
8个通用寄存器:
      数据寄存器:AX,BX,CX,DX
      指针寄存器:SP(堆栈指针),BP(基址指针)
      变址寄存器:SI(原地址),DI(目的地址)
1、通用寄存器
数据寄存器,指针寄存器和变址寄存器统称为通用寄存器。这些寄存器除了各自专门用途外,它们均可用于传送和暂存数据,可以保存算术逻辑运算中的操作数和运算结果。
(1)数据寄存器
数据寄存器主要用来保存操作数或运算结果等信息,它们的存在节省了为存取操作数所需占用总线和访问存储器的时间。
(2)变址和指针寄存器
变址和指针寄存器主要用于存放某个存储单元地址的偏移,或某组存储单元地址的偏移,即作为存储器(短)指针使用。作为通用寄存器,它们可以保存16位算术逻辑运算中的操作数和运算结果,有时运算结果就是需要的存储单元地址的偏移。
2、控制寄存器(2个)
(1)指令指针寄存器
8086/8088CPU中的指令指针IP也是16位的。
指令指针IP给出接着要执行的指令在代码段中的偏移。
(2)标志寄存器
8086/8088CPU中有一个16位的标志寄存器,包含了9个标志,主要用于反映处理器的状态和运算结果的某些特征。6个条件标志+3个方向标志
3、段寄存器(4个)
8086/8088CPU依赖其内部的四个段寄存器实现寻址1M字节物理地址空间。
8086/8088把1M字节地址空间分成若干逻辑段,当前使用的段值存放在段寄存器中。
由于8086/8088有这四个段寄存器,所以有四个当前使用段可以直接存取,这四个当前段分别称为代码段,数据段,堆栈段和附加段。
(1)代码段
(2)数据段
(3)堆栈段
(4)附加段


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表