9.程序的机器级代码表示,CISC和RISC

目录

一. x86汇遍语言基础(Intel格式)

二. AT&T格式汇编语言

三. 程序的机器级代码表示

(1)选择语句

(2)循环语句

(3)函数调用

1.函数调用命令

2.栈帧及其访问

3.栈帧的切换

4.函数传参和返回值

四. CISC和RISC


一. x86汇遍语言基础(Intel格式)

x86架构的CPU有哪些寄存器?

对于前面的通用寄存器,还可以指定使用16位或8位:

常用的x86汇编指令:

算术运算指令:

d和s的解释:destination:目的地(d目的操作数),source:来源地(s源操作数)。因为最终运算结果要送回d,所以目的操作数d不可以是常量。此外x86不允许两个操作数同时来自于主存。

除法的解释:32位的被除数除以32位的除数,在计算前会对被除数进行扩展,把被除数扩展到64位,低32位存入eax,高32位存入edx。

逻辑运算指令:

其他:

用于实现分支结构、循环结构的指令: cmp、test、 jmp、jxxx
用于实现函数调用的指令:push、pop、call、ret
用于实现数据转移的指令:mov

二. AT&T格式汇编语言

三. 程序的机器级代码表示

408考试要求:

只需关注x86汇编语言;若考察其他汇编语言题目会详细注释
题目给出某段简单程序的C语言、汇编语言、机器语言表示。能结合C语言看懂汇编语言的关键语句(看懂常见指令、选择结构、循环结构、函数调用)
汇编语言、机器语言一一对应,要能结合汇编语言分析机器语言指令的格式、寻址方式
不会考:将C语言人工翻译为汇编语言或机器语言

注: Intel x86处理器中程序计数器PC ( Program Counter)通常被称为IP( lnstruction Pointer)

(1)选择语句

jmp <地址>  #PC无条件转移至<地址>:
jmp 128  #<地址>可以用常数给出
jmp eax  #<地址>可以来自于寄存器
jmp [999]  #<地址>可以来自于主存

也可以用“标号”锚定位置,这样不用每次更改地址:

条件转移指令:

示例:

注意:写汇编语言代码时,一般会以函数名作为“标号”,标注该函数指令的起始地址。

扩展:cmp命令的底层原理,本质上是做减法运算。

(2)循环语句

用条件转移指令实现循环:

用loop指令实现循环(注意:循环计数器必须使用ECX寄存器):

(3)函数调用

1.函数调用命令

函数调用指令:call <函数名>
函数返回指令:ret
call指令的作用:①将IP(其实就是程序计数器PC)旧值压栈保存(保存在函数的栈帧顶部)
②设置IP新值,无条件转移至被调用函数的第一条指令
ret指令的作用:从函数的栈帧顶部找到IP旧值,将其出栈并恢复IP寄存器。

2.栈帧及其访问

函数的栈帧(Stack Frame):保存函数大括号内定义的局部变量、保存函数调用相关的信息。

下面的图示,栈顶在下,栈底在上,上面是高地址,下面是低地址。

访问栈帧数据有两种方法:(1)push和pop指令;(2)mov指令

标记栈帧范围:x86中有EBP、ESP寄存器。EBP是堆栈基指针,ESP是堆栈顶指针。EBP:指向当前栈帧的“底部,ESP:指向当前栈帧的“顶部”。对栈帧内数据的访问,都是基于ebp、esp进行的。

1.使用push和pop指令(eax寄存器里的初始值是211)

执行完上述指令后,栈内内容如下,eax内容变为666:

注意:x86系统中,默认以4字节为栈的操作单位。

2.mov指令

可以用mov指令,结合esp、 ebp指针访问栈帧数据
可以用减法/加法指令,即 sub/add修改栈顶指针esp的值。

3.栈帧的切换

在call add后,call会首先把IP(PC)的旧值压栈保存,然后设置IP(PC)新值,无条件转移至被调用函数的第一条指令。在被调用的函数体中,开头一般是这两条命令:

push ebp  # 保存上一层函数的栈帧基址(ebp旧值)
mov ebp,esp  # 设置当前函数的栈帧基址(ebp新值)

push ebp会把上一层函数的栈帧基址压入栈中,成为本层函数栈帧的底,同时esp向下移动;然后执行mov指令,把ebp也指向本层函数栈帧的底,到此一个新的函数栈帧形成,可以往里继续压入一些数据。以上两行代码可以用enter等价表示:

当函数返回时,切换栈帧的方式如下:

mov esp, ebp  # 让esp指向当前栈帧的底部
pop ebp  # 将esp所指元素出栈,写入寄存器ebp

mov指令可以把esp和ebp都指向栈帧的底,然后弹出栈中元素至ebp,这时ebp就可以恢复指向上一层函数栈的栈底,esp+,指向IP旧值,最后执行ret指令,从函数的栈帧顶部找到IP旧值,将其出栈并恢复IP寄存器。上面两行可以用leave等价表示:

4.函数传参和返回值

栈帧里包含的内容:gcc编译器将每个栈帧大小设置为16B的整数倍(当前函数的栈帧除外),因此栈帧内可能出现空闲未使用的区域。

  • 通常将局部变量集中存储在栈帧底部区域
  • 通常将调用参数集中存储在栈帧顶部区域
  • 栈帧最底部一定是上一层栈帧基址(ebp旧值)
  • 栈帧最顶部一定是返回地址(当前函数的栈帧除外)

使用[ebp-8],[ebp-12]等读取,返回参数。

此外,调用其他函数前,如果有必要,可将某些寄存器(如:eax、 edx、ecx)的值入栈保存,防止中间结果被破坏。如果这些寄存器值不是运算的中间结果,则可以不保存。(这部分内容一般在空区域后,调用参数前)

四. CISC和RISC

可以把CISC理解为“库函数+C语言”,RISC理解为C语言。

CISC:Complex Instruction Set Computer
设计思路:一条指令完成一个复杂的基本功能。
代表:x86架构,主要用于笔记本、台式机等。

RISC: Reduced lnstruction Set Computer

设计思路:一条指令完成一个基本“动作”;多条指令组合完成一个复杂的基本功能。
代表:ARM架构,主要用于手机、平板等。

80-20规律:典型程序中80%的语句仅仅使用处理机中20%的指令。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北京地铁1号线

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值