实验11_程序的机器级表示_过程_实验报告
基于编程的计算机组成原理实验教学

本栏目责任编辑:王力计算机教学与教育信息化基于编程的计算机组成原理实验教学吴元斌(重庆三峡学院计算机科学与工程学院,重庆404000)摘要:该文分析了基于编程的计算机组成原理实验教学方法,介绍了字节顺序和数据对齐、存储器层次结构与局部性原理、整数的机器表示与运算、浮点数的表示与运算、DEBUG 与机器指令、C 语言程序的机器级表示等实验教学内容。
实践表明,基于编程的实验教学对学生学习和掌握计算机组成原理十分有效。
关键词:计算机组成原理;实验;教学;编程;C 语言中图分类号:G642文献标识码:A文章编号:1009-3044(2020)36-0110-03开放科学(资源服务)标识码(OSID ):Experimental Teaching in the Principles of Computer Organization based on Programming WU Yuan-bin(Department of Computer Science and Engineering,Wanzhou 404000,China)Abstract :the experimental teaching method of computer composition principle based on programming are analyzed in this paper.the byte ordering and data alignment,the memory hierarchy and the principle of locality,the machine representation and operation of integers,the representation and operation of floating-point numbers,debug and machine instructions,and machine level repre⁃sentation of C language programs are introduced.Practice shows that the experimental teaching method based on programming is very effective for students to learn and master the principles of computer organization.Key words :the principles of computer organization;experiment;teaching;programming;the c language1引言计算机组成原理课程的主要目标是:(1)理解单处理器计算机系统中各部件的内部工作原理、组成结构以及相互连接方式,具有完整的计算机系统的整机概念。
实验03整数的表示实验

浙江大学城市学院实验报告课程名称计算机系统原理实验实验项目名称实验三数据的机器级表示实验成绩指导老师(签名)日期一、实验目的:1、通过无符号数和带符号整数之间的相互转换来理解无符号数和补码整数的表示;2、了解IEEE 754浮点数在机器中的应用,特别是一些特殊值的处理。
二、实验步骤:1、用32位补码表示的机器上编译并执行以下程序,记录程序的执行结果,并解释原因。
图3-1运行结果:对运算结果的解释:第一个结果:因为在ISO C90标准中,编译器将-2147483648分为两个部分来处理。
首先将2147483648看成无符号整型,其机器数为0x80000000,然会对其取负,结果仍为0x80000000,还是将其看成无符号整型,其值仍为21474833648,因此前者大于后者。
第二个结果:由于i为int型变量,因此这两个数皆为带符号数,前者小于后者。
第三个结果:编译器首先将2147483647看成带符号整型,然后对其取负,得到-2147483647,然后对其-1得到-2147483648,因此前者大于后者。
2、编写程序,计算表2.1中的表达式,说明运算类型(无符号、带符号),得到运算结果,并说明为什么是这样的运算结果(参考第二章习题8);源代码:运算结果:对运算结果的解释:1.0和0U都是无符号数,值相等2.-1和0都为带符号数,因此前者小于后者3.0后加上U表示无符号数,因此比较时前者大于后者4.-2147483647-1的计算结果为一个int型整数,为带符号数,因此前者大于后者。
5.加上U的数都为无符号数,因此前者小于后者6.2147483648U在经过int强制类型转换后,变为带符号的-2147483648,因此前者大于后者7.两个数皆为带符号数,因此前者大于后者8.数据转化为无符号数,前者11…1B (2^32-1) > 后者11…10B (2^32-2)3、分析以下代码:当len = 0 时, 执行sum 函数的for循环时会发生Access Violation , 即段错误异常. 但是, 当参数len 说明为int 型时, sum 函数能正确执行, 为什么?编写程序测试并分析。
编译原理—pl0实验报告

PL/0实验报告课程名称编译原理题目名称PL/0编译程序学生学院计算机科学与技术学院专业班级学号学生姓名班内序号山东理工大学实验报告纸第 1 页姓名:蔡鹏飞计算机院_11_级02班同组者成绩_________室温:气压:课程名称:编译原理教师签字实验项目编号(1)PL/0编译程序的分析指导教师鞠传香实验目的1.熟悉pl/0语言并能编写小程序2.掌握pl/0编译程序的编译过程(词法分析、语法分析、语义分析等)实验仪器(编号)材料、工具PC机、VC++6.0(原理概述)pl/0语言编译程序采用以语法分析为核心、一遍扫描的编译方法。
词法分析和代码生成作为独立的子程序供语法分析程序调用。
语法分析的同时,提供了出错报告和出错恢复的功能。
在源程序没有错误编译通过的情况下,调用类pcode解释程序解释执行生成的类pcode代码。
PL/0语言文法的EBNF表示EBNF表示的符号说明。
〈〉:用左右尖括号括起来的中文字表示语法构造成分,或称语法单位,为非终结符。
∷= :该符号的左部由右部定义,可读作'定义为'。
| :表示'或',为左部可由多个右部定义。
{ } :花括号表示其内的语法成分可以重复。
在不加上下界时可重复0到任意次数,有上下界时为可重复次数的限制。
如:{*}表示*重复任意次,{*}38表示*重复3-8次。
[ ] :方括号表示其内的成分为任选项。
( ) :表示圆括号内的成分优先。
例:用EBNF描述<整数>文法的定义:<整数>∷=[+|-]<数字>{<数字>}<数字>∷=0|1|2|3|4|5|6|7|8|9或更好的写法<整数>∷=[+|-]<非零数字>{<数字>}|0<非零数字>∷=1|2|3|4|5|6|7|8|9<数字>∷=0|<非零数字>PL/0语言文法的EBNF表示PL/0语言文法的EBNF表示为:〈程序〉∷=〈分程序〉.〈分程序〉∷=[〈常量说明部分〉][〈变量说明部分〉][〈过程说明部分〉]〈语句〉〈常量说明部分〉∷=CONST〈常量定义〉{,〈常量定义〉};〈常量定义〉∷=〈标识符〉=〈无符号整数〉〈无符号整数〉∷=〈数字〉{〈数字〉}〈变量说明部分〉∷=VAR〈标识符〉{,〈标识符〉};〈标识符〉∷=〈字母〉{〈字母〉|〈数字〉}〈过程说明部分〉∷=〈过程首部〉〈分程序〉{;〈过程说明部分〉};〈过程首部〉∷=PROCEDURE〈标识符〉;〈语句〉∷=〈赋值语句〉|〈条件语句〉|〈当型循环语句〉|〈过程调用语句〉|〈读语句〉|〈写语句〉|〈复合语句〉|〈空〉〈赋值语句〉∷=〈标识符〉∶=〈表达式〉〈复合语句〉∷=BEGIN〈语句〉{;〈语句〉}END〈条件〉∷=〈表达式〉〈关系运算符〉〈表达式〉|ODD〈表达式〉〈表达式〉∷=[+|-]〈项〉{〈加法运算符〉〈项〉}〈项〉∷=〈因子〉{〈乘法运算符〉〈因子〉}〈因子〉∷=〈标识符〉|〈无符号整数〉|'('〈表达式〉')'〈加法运算符〉∷=+|-〈乘法运算符〉∷=*|/// 栈顶指针减一相关过程:base(),interpret()。
华科_计算机系统实验报告

课程实验报告课程名称:计算机系统基础专业班级:学号:姓名:指导教师:报告日期:年月日计算机科学与技术学院目录实验1: (1)实验2: (7)实验3: (24)实验总结 (34)实验1:数据表示1.1 实验概述实验目的:更好地熟悉和掌握计算机中整数和浮点数的二进制编码表示。
实验目标:加深对数据二进制编码表示的了解。
实验要求:使用有限类型和数量的运算操作实现一组给定功能的函数。
实验语言:c。
实验环境:linux1.2 实验内容需要完成bits.c中下列函数功能,具体分为三大类:位操作、补码运算和浮点数操作。
1)位操作表1列出了bits.c中一组操作和测试位组的函数。
其中,“级别”栏指出各函数的难度等级(对应于该函数的实验分值),“功能”栏给出函数应实现的输出(即功能),“约束条件”栏指出你的函数实现必须满足的编码规则(具体请查看bits.c中相应函数注释),“最多操作符数量”指出你的函数实现中允许使用的操作符的最大数量。
你也可参考tests.c中对应的测试函数来了解所需实现的功能,但是注意这些测试函数并不满足目标函数必须遵循的编码约束条件,只能用做关于目标函数正确行为的参考。
表1 位操作题目列表2)补码运算表2列出了bits.c中一组使用整数的补码表示的函数。
可参考bits.c中注释说明和tests.c中对应的测试函数了解其更多具体信息。
表2 补码运算题目列表3)浮点数操作表3列出了bits.c中一组浮点数二进制表示的操作函数。
可参考bits.c中注释说明和tests.c中对应的测试函数了解其更多具体信息。
注意float_abs的输入参数和返回结果(以及float_f2i函数的输入参数)均为unsigned int类型,但应作为单精度浮点数解释其32 bit二进制表示对应的值。
表3 浮点数操作题目列表表示,当输入参数是NaN 时,返回NaN 号整型操作,包括||,&&以及if,while控制结构4 float_f2i 返回浮点数‘f’的强制整型转换“(int)f”表示仅能使用任何整型/无符号整型操作,包括||,&&以及if,while控制结构301.3 实验设计根据题目要求,选择合适的操作符来编写代码。
华中科技大学计算机系统基础实验报告

课程实验报告课程名称:计算机系统基础专业班级:学号:姓名:指导教师:报告日期:2016年5月24 日计算机科学与技术学院目录实验1: (2)实验2: (9)实验3: (22)实验总结 (30)实验1:数据表示1.1 实验概述本实验的目的是更好地熟悉和掌握计算机中整数和浮点数的二进制编码表示。
实验中,你需要解开一系列编程“难题”——使用有限类型和数量的运算操作实现一组给定功能的函数,在此过程中你将加深对数据二进制编码表示的了解。
实验语言:c; 实验环境: linux1.2 实验内容需要完成bits.c 中下列函数功能,具体分为三大类:位操作、补码运算和浮点数操作。
1.3 实验设计源码如下:/** lsbZero - set 0 to the least significant bit of x* Example: lsbZero(0x87654321) = 0x87654320* Legal ops: ! ~ & ^ | + << >>* Max ops: 5* Rating: 1*/int lsbZero(int x) {//x右移一位再左移一位实现把最低有效位置0x = x>>1;x = x<<1;return x;}/** byteNot - bit-inversion to byte n from word x* Bytes numbered from 0 (LSB) to 3 (MSB)* Examples: getByteNot(0x12345678,1) = 0x1234A978* Legal ops: ! ~ & ^ | + << >>* Max ops: 6* Rating: 2*/int byteNot(int x, int n) {//x第n个字节每位都和1异或实现取反int y = 0xff;n = n<<3;y = y<<n;x = (x^y);return x;}/** byteXor - compare the nth byte of x and y, if it is same, return 0, if not, return 1* example: byteXor(0x12345678, 0x87654321, 1) = 1* byteXor(0x12345678, 0x87344321, 2) = 0* Legal ops: ! ~ & ^ | + << >>* Max ops: 20* Rating: 2*/int byteXor(int x, int y, int n) {//把x和y的第n个字节取出来异或,再转换为逻辑的0和1n = n<<3;x = x>>n;y = y>>n;x = x&(0xff);y = y&(0xff);return !!(x^y);}/** logicalAnd - x && y* Legal ops: ! ~ & ^ | + << >>* Max ops: 20* Rating: 3*/int logicalAnd(int x, int y) {//把x和y分别转化为逻辑的0和1,再相与x = (!(!x))&(!(!y));return x;}/** logicalOr - x || y* Legal ops: ! ~ & ^ | + << >>* Max ops: 20* Rating: 3*/int logicalOr(int x, int y) {//把x和y分别转化为逻辑的0和1,再相或x = (!(!x))|(!(!y));return x;}/** rotateLeft - Rotate x to the left by n* Can assume that 0 <= n <= 31* Examples: rotateLeft(0x87654321,4) = 0x76543218* Legal ops: ~ & ^ | + << >> !* Max ops: 25* Rating: 3*/int rotateLeft(int x, int n) {//先构造低n位为1,高(32-n)位为0的数z,x左移n位后的数加上x右移(32-n)位的数&z即可int z;z = ~(((1<<31)>>31)<<n);x = ((x>>(32+(~n+1)))&z)+(x<<n);return x;}/** parityCheck - returns 1 if x contains an odd number of 1's* Examples: parityCheck(5) = 0, parityCheck(7) = 1* Legal ops: ! ~ & ^ | + << >>* Max ops: 20* Rating: 4*/int parityCheck(int x) {//每次将数的低半数位与高半数位比较,再把y右移31位,最后把y转化为逻辑的0和1int y;y = x<<16;y = y^x;y = y^(y<<8);y = y^(y<<4);y = y^(y<<2);y = y^(y<<1);y = y>>31;return !(!y);}/** mul2OK - Determine if can compute 2*x without overflow* Examples: mul2OK(0x30000000) = 1* mul2OK(0x40000000) = 0** Legal ops: ~ & ^ | + << >>* Max ops: 20* Rating: 2*/int mul2OK(int x) {//把x第31位和30位分别和1做按位与,再异或,再和1异或int m;m = ((x>>31)&0x1)^((x>>30)&0x1);return m^0x1;}/** mult3div2 - multiplies by 3/2 rounding toward 0,* Should exactly duplicate effect of C expression (x*3/2),* including overflow behavior.* Examples: mult3div2(11) = 16* mult3div2(-9) = -13* mult3div2(1073741824) = -536870912(overflow)* Legal ops: ! ~ & ^ | + << >>* Max ops: 12* Rating: 2*/int mult3div2(int x) {//左移一位再+x即x*3,右移一位的时候,当y的最高位和最低位都为0时还要+1int y = (x<<1)+x;y = (y>>1)+(((y>>31)&1)&(((y<<31)>>31)&1));return y;}/** subOK - Determine if can compute x-y without overflow* Example: subOK(0x80000000,0x80000000) = 1,* subOK(0x80000000,0x70000000) = 0,* Legal ops: ! ~ & ^ | + << >>* Max ops: 20* Rating: 3*/int subOK(int x, int y) {//x的最高有效位和y的最高有效位不同且x和(x-y)的最高位不同才能判断溢出int m = (x>>31)&1;int n = (y>>31)&1;x = (m^n)&(m^(((x+(~y+1))>>31)&1));return (!x);}/** absVal - absolute value of x* Example: absVal(-1) = 1.* You may assume -TMax <= x <= TMax* Legal ops: ! ~ & ^ | + << >>* Max ops: 10* Rating: 4*/int absVal(int x) {//x最高位为0时就是x,最高位为1时是~x+1int y = x>>31;x = (y&(~x+1))+((~y)&x);return x;}/** float_abs - Return bit-level equivalent of absolute value of f for * floating point argument f.* Both the argument and result are passed as unsigned int's, but * they are to be interpreted as the bit-level representations of * single-precision floating point values.* When argument is NaN, return argument..* Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while* Max ops: 10* Rating: 2*/unsigned float_abs(unsigned uf) {int x=uf&(~(1<<31));if(x>0x7f800000){return uf;}else return x;}/** float_f2i - Return bit-level equivalent of expression (int) f* for floating point argument f.* Argument is passed as unsigned int, but* it is to be interpreted as the bit-level representation of a* single-precision floating point value.* Anything out of range (including NaN and infinity) should return * 0x80000000u.* Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while* Max ops: 30* Rating: 4*/int float_f2i(unsigned uf) {unsigned num=0x80000000;int x=(uf&0x007fffff)^0x00800000;int order=0;order=(uf&0x7f800000)>>23;if(order>158){return num;}if(order<127) return 0;else if(((uf>>31)&1)==1){if(order>150){return ~(x<<(order-150))+1;}else return ~(x>>(150-order))+1;}else{if(order>150) return x<<(order-150);else return x>>(150-order);}}1.4 实验过程编写源码,运行btest,得出实验结果。
华科_计算机系统实验报告

课程实验报告课程名称:计算机系统基础专业班级:学号:姓名:指导教师:报告日期:年月日计算机科学与技术学院目录实验1: (1)实验2: (7)实验3: (24)实验总结 (34)实验1:数据表示1.1 实验概述实验目的:更好地熟悉和掌握计算机中整数和浮点数的二进制编码表示。
实验目标:加深对数据二进制编码表示的了解。
实验要求:使用有限类型和数量的运算操作实现一组给定功能的函数。
实验语言:c。
实验环境:linux1.2 实验内容需要完成bits.c中下列函数功能,具体分为三大类:位操作、补码运算和浮点数操作。
1)位操作表1列出了bits.c中一组操作和测试位组的函数。
其中,“级别”栏指出各函数的难度等级(对应于该函数的实验分值),“功能”栏给出函数应实现的输出(即功能),“约束条件”栏指出你的函数实现必须满足的编码规则(具体请查看bits.c中相应函数注释),“最多操作符数量”指出你的函数实现中允许使用的操作符的最大数量。
你也可参考tests.c中对应的测试函数来了解所需实现的功能,但是注意这些测试函数并不满足目标函数必须遵循的编码约束条件,只能用做关于目标函数正确行为的参考。
表1 位操作题目列表2)补码运算表2列出了bits.c中一组使用整数的补码表示的函数。
可参考bits.c中注释说明和tests.c中对应的测试函数了解其更多具体信息。
表2 补码运算题目列表3)浮点数操作表3列出了bits.c中一组浮点数二进制表示的操作函数。
可参考bits.c中注释说明和tests.c中对应的测试函数了解其更多具体信息。
注意float_abs的输入参数和返回结果(以及float_f2i函数的输入参数)均为unsigned int类型,但应作为单精度浮点数解释其32 bit二进制表示对应的值。
表3 浮点数操作题目列表表示,当输入参数是NaN 时,返回NaN 号整型操作,包括||,&&以及if,while控制结构4 float_f2i 返回浮点数‘f’的强制整型转换“(int)f”表示仅能使用任何整型/无符号整型操作,包括||,&&以及if,while控制结构301.3 实验设计根据题目要求,选择合适的操作符来编写代码。
大学机械基础实验报告

大学机械基础实验报告本实验的主要目的是通过进行机械基础实验来加深对机械原理和机械基本知识的理解,掌握力学和热学的基础实验方法,培养实验操作能力和科学分析能力。
同时,通过实验数据的处理和结果分析,了解机械实验中的误差来源,并学会如何进行误差分析和控制。
实验装置和实验原理:本次实验使用了一台名称为“XX实验装置”的设备,该设备采用了电磁和电动机作为动力源驱动组件,通过齿轮和传动系统将电机的旋转运动转化为线性运动,并且配备了测量传感器和数据采集系统,可以实时监测和记录实验过程中的相关数据。
实验中,我们首先将实验装置放置在水平台面上,并进行了装置的校正和调试。
然后,我们分别进行了实验A和实验B两个部分的实验操作。
实验A的实验原理是通过对不同质量物体的运动学和动力学的实验研究来验证机械的牛顿力学定律。
我们首先测量了不同质量物体的质量和体积,并用测量仪器得到物体下落的时间和距离数据。
然后,我们利用牛顿第二定律和运动学公式来计算物体下落过程中的加速度和作用力,并与实验测得的数据进行比较和分析。
实验B的实验原理是通过测量不同材料线性膨胀系数对材料热学性质的影响来验证热学膨胀定律。
我们首先测量了不同材料的长度和温度,并利用实验装置加热和冷却不同材料样品,实时测量相应的温度和长度数据。
然后,我们根据线性膨胀定律和热学公式来计算材料线性膨胀系数,并与实验数据进行比较和分析。
实验结果和数据处理:根据实验A的数据分析,我们得到了不同质量物体的加速度和作用力随质量的变化关系图。
根据数据处理和拟合曲线,我们得到了质量和加速度、作用力之间的数学关系。
根据实验B的数据分析,我们得到了不同材料的线性膨胀系数与温度变化的关系图。
根据数据处理和拟合曲线,我们得到了线性膨胀系数和温度之间的数学关系。
讨论与结论:通过本次实验,我们加深了对机械原理和机械基本知识的理解。
通过数据分析和结果讨论,我们验证了机械的牛顿力学定律和热学的膨胀定律。
在数据处理过程中,我们也发现了实验误差的来源,并学会了如何进行误差分析和控制。
编译原理实验报告

编译原理实验报告一、实验目的编译原理是计算机科学中的重要学科,它涉及到将高级编程语言转换为计算机能够理解和执行的机器语言。
本次实验的目的是通过实际操作和编程实践,深入理解编译原理中的词法分析、语法分析、语义分析以及中间代码生成等关键环节,提高我们对编译过程的认识和编程能力。
二、实验环境本次实验使用的编程语言为C++,开发环境为Visual Studio 2019。
此外,还使用了一些相关的编译工具和调试工具,如 GDB 等。
三、实验内容(一)词法分析器的实现词法分析是编译过程的第一步,其任务是将输入的源程序分解为一个个单词符号。
在本次实验中,我们使用有限自动机的理论来设计和实现词法分析器。
首先,定义了各种单词符号的类别,如标识符、关键字、常量、运算符等。
然后,根据这些类别设计了相应的状态转换图,并将其转换为代码实现。
在实现过程中,使用了正则表达式来匹配输入字符串中的单词符号。
对于标识符和常量等需要进一步处理的单词符号,使用了相应的规则进行解析和转换。
(二)语法分析器的实现语法分析是编译过程的核心环节之一,其任务是根据给定的语法规则,分析输入的单词符号序列是否符合语法结构。
在本次实验中,我们使用了递归下降的语法分析方法。
首先,根据实验要求定义了语法规则,并将其转换为相应的递归函数。
在递归函数中,通过对输入单词符号的判断和处理,逐步分析语法结构。
为了处理语法错误,在分析过程中添加了错误检测和处理机制。
当遇到不符合语法规则的输入时,能够输出相应的错误信息,并尝试进行恢复。
(三)语义分析及中间代码生成语义分析的目的是对语法分析得到的语法树进行语义检查和语义处理,生成中间代码。
在本次实验中,我们使用了三地址码作为中间代码的表示形式。
在语义分析过程中,对变量的定义和使用、表达式的计算、控制流语句等进行了语义检查和处理。
对于符合语义规则的语法结构,生成相应的三地址码指令。
四、实验步骤(一)词法分析器的实现步骤1、定义单词符号的类别和对应的正则表达式。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
浙江大学城市学院实验报告
课程名称计算机系统原理实验
实验项目名称实验十一程序的机器级表示——过程
学生姓名专业班级学号
实验成绩指导老师(签名)日期
注意:
●务请保存好各自的源代码,已备后用。
●请把作业同时上传到BB平台和FTP。
●文件名为:学号_姓名_日期_实验几,如30801001_姓名_20100305_实验01
●ftp://10.66.28.222:2007huommupload 123456
一、实验目的:
了解IA32指令系统的常用指令,了解Linux汇编语言的基本语法、汇编语言的编写、调试技巧。
二、实验内容:
1、阅读给出test11_1.c以及对应的反汇编代码,为汇编代码添加注释,并画出函数调用前后的栈帧结构图。
2、阅读给出test11_2.c以及对应的汇编代码,为汇编代码添加注释,并补充完整c程序源码。
三、实验步骤:
1、阅读给出test11_1.c以及对应的反汇编代码,为汇编代码添加注释,并画出函数调用前后的栈帧结构图。
指令注释:
08048354 <swap_add>:
8048354: 55 push %ebp #
8048355: 89 e5 mov %esp,%ebp #
8048357: 53 push %ebx #
8048358: 8b 55 08 mov 0x8(%ebp),%edx #
804835b: 8b 4d 0c mov 0xc(%ebp),%ecx # 804835e: 8b 1a mov (%edx),%ebx # 8048360: 8b 01 mov (%ecx),%eax # 8048362: 89 02 mov %eax,(%edx) # 8048364: 89 19 mov %ebx,(%ecx) # 8048366: 01 d8 add %ebx,%eax # 8048368: 5b pop %ebx #
8048369: 5d pop %ebp #
804836a: c3 r et
0804836b <caller>:
804836b: 55 push %ebp #
804836c: 89 e5 mov %esp,%ebp #
804836e: 83 ec 18 sub $0x18,%esp # 8048371: c7 45 fc 7b 00 00 00 movl $0x7b,0xfffffffc(%ebp) # 8048378: c7 45 f8 c8 01 00 00 movl $0x1c8,0xfffffff8(%ebp) # 804837f: 8d 45 f8 lea 0xfffffff8(%ebp),%eax # 8048382: 89 44 24 04 mov %eax,0x4(%esp) # 8048386: 8d 45 fc lea 0xfffffffc(%ebp),%eax # 8048389: 89 04 24 mov %eax,(%esp) #
804838c: e8 c3 ff ff ff call 8048354 <swap_add> # 8048391: 8b 55 fc mov 0xfffffffc(%ebp),%edx # 8048394: 2b 55 f8 sub 0xfffffff8(%ebp),%edx # 8048397: 0f af c2 imul %edx,%eax #
804839a: c9 l eave #
804839b: c3 r et #
调试过程及结果解释(截图):
函数栈帧结构图:
调用swap_add之前:
caller栈帧
调用swap_add 过程当中:
2、(选做)
1)为汇编代码每行添加注释;fun
存储在被调用者保存寄存器%ebx 中的值是什
么?
fun:
pushl %ebp #
movl %esp, %ebp #
pushl %ebx #
subl $4, %esp #
movl 8(%ebp), %ebx #
movl $0, %eax # testl %ebx, %ebx #test 指令的作用:两个操作数按位与,根据与的结果设 置相应的标志位,但是相与的结果并不保留。
je .L4 #
movl %ebx, %eax #
shrl %eax #
movl %eax, (%esp) #
call fun # movl %ebx, %edx #
swap_add 栈帧 caller 栈帧 caller 栈帧
andl $1, %edx #
leal (%edx,%eax), %eax #
.L4:
addl $4, %esp #
popl %ebx #
popl %ebp #
ret #
2)填写上述c代码中缺失的表达式;
3)描述fun函数的功能;
求(x+1)/2
4)调试验证理解:
四、思考题(必做)
1)函数调用时,实参存储在哪个函数的栈帧中?
函数调用时的内存分析
(为即将调用的函数准备参数)
mov %ebp+偏移,%eax 将参数传到eax
mov %eax ,%esp+偏移将参数放到当前空间。
sub $18 ,%ebp #将栈底指针向下移动以存放参数和变量。
(call 保存函数执行现场)
call %eip
相当于指令:push %eip
mov addr ,%eip
(保存栈的相关指针)
push %ebp #保存栈顶。
mov %esp, %ebp #将栈底赋给栈顶。
(将返回值放入eax中,供调用函数读取)
mov 返回变量地址, %eax
(还原栈指针,释放被调用函数的内存空间。
)
leave
相当于一下指令:mov %ebp, %dsp
pop %ebp
(恢复调用前的现场)
ret
相当于一下指令:~call
pop %eip //恢复执行前的地址。
问题:
每次为参数和变量预留空间时sub的值是怎么确定的?
sub 的值是由被调用函数内部声明的变量和参数决定的。
每多一个参数地址就加0x04,而函数中的变量为每四个,地址就增加0x10。
例如:有两个整形参数,则加0x08,有一个整形参数的话加0x10,有四个整形参数也加0x10,有五个时就加0x20。
2)函数调用过程中,为什么必须保持%ebp和%esp的值?
为了确保栈帧位置与大小。
以免出错。