第三章 程序的机器级表示

程序的机器级表示

3.1历史观点

8086—〉80286—〉i386—〉i486—〉Pentium—〉PentiumPro—〉Pentium—〉Pentium—〉Pentium4—〉Pentium4e—〉Core 2 Duo —〉Core i7

3.2程序编码

1.gcc -01 –o p p1.c p2.c      使用第一级优化

2.程序计数器(%eip)指示将要执行的下一条指令在存储器中的地址。

3.寄存器文件

4.-S:C语言编译器产生的汇编代码

例:gcc -01 –S code.c 会产生一个汇编文件code.c

3.3数据格式


char


字节


b


1


short



w


2


int


双字


1


4


long int


双字


1


4


long long int




4


char*


双字


1


4


float


单精度


s


4


Double


双精度


l


8


long double


扩展精度


t


10/12

3.4访问信息

1.操作数指示符类型:立即数、寄存器、寄存器

2.数据传送指令


指令


效果


描述


MOV      S,D


S<-D


传送


movb

movw

movl


传送字节

传送字

传送双字


MOVS     S,D


D<-符号扩展(S)


传送符号扩展的字节


MOVZ     S,D


D<-零扩展(S)


传送零扩展的字节

3.5算术和逻辑操作(20135315韩玉琪的博客)

1.加载有效地址:leal实际上是movl的变形,为存储器引用产生指针

2.一元操作和二院操作:1)++,- -;2)+=

  • 一元操作
  • - INC          加1
  • - DEC          减1
  • - NEG          取负

- NOT          取补

  • 只有一个操作数,既是源又是目的,可以是一个寄存器,或者存储器位置。
  • 二元操作
  • - ADD          加
  • - SUB          减
  • - IMUL         乘
  • - XOR          异或
  • - OR           或

- AND          与

  • 第一个操作数可以是立即数、寄存器或者存储器位置
  • 第二个操作数既是源也是又是目的。可以是寄存器或者存储器位置,但是不能同时是存储器位置。
  • 注意操作的顺序:

第二个操作数 操作符 第一个操作数

3.移位操作:>>,<<

  • 先给出移位量,第二项给出要移位的数值。
  • - SAL          左移
  • - SHL          左移(等同于SAL)
  • - SAR          算术右移

- SHR          逻辑右移

  • 源操作数(移位量):立即数或者放在单字节寄存器元素%cl中。
  • 目的操作数:一个寄存器或是一个存储器位置。

4.特殊算术操作

  • 乘法
  • 乘积截断
  • imull 双操作数

- 从两个32位操作数产生一个32位的乘积。

  • 乘积不截断
  • mull  无符号数乘法
  • imull 有符号数乘法
  • - 要求一个参数必须在寄存器%eax中,另一个作为指令的源操作数给出。

- 乘积的高32位在%edx中,低32位在%eax中。

  • 除法
  • 有符号除法
  • idivl 操作数
  • - 将DX:AX中的64位数作为被除数,操作数中为除数

- 结果:商在AX中,余数在DX中。

  • 无符号除法
  • divl指令

- 通常会事先设定寄存器%edx为0.

3.6控制

1.条件码:

CF:进位标志   ZF:零标志    SF:符号标志  OF:溢出标志

2.访问条件码

  • SET指令:执行比较指令,根据计算t=a-b的结果设置条件码

3.跳转指令及其编码:jmp *%eax

  • 无条件跳转
  • 直接跳转:跳转目标是作为指令的一部分编码的。
  • 间接跳转:跳转目标是从寄存器或存储器位置中读出的。

4.条件传送指令(参考资料20135202闫佳歆博客)

  • 将条件表达式和语句从c语言翻译成机器语言,最常用的方式就是结合有条件和无条件跳转。
  • if-else 的汇编结构
  • 通用形式模板
  • if(test-expr)
  • then-statement
  • else
  • else-statement

(注:test-expr     整数表达式[假/真])

  • 汇编实现形式
  • t = test-expr;
  • if (!t)
  • goto false;
  • then-statement
  • goto done;
  • false:
  • else-statement

done:

5.switch语句

3.7过程

1.栈帧结构:机器用栈帧来传递过程参数、存储返回信息、保存寄存器用于以后的回复以及本地存储。为单个过程分配的那部分栈称为栈帧

2.帧指针:%ebp,栈指针:%%esp

3.转移控制

call  Label         过程调用

call  *Operand      过程调用

leave               为返回准备栈

ret                 从过程调用中返回

4.寄存器使用惯例

1).%eax、%edx、%ecx  调用者保存

2).%ebx、%esi、%edi  被调用者保存

5.递归过程:递归调用一个函数本身与调用其他函数是一样的。相互调用更为复杂

问题:

1.比较指令cmp和减法指令sub有何不同?

sub d,s   是d-s,结果送回d中,即送回目的操作数中。

cmp d,s   也是d-s,但结果不送回目的操作数中,是利用减法进行两个数值的比较。

作业

  • main.c:

  • 汇编代码:

  • 用vi查看编译器指令:

  • 删除gcc产生代码中以"."开头的编译器指令后:

  • 分析:
  • main函数保存%ebp,并设置新的帧指针。
    	pushl	%ebp
    	movl	%esp,%ebp
  • 分配4字节的栈空间
    	subl	$4,%esp
  • 设置 arg1=8
    	movl	$8,(%esp)
  • call调用fh
  • fh被调用,初始化帧指针,分配栈空间。
  • 将(%esp)中的8给 %eax,即存入栈中
    	movl	%eax,(%esp)
  • call调用gh
  • gh被调用,初始化栈指针,分配栈空间
  • 将 %eax 与立即数 3 相加
    	add		$3,%eax
  • 在gh结束前弹栈
    	popl	%ebp
  • ret返回fh中call的调用位置
  • fh也结束,return返回main中call调用的位置
  • main继续 %eax 加1的操作
    	addl	$1,%eax
  • leave为返回准备栈,相当于%ebp出栈,最后ret结束。
时间: 2024-10-08 11:04:48

第三章 程序的机器级表示的相关文章

第三章程序的机器级表示 学习报告

第三章 程序的机器级表示 3.1 历史观点 Intel处理器系列俗称x86,开始时是第一代单芯片.16位微处理器之一. 每个后继处理器的设计都是后向兼容的——较早版本上编译的代码可以在较新的处理器上运行. X86 寻址方式经历三代: 1  DOS时代的平坦模式,不区分用户空间和内核空间,很不安全 2  8086的分段模式 3  IA32的带保护模式的平坦模式 3.2 程序编码 gcc -01 -o p p1.c -01 表示使用第一级优化.优化的级别与编译时间和最终产生代码的形式都有关系,一般认

CSAPP:第三章程序的机器级表示2

CSAPP:程序的机器级表示2 关键点:算术.逻辑操作 算术逻辑操作1.加载有效地址2.一元二元操作3.移位操作 算术逻辑操作 ??如图列出了x86-64的一些整数和逻辑操作,大多数操作分成了指令类(只有leaq没有其他的变种,addb.addw.addl.addq分别是字节加法.字加法.双字加法和四字加法),这些操作通常分为四组:加载有效地址.一元操作.二元操作和移位操作. 1.加载有效地址 leaq S,D;D = &S??加载有效地址指令leag实际上是movq指令的变形,它的指令形式上是

深入理解计算机系统之程序的机器级表示部分学习笔记

不论我们是在用C语言还是用JAVA或是其他的语言编程时,我们会被屏蔽了程序的机器级的实现.机器语言不需要被编译,可以直接被CPU执行,其执行速度十分  快.但是机器语言的读写性与移植性较高级语言低.高级语言被编译后便成为了汇编语言,汇编语言十分接近机器语言.之后汇编代码会转化为机器语言.虽然现代  的编译器能帮助我们将高级语言转化为汇编语言,解决了不少问题,但是对于一个严谨的程序员来说,需要做到能够阅读和理解汇编语言.我们主要围绕Intel来讲  解. 一  Intel处理器的历史演变 Inte

深入理解计算机系统(第二版)----之三:程序的机器级表示

计算机执行机器代码,用字节编码低级的操作,包括处理数据.管理存储器.读写存储设备上的数据,利用网络通信,编译器基于变成语言的原则, 目标机器的指令集合操作系统遵循的原则,经过一系列阶段产生机器代码,gcc c语言编辑器以汇编代码的形式输出,汇编代码是机器代码的文本表示,给出程序的每一条指令.然后gcc调用汇编器和链接器,根据汇编代码生成可执行的机器代码. 本章,近距离观察机器代码和汇编代码. 机器级的实现,被高级语言屏蔽了,用高级语言编写的程序可以在很多不同的机器上编译和执行,而汇编代码则是与特

六星经典CSAPP-笔记(3)程序的机器级表示

1.前言 IA32机器码以及汇编代码都与原始的C代码有很大不同,因为一些状态对于C程序员来说是隐藏的.例如包含下一条要执行代码的内存位置的程序指针(program counter or PC)以及8个寄存器.还要注意的一点是:汇编代码的ATT格式和Intel格式.ATT格式是GCC和objdump等工具的默认格式,在CSAPP中一律使用这种格式.而Intel格式则通常会在Intel的IA32架构文档以及微软的Windows技术文档中碰到.两者的主要区别有: Intel格式忽略指令中暗示操作数长度

程序的机器级表示——基础

计算机执行的是机器代码,机器代码是二进制文件,既程序.机器代码用字节(1Byte=8bit)序列编码低级的操作,例如数据处理,管理存储器,从存储设备取数据等.使用高级语言(c,c++等)编写的程序(文本形式)最终需要被编译成机器代码才可以被计算机执行.当使用GCC c编译器来编译c语言代码时,会首先将其编译成汇编语言形式的内容,然后c编译器调用汇编器和连接器来最终形成计算机可执行的机器代码.汇编语言代码是机器码的文本形式,是机器码(字节序列)的文本助记形式.现在的要求是可以理解经过编译器优化过的

C语言程序的机器级表示

过程调用的机器级表示 特别说明该表示是基于IA-32指令系统,x86 64指令系统不同于IA-32 机器级表示 可执行文件的存储器映像 调用过程 IA-32的寄存器使用约定 – 调用者保存寄存器:EAX.EDX.ECX 当过程P调用过程Q时,Q可以直接使用这三个寄存器,不用 将它们的值保存到栈中.如果P在从Q返回后还要用这三个寄 存器的话,P应在转到Q之前先保存,并在从Q返回后先恢复 它们的值再使用. – 被调用者保存寄存器:EBX.ESI.EDI Q必须先将它们的值保存到栈中再使用它们,并在返

程序的机器级表示 (2)

3.6.5 循环 据说大多数汇编器会根据do-while循环来产生代码, 所以其他循环可能会先转化为do-while形式再编译成机器代码, 所以我们首先介绍do-while循环... 1. do-while 循环 do-while的通用形式如图所示 : loop: body-statement t = test-expr; if(t) goto loop; 这里给出一个实际的例子 : 2. while循环 while循环有多种翻译方法, gcc使用了的是 先用if 进行检测第一次循环, 这样就将

程序的机器级表示

P104,p105:     X86,经历了一个长期的的不断发展的过程.开始时他是第一代单芯片和16位微处理器之一,由于当时集成电路技术水平十分有限,其中做了很多妥协.此后,他不断地成长,利用进步的技术满足更高性能和支持更高级的操作系统的需求. 8086(1978) 80286(1982) i386(1985) i486(1989) Pentium(1993) PentiumPro(1995) Pentium II(1997) Pentium III(1999) Pentium 4(2000)