25考研计算机组成原理复习·4.3程序的机器级代码表示

2024-08-25 23:04

本文主要是介绍25考研计算机组成原理复习·4.3程序的机器级代码表示,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

高级语言与机器级代码之间的对应

常见的算术运算指令

常见的逻辑运算指令

AT&T格式 v.s. Intel格式

选择语句的机器级表示

无条件转移指令——jmp

条件转移指令——jxxx

示例:选择语句的机器级表示

循环语句的机器级表示

用条件转移指令实现循环

用loop指令实现循环

函数调用机器级表示

call、ret指令

如何访问栈帧?

访问栈帧数据:push、pop指令

访问栈帧数据:mov指令

如何切换栈帧?

栈帧内包含哪些内容?

参数、返回值传递

高级语言与机器级代码之间的对应

  • 指令的作用?1.改变程序执行流 2.处理数据
  • 指令格式:
    • 操作码:怎么处理?
    • 地址码:数据在哪儿?
      • 在寄存器里。在汇编指令中,给出寄存器名(通用寄存器:eax、ebx、ecx、edx;变址寄存器:esi、edi;堆栈寄存器:ebp、esp
      • 在主存里:在汇编指令中,给出读写长度主存地址dword ptr[地址] #32bitword ptr[地址] #16bittype ptr[地址] #8bit
      • 在指令里:在汇编指令中,直接给出常量,即“立即寻址”;可用十进制表示、也可用十六进制表示(通常用h结尾)

常见的算术运算指令

功能英文汇编指令注释
addadd d,s#计算d+s,结果存入d
subtractsub d,s#计算d-s,结果存入d
multiply

mul d,s

imul d,s

#无符号数d*s,乘积存入d

#有符号数d*s,乘积存入d

divide

div s

idiv s

#无符号数除法edx:eax/s,商存入eax,余数存入edx

#有符号数除法edx:eax/s,商存入eax,余数存入edx

取负数negativeneg d#将d取负数,结果存入d
自增++increaseinc d#将d++,结果存入d
自减--decreasedec d#将d- -,结果存入d

常见的逻辑运算指令

功能英文汇编指令注释
andand d,s#将d、s逐位相与,结果放回d
oror d,s#将d、s逐位相或,结果放回d
notnot d#将d逐位取反,结果放回d
异或exclusive orxor d,s#将d、s逐位异或,结果放回d
左移shift leftshl d,s#将d逻辑左移s位,结果放回d(通常s是常量)
右移shift rightshr d,s#将d逻辑右移s位,结果放回d(通常s是常量)

AT&T格式 v.s. Intel格式

AT&T格式Intel格式
目的操作数d、源操作数s

op s,d

注:源操作数在左,目的操作数在右

op d,s

注:源操作数在右,目的操作数在左

寄存器的表示

mov %ebx,%eax

注:寄存器名之前必须加“%”

mov eax,ebx

注:直接写寄存器名即可

立即数表示

mov $985,%eax

注:立即数之前必须加“$”

mov eax,985

注:直接写数字即可

主存地址表示

mov %eax,(af996h)

注:用“()”

mov [af996h],eax

注:用“[]”

读写长度表示

movb $5,(af996h)

movw $5,(af996h)

movl $5,(af996h)

addb $4,(af996h)

注:指令后加b、w、l分别表示读写长度为byte、word、dword

mov byte ptr[af996h],5

mov word ptr[af996h],5

mov dword ptr[af996h],5

add byte ptr[af996h],4

注:在主存地址前说明读写长度byte、word、dword

主存地址偏移量表示

movl -8(%ebx),%eax

注:偏移量(基址)

movl 4(%ebx,%eax,32),%eax

注:偏移量(基址,变址,比例因子)

mov eax,[ebx - 8]

注:[基址+偏移量]

mov eax,[ebx + eax*32 +4]

注:[基址+变址*比例因子+偏移量]

选择语句的机器级表示

无条件转移指令——jmp

mov eax,7
mov ebx,6
jum NEXT
mov ecx,ebx
NEXT: #用“标号”锚定位置 特征——有冒号,名字可以自己取
mov ecx,eax

条件转移指令——jxxx

cmp a,b #比较a和b两个数je<地址>  #jump when equal,若a=b则跳转
jne<地址>  #jump when not equal,若a!=b则跳转
jg<地址>  #jump when greater than,若a>b则跳转
jge<地址>  #jump when greater than or equal to,若a>=b则跳转
jl<地址>  #jump when less than,若a<b则跳转
jle<地址>  #jump when less than or equal to,若a<=b则跳转

示例:选择语句的机器级表示

if(a > b){c = a;
}else{c = b;
}
mov eax,7
mov ebx,6
cmp eax,ebx
jg NEXT
mov ecx,ebx
jum END
NEXT:
mov ecx,eax
END:

循环语句的机器级表示

用条件转移指令实现循环

int result = 0;
for(int i = 1;i <= 100;i++){result += i;
}//求1+2+3+…+100

用条件转移指令实现循环,需要4个部分构成:

  1. 循环前的初始化
  2. 是否直接跳过循环?
  3. 循环主题
  4. 是否继续循环?
mov eax,0  #1.用eax保存result,初值为0
mov edx,1  #1.用edx保存i,初始值为1
cmp edx,100  #2.比较i和100
jg L2  #2.若i>100,转跳到L2执行
L1:  #循环主体
add eax,edx  #3.实现 result += i
inc edx  #3.inc自增指令,实现i++
cmp edx,100  #4.i和100
jle L1  #4.若i <= 100,转跳到L1执行
L2:  #跳出循环主体

用loop指令实现循环

for(int i = 500;i > 0;i--){做某些处理;
}//循环500轮
mov ecx,500  #用ecx作为循环寄存器
Looptup:  #循环的开始
...
做某些处理
...
loop Looptop  #ecx--,若ecx!=0,跳转到Looptop
#等价于dec ecx 
#cmp ecx,0
#jne Looptop

理论上,能用loop指令实现的功能一定能用条件转移指令实现。

使用loop指令可能会使代码更清晰简洁。

补充:loopx指令——loopnz,loopz

        loopnz——当ecx≠0&&ZF==0时,继续循环

        loopz——当ecx≠0&&ZF==1时,继续循环

函数调用机器级表示

call、ret指令

  1. 函数调用指令:call<函数名>

    函数返回指令:ret

  2. call指令的作用:

    1. IP旧值压栈保存(保存在函数的栈帧顶部)(效果相当于 push IP)
    2. 设置IP新值,无条件转移至被调用函数的第一条指令(效果相当于jmp add)
  3. ret指令的作用:从函数的栈帧顶部找到IP旧值,将其出栈并恢复IP寄存器

如何访问栈帧?

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

访问栈帧数据:push、pop指令

push、pop指令实现入栈、出栈操作,x86默认以4字节为单位。指令格式如下:

        push 🏇  //先让esp减4,再将🏇压入(🏇可以是立即数、寄存器、主存地址)

        pop 🐘  //栈顶元素出栈写入🐘,再让esp加4(🐘可以是寄存器、主存地址)

访问栈帧数据:mov指令

sub esp,12 #栈顶指针-12
mov[esp+8],eax  #将eax的值复制到主存[esp+8]
mov[esp+4],985  #将985复制到主存[esp+4]
mov eax,[ebp+8]  #将主存[ebp+8]的值复制到eax
mov [esp],eax  #将eax的值复制到主存[esp]
add esp,8  #栈顶指针+8

可以用mov指令,结合esp、ebp指针访问栈帧数据

可以用减法/加法指令,即sub/add修改栈顶指针esp的值

如何切换栈帧?

call指令的作用:

        将IP旧值压栈保存(效果相当于 push IP)

        设置IP新值,无条件转移至被调用函数的第一条指令(效果相当于jmp add)


push ebo #保存上一层函数的栈帧基址(ebp旧值)

mov ebp,esp #设置当前函数的栈帧基址(ebp新值)

 在每个函数开头的“例行处理”。两条指令等价于enter

mov esp,ebp #让esp指向当前栈帧的底部

pop ebp #将esp所指元素出栈,写入寄存器ebp

 在每个函数ret前的“例行处理”。两条指令等价于leave


ret指令的作用:从函数的栈帧顶部找到IP旧值,将其出栈并恢复IP寄存器

栈帧内包含哪些内容?

  1. gcc编译器将每个栈帧大小设置为16B的整数倍,因此战阵内可能出现空闲未使用的区域。
  2. 通常将局部变量集中存储在栈帧底部区域
  3. 通常将调用参数集中存储在栈帧顶部区域
  4. 栈帧最底部一定是上一层栈帧基址(ebp旧值)
  5. 栈帧最顶部一定是返回地址(当前函数的栈帧除外)

参数、返回值传递

  1. 在cal指令前,将调用参数写入栈帧顶部区域
  2. 在ret指令前,将函数返回值写入eax寄存器

这篇关于25考研计算机组成原理复习·4.3程序的机器级代码表示的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


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

相关文章

在MySQL中实现冷热数据分离的方法及使用场景底层原理解析

《在MySQL中实现冷热数据分离的方法及使用场景底层原理解析》MySQL冷热数据分离通过分表/分区策略、数据归档和索引优化,将频繁访问的热数据与冷数据分开存储,提升查询效率并降低存储成本,适用于高并发... 目录实现冷热数据分离1. 分表策略2. 使用分区表3. 数据归档与迁移在mysql中实现冷热数据分

Python实现MQTT通信的示例代码

《Python实现MQTT通信的示例代码》本文主要介绍了Python实现MQTT通信的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录1. 安装paho-mqtt库‌2. 搭建MQTT代理服务器(Broker)‌‌3. pytho

MySQL进行数据库审计的详细步骤和示例代码

《MySQL进行数据库审计的详细步骤和示例代码》数据库审计通过触发器、内置功能及第三方工具记录和监控数据库活动,确保安全、完整与合规,Java代码实现自动化日志记录,整合分析系统提升监控效率,本文给大... 目录一、数据库审计的基本概念二、使用触发器进行数据库审计1. 创建审计表2. 创建触发器三、Java

golang程序打包成脚本部署到Linux系统方式

《golang程序打包成脚本部署到Linux系统方式》Golang程序通过本地编译(设置GOOS为linux生成无后缀二进制文件),上传至Linux服务器后赋权执行,使用nohup命令实现后台运行,完... 目录本地编译golang程序上传Golang二进制文件到linux服务器总结本地编译Golang程序

使用Docker构建Python Flask程序的详细教程

《使用Docker构建PythonFlask程序的详细教程》在当今的软件开发领域,容器化技术正变得越来越流行,而Docker无疑是其中的佼佼者,本文我们就来聊聊如何使用Docker构建一个简单的Py... 目录引言一、准备工作二、创建 Flask 应用程序三、创建 dockerfile四、构建 Docker

从原理到实战深入理解Java 断言assert

《从原理到实战深入理解Java断言assert》本文深入解析Java断言机制,涵盖语法、工作原理、启用方式及与异常的区别,推荐用于开发阶段的条件检查与状态验证,并强调生产环境应使用参数验证工具类替代... 目录深入理解 Java 断言(assert):从原理到实战引言:为什么需要断言?一、断言基础1.1 语

Java中调用数据库存储过程的示例代码

《Java中调用数据库存储过程的示例代码》本文介绍Java通过JDBC调用数据库存储过程的方法,涵盖参数类型、执行步骤及数据库差异,需注意异常处理与资源管理,以优化性能并实现复杂业务逻辑,感兴趣的朋友... 目录一、存储过程概述二、Java调用存储过程的基本javascript步骤三、Java调用存储过程示

Visual Studio 2022 编译C++20代码的图文步骤

《VisualStudio2022编译C++20代码的图文步骤》在VisualStudio中启用C++20import功能,需设置语言标准为ISOC++20,开启扫描源查找模块依赖及实验性标... 默认创建Visual Studio桌面控制台项目代码包含C++20的import方法。右键项目的属性:

MySQL中的表连接原理分析

《MySQL中的表连接原理分析》:本文主要介绍MySQL中的表连接原理分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、环境3、表连接原理【1】驱动表和被驱动表【2】内连接【3】外连接【4编程】嵌套循环连接【5】join buffer4、总结1、背景

MySQL数据库的内嵌函数和联合查询实例代码

《MySQL数据库的内嵌函数和联合查询实例代码》联合查询是一种将多个查询结果组合在一起的方法,通常使用UNION、UNIONALL、INTERSECT和EXCEPT关键字,下面:本文主要介绍MyS... 目录一.数据库的内嵌函数1.1聚合函数COUNT([DISTINCT] expr)SUM([DISTIN