3.2程序编码

unix> gcc -01 -o p p1.c p2.c

-o用于指定输出(out)文件名。

-01,-02 告诉编译器使用第一级或第二级优化

3.2.1机器级代码

机器级编程两种重要的抽象:

1.ISA(指令集体系结构):机器级程序的格式和行为,叙述成按顺序执行,一条指令结束后,下一条再开始。

2.机器级程序使用的储存器地址是虚拟地址,提供的储存器模型看上去是一个非常大的字节数组。

IA32:

1.程序计数器

2.整数寄存器文件

3.条件码寄存器保存着最近执行的算术或逻辑指令的状态信息。

4.一组浮点寄存器存放浮点数据。

3.2.2代码示例

gcc  -S -o code.s code.c产生一个汇编文件code.svim code.s

objdump -d xxx.xx使用反汇编器查看目标代码文件的内容。

机器代码和它的反汇编表示的一些特性

1.IA32指令长度从1到15个字节不等

2.设计指令格式的方式是,从某个给定位置开始,可以将字节唯一的解码成机器指令

3.反汇编器只是基于机器代码文件中的字节序列来确定汇编代码,不需要访问程序的源代码或汇编代码

4.反汇编器使用的指令命名规则与GCC生成的汇编代码使用的有些差别

3.3数据格式

8 位:字节

16位:字

32位:双字

64位:四字

16位的机器体系结构,Intel用术语"字(word)"表示16位数据类型。

32位机器体系结构是从16位扩展过来,因此称32位数为“双字(double words)”,称64位数为“四字(quad words)”。

大部分指令都是针对字节和双字操作的。

C声明               Intel数据类型                          GAS后缀                                      大小(字节)

char                 字节(byte)                             b                                                       1

short                字(word)                               w                                                       2

int                    双字(double words)            l                                                        4

unsigned         双字(double words)            l                                                        4

long int           双字(double words)             l                                                        4

unsigned long    双字(double words)         l                                                        4

char *                  双字(double words)         l                                                        4

float                 单精度(signal)                      s                                                        4

double              双精度(double)                  l                                                         8

long double       扩展精度                                 t                                                     10/12

GAS中的每个操作指令都有一个字符后缀,用于表明操作数的大小。例如,mov有三种形式: movb(传送字节)、movw(传送字)、movl(传送双字)。其中float的后缀也是l,这不会与整数的混淆,因为浮点数使用的一组完全不同的指令和寄存器(浮点数寄存器)。

3.4访问信息

在IA32中央处理单元(CPU)中,包含了8个32位整数寄存器。在每个32位寄存器的名字前面都会有一个%e,在这里可以把e理解成extended(扩展的),因为早期的8086寄存器是16位,所以加e之后就变成32位的了。

3.4.1操作数指示符

操作数指示符包括立即数,寄存器,存储器。

类型

格式

操作数值

名称

立即数

$Imm

Imm

立即数寻址

寄存器

Ea

R[Ea]

寄存器寻址

存储器

Imm

M[Imm]

绝对寻址

存储器

(Ea)

M[R[Ea]]

间接寻址

存储器

Imm(Eb)

M[Imm + R[Eb]]

(基址+偏移量)寻址

存储器

(Eb, Ei)

M[R[Eb] + R[Ei]]

变址寻址

存储器

Imm(Eb, Ei)

M[Imm + R[Eb] + R[Ei]]

变址寻址

存储器

(, Ei, s)

M[R[Ei] * s]

比例变址寻址

存储器

Imm(, Ei, s)

M[Imm + R[Ei] * s]

比例变址寻址

存储器

(Eb, Ei, s)

M[R[Eb] + R[Ei]*s]

比例变址寻址

寄存器

Imm (Eb, Ei, s)

M[Imm + R[Eb] + R[Ei]*s]

比例变址寻址

3.4.2数据传送指令

将数据从一个位置复制到另一个位置的指令是最频繁使用的指令

传送指令MOV

MOV reg/mem,imm           ;立即数送寄存器或是存储器

MOV reg/mem/seg,reg      ;寄存器送寄存器(包括段寄存器)或贮存

MOV reg/seg,mem            ;主存送寄存器(包括段寄存器)

MOV reg/mem,seg            ;段寄存器送主存或寄存器

特别说明:(1)立即数传送至通用寄存器(不包括段寄存器)或存储单元

(2)IA32的限制:两个操作数都不能指向存储器。

3.5算术和逻辑操作

3.5.1加载有效地址    3.5.2一元和二元操作     3.5.3移位操作

加载有效地址指令leal 实际上是movl指令的变形,它的指令形式是从储存器读数据到寄存器,但实际上它没用引用储存器。

一元操作

只有一个操作数,既是源又是目的,可以是一个寄存器,或者存储器位置。

二元操作

操作数既是源又是目的

·第一个操作数可以是立即数、寄存器或者存储器位置 第二个操作数可以是寄存器或者存储器位置 但是不能同时是存储器位置。

移位操作

SAL 算术左移

SHL 逻辑左移

SAR 算术右移(补符号位)

SHR 逻辑右移(补0)

3.5.5特殊的算术操作

imull

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

mull
         无符号数乘法

要求一个参数必须在寄存器%eax中,另一个作为指令的源操作数给出。乘积的高32位在%edx中,低32位在%eax中。

idivl

有符号除法

操作数

将DX:AX中的64位数作为被除数,操作数中为除数,结果商在AX中,余数在DX中。

divl无符号除法

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

3.6控制

3.6.1条件码

条件语句、循环语句和分支语句,要求有条件的进行,根据数据测试的结果来决定操作执行的顺序。机器代码提供两种基本的低级机制来实现有条件的行为:测试数据值,然后根据测试的结果来改变控制流或者数据流

控制指令-条件码

CPU维护着一组单个位的条件码寄存器,他们描述了最近的算术或者逻辑操作的属性。可以检测这些寄存器来执行条件分支指令

最常用的条件码:

CF:进位标志。最近的操作使最高位产生了进位。可以用来检查无符号操作数的溢出

ZF:零标志。最近的操作得出的结果为0.

SF:符号标志。最经的操作得到的结果为负数。

OF:溢出标志。最近的操作导致一个补码溢出——正溢出或者负溢出

比较和测试指令

有两类指令只设置条件码而不改变任何其他寄存器。

CMP指令根据两个操作数之间的差来设置条件码。

TEST指令的行为同and一样。典型的用法是,testl %eax,%eax用来检查%eax是负数、零还是正数

3.6.2访问条件码

三种方法

1.根据条件码的某个组合,将一个字节设置为0或者1

2.可以条件跳转到程序的某个其他的部分

3.可以有条件地传送数据

3.6.3、跳转指令及其编码

jump分为直接跳转和间接跳转

直接跳转:后面跟标号作为跳转目标

间接跳转:*后面跟一个操作数指示符

 

 

3.6.4翻译条件分支

将条件表达式和语句从c语言翻译成机器语言,最常用的方式就是结合有条件和无条件跳转

无条件跳转:例如 goto。书上的例子就是把if-else语句翻译成了goto形式,然后再由这个形式翻译成汇编语言。

3.6.5循环

1.Do-while循环

源代码

do{

body-statement 

}while(test-expr)

翻译成汇编的伪代码

loop:

         body-statement;

t = test-expr;

if(t)

goto loop;

2.While循环

源代码

while(test-expr)

body-statement

翻译成汇编的伪代码

t = test-expr;

if(!t)

goto done;

loop:

body-statement;

t = test-expr;

if(t)

goto loop;

done:

For循环

源代码:

for(init-expr;

test-expr;

update-expr)

body-statement;

翻译成汇编的伪代码:

init-expr;

t = test-expr;

if(!t)

goto done;

loop:

body-statement;

update-expr;

t = test-expr;

if(t)

goto loop;

done:

switch语句

根据一个整数索引值进行多重分支,执行switch语句的关键步骤是通过跳转表来访问代码位置,使结构更加高效。

3.7过程

数据传递、局部变量的分配和释放通过操纵程序栈来实现。

3.7.1栈帧结构

·      为单个过程分配的栈叫做栈帧,寄存器%ebp为帧指针,而寄存器指针%esp为栈指针,程序执行时栈指针移动,大多数信息的访问都是相对于帧指针。

·      栈向低地址方向增长,而栈指针%esp指向栈顶元素。

3.7.2转移控制

call:目标是指明被调用过程起始的指令地址,效果是将返回地址入栈,并跳转到被调用过程的起始处。

ret:从栈中弹出地址,并跳转到这个位置。

函数返回值存在%eax中

3.7.3寄存器使用惯例

程序寄存器是唯一能被所有过程共享的资源,调用者保存寄存器 和 被调用者保存寄存器是分开的,对于哪一个寄存器保存函数调用过程中的返回值要有统一的约定。

3.11使用GDB调试器

命令

参数含义

说明

display

设置自动显示列表,不带参数时显示列表中所有表达式

delete display dnums…..

自动显示列表的ID号

删除自动显示列表

disable dislay dnums…..

自动显示列表的ID号

禁用自动显示列表

enable display dnums…..

自动显示列表的ID号

使用自动显示列表

info display

显示自动显示列表中的表达式

show convenience

显示快捷变量

macro expand expression

包含宏定义的表达式

将表达式宏展示

info macro macroname

宏定义的名字

查看宏定义的信息

generatre-core file

产生转储文件

backtrace

n 最内层的n个函数栈帧

-n 最外层n个函数栈帧

栈帧回溯

frame

栈帧号或者内存地址

选定栈帧,不带参数时显示栈帧简要信息

up

栈帧号

选定栈帧上移

down

栈帧号

选定栈帧下移

info frame

显示栈帧详细信息

info agrs

显示当前选定栈帧的函数参数

info locals

显示当前选定栈帧中的所有局部变量

set variable expr

赋值表达式

给变量赋值或者修改变量的值

print

赋值表达式

给变量赋值或者修改变量的值

jump

使程序从另外的地址开始执行

signal sig

信号值或者信号和名称

向被调试程序发送信号

call expr

包含函数调用的表达式

调用函数

print expr

包含函数调用的表达式

调用函数

list

函数名 行号 地址 偏移等

列出程序源码

set listsize count

设置 list默认显示的行数

disassemble

反汇编被调试程序

set disassembly-flavor instruction-set

设置反汇编格式

 

命令

参数含义

说明

display

设置自动显示列表,不带参数时显示列表中所有表达式

delete display dnums…..

自动显示列表的ID号

删除自动显示列表

disable dislay dnums…..

自动显示列表的ID号

禁用自动显示列表

enable display dnums…..

自动显示列表的ID号

使用自动显示列表

info display

显示自动显示列表中的表达式

show convenience

显示快捷变量

macro expand expression

包含宏定义的表达式

将表达式宏展示

info macro macroname

宏定义的名字

查看宏定义的信息

generatre-core file

产生转储文件

backtrace

n 最内层的n个函数栈帧

-n 最外层n个函数栈帧

栈帧回溯

frame

栈帧号或者内存地址

选定栈帧,不带参数时显示栈帧简要信息

up

栈帧号

选定栈帧上移

down

栈帧号

选定栈帧下移

info frame

显示栈帧详细信息

info agrs

显示当前选定栈帧的函数参数

info locals

显示当前选定栈帧中的所有局部变量

set variable expr

赋值表达式

给变量赋值或者修改变量的值

print

赋值表达式

给变量赋值或者修改变量的值

jump

使程序从另外的地址开始执行

signal sig

信号值或者信号和名称

向被调试程序发送信号

call expr

包含函数调用的表达式

调用函数

print expr

包含函数调用的表达式

调用函数

list

函数名 行号 地址 偏移等

列出程序源码

set listsize count

设置 list默认显示的行数

disassemble

反汇编被调试程序

set disassembly-flavor instruction-set

设置反汇编格式

实验楼实验五

要求

使用gcc –S –o main.s main.c -m32
命令编译成汇编代码,如下代码中的数字和函数名请自行修改以防与他人雷同

int g(int x) {   return x + 3; }  int f(int x) {   return g(x); int main(void) {   return f(8) + 1; }

1.删除gcc产生代码中以"."开头的编译器指令,针对每条指令画出相应栈帧的情况
2.(选做)使用gdb的bt/frame/up/down 指令动态查看调用栈帧的情况

实验结果

2.

参考资料:

http://blog.csdn.net/21cnbao/article/details/7385161

http://blog.csdn.net/nabila/article/details/7786428

Linux(10.5-10.11)学习笔记的更多相关文章

  1. linux内核分析第四周学习笔记

    linux内核分析第四周学习笔记 标签(空格分隔): 20135328陈都 陈都 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.co ...

  2. C++11 学习笔记 std::function和bind绑定器

    C++11 学习笔记 std::function和bind绑定器 一.std::function C++中的可调用对象虽然具有比较统一操作形式(除了类成员指针之外,都是后面加括号进行调用),但定义方法 ...

  3. Linux内核分析第二周学习笔记

    linux内核分析第二周学习笔记 标签(空格分隔): 20135328陈都 陈都 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.co ...

  4. linux内核分析第一周学习笔记

    linux内核分析第一周学习笔记 标签(空格分隔): 20135328陈都 陈都 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.co ...

  5. Linux就该这么学11学习笔记

    参考链接:https://i.cnblogs.com/EditPosts.aspx?opt=1 文件传输协议 一般来讲,人们将计算机联网的首要目的就是获取资料,而文件传输是一种非常重要的获取资料的方式 ...

  6. zepto源码--核心方法10(位置)--学习笔记

    今天基本上就是zepto学习笔记的最后一篇了,介绍一下有关位置的函数,position, offset, scrollLeft, scrollTop scrollLeft 如果所选取的包装集不存在,则 ...

  7. Linux简易APR内存池学习笔记(带源码和实例)

    先给个内存池的实现代码,里面带有个应用小例子和画的流程图,方便了解运行原理,代码 GCC 编译可用.可以自己上网下APR源码,参考代码下载链接: http://pan.baidu.com/s/1hq6 ...

  8. C++11学习笔记

    C++11 1.long long新类型 2.列表初始化 int t=0; int t={0}; int t(0); int t{0}; 注意:如果我们使用列表初始化有丢失信息的风险,则编译器报错 l ...

  9. linux下文件搜索命令学习笔记

    1. locate:按照文件名搜索文件 locate filename 与find在整个操作系统中遍历搜索不同,locate命令在/var/lib/mlocate这个后台数据库中按照文件名搜索,所以优 ...

  10. Linux文件与目录管理(学习笔记)

    本笔记为<鸟哥linux私房菜>第六章学习笔记 一.目录与路径 相对路径与绝对路径 绝对路径:一定由根目录 / 写起              正确度比较好 相对路径:不是由 / 写起  ...

随机推荐

  1. 深入理解CSS中的层叠上下文和层叠顺序

    零.世间的道理都是想通的 在这个世界上,凡事都有个先后顺序,凡物都有个论资排辈.比方说食堂排队打饭,对吧,讲求先到先得,总不可能一拥而上.再比如说话语权,老婆的话永远是对的,领导的话永远是对的. 在C ...

  2. Atitit.一个cms有多少少扩展点,多少api wordpress  cms有多少api。。扩展点

    Atitit.一个cms有多少少扩展点,多少api wordpress  cms有多少api..扩展点 1. Api分类 WordPress APIs1 1.1. 1 函数分类2 1.2. 函数api ...

  3. SoapUI接口测试实例(webservice接口)

    接口测试步骤 注:以测试queryHistoryAccepts接口作举例. 1. 用户登录获取SessionKey实体信息 注:由于大部分的接口都需要SessionKey实体的信息,因此测试那些接口都 ...

  4. JavaScript Patterns 4.2 Callback Pattern

    function writeCode(callback) { // do something... callback(); // ... } function introduceBugs() { // ...

  5. C# 图片处理(压缩、剪裁,转换,优化)

    1.图片与二进制的转换 图片转换成二进制主要用于数据库存储及图片数据的应用间传输,如网站服务器通过WebService或WCF从数据处理服务器获取图片数据,就可以以二进制形式传输 ///图片转二进制 ...

  6. Python开发之【简单计算器】

    开发一个简单的python计算器 1.实现加减乘除及括号优先级解析 2.用户输入 1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * ...

  7. Hive query issue

    One time, I have written a query with two tables join, One table is big table with partitions , anot ...

  8. java读取word内容

    暂时只写读取word内容的方法. 依赖的jar: poi-3.9-20121203.jarpoi-ooxml-3.9-20121203.jarxmlbeans-2.3.0.jar package co ...

  9. selenium如何操作cookies实现免登录

    执行接口测试或者某些自动化测试时,为了避免每次访问接口都需要登录操作,可以用访问接口时,把cookies信息传过去. 思路是先登录一次页面,获取到cookies信息,把cookies信息保存到本地文件 ...

  10. 【温故而知新-Javascript】图片效果(图像震动效果、闪烁效果、自动切换图像)

    1.当鼠标指针经过图像时图像震动效果 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" " ...