第1讲 实验环境.

Slides:



Advertisements
Similar presentations
Linux管理与应用 Linux 诞生历史 主讲教师:张美平. 主要内容 Linux诞生的几个要素及背景 GNU项目 Linux系统诞生与发展过程.
Advertisements

Linux 安裝入門與基本管理 課程目標: 學習Linux平台下的安裝設定 與 建置一個基本的Linux伺服器
2015退伍士兵焊工专业 第一学期 课程名称:计算机基础(一).
基础模块 模块一 程序设计基础 (一)开发环境部分.
上課教材 Database Slide Windows筆電 (32 bit)
ARM 嵌入式系统 第七章 嵌入式Linux.
培养目标 1.建立基本的程序设计概念体系,掌握基础程序设计方法。
第1单元 操作系统概论 第一节 绪论 操作系统定义.
操作系统 袁昕.
命令行操作 shell介绍 常见三种Shell ---Bourne shell(sh) ---C shell(csh)
Linux 的历史、现状和未来 2011 《网管员世界》杂志社 副总编辑 孙浩峰.
第七章 操作系统接口 7.1 联机用户接口 7.2 Shell命令语言 7.3 系统调用 7.4 UNIX系统调用 7.5 图形用户接口.
技术支持部 张新凤( ) 并行机群系统安装、使用和管理 技术支持部 张新凤( )
计算机体系结构 应用程序 软件 操作系统 编译器 固件 指令集 输入输出 CPU 硬件 内存 (I/O) 集成电路 元件,逻辑门.
第六章 Linux的系統管理基礎 課前指引 身為Linux系統管理員,除了熟悉作業系統的安裝、圖形介面的操作及系統指令的使用與軟體套件的安裝外,更需要瞭解基礎的Linux系統管理技巧。本節,將針對此部分進行說明。
靜宜大學專用 PowerPoint 檔案 數位教材
嵌入式系统讲义 第5章 嵌入式系统软件开发环境与工具
LINUX 环境下程序开发基础 曙光用户培训课程系列 课程时间:1.5小时 更新日期:2008年3月.
第六章 ADS集成开发环境的使用.
資訊安全與系統管理 2013/3/13 Chien wei lin.
基于操作系统的编程复习 张玉宏
UNIX系統與資料庫安裝 Why UNIX 常用的工具程式介紹 資料庫的安裝.
Linux.
Linux的認識與使用 2013/01/05.
第 2 章 上機使用 Unix/Linux 內容: 操作介面 主機連線 登入主機 認識系統環境 使用者常用命令.
Linux环境下程序编译 曙光信息产业(北京)有限公司.
第4章 作業系統的介紹及操作.
Linux 圖形操作介面 GUI -- X-window 與 Webmin
Linux 系統管理 計網中心網路組 楊世偉.
Linux 的一些事儿 系统管理 宁波市高校慕课联盟课程
編譯環境介紹.
张吉豫 GNU编译工具链使用简介 张吉豫
Linux 基础与常用命令简介 生物信息学培训班 杭州,2018年1月18日 周银聪.
Linux环境高级编程实验.
编译与多文件.
第六章 运行时存储空间的组织和管理 术语 本章内容 讨论一个活动记录中的数据布局 程序执行过程中,所有活动记录的组织方式 过程的活动
第二天 计算机基础技能培训 (一)linux基础知识
什么是C语言 编写HelloWorld程序 注释
第2章 Linux概述 2.1 操作系统的功能和分类 2.2 Linux操作系统概述 2.3 Linux的应用现状与前景
基本的”防”黑客技术 Basic” ” Hacker Technique
網路資源的建立--LINUX系統 國立東華大學電算中心 陳鴻彬.
Linux基本操作 程設實習課 ( 2/25 ).
伺服器探索營 Day 1 指導老師: 張啟中 (JohnAxer) 教學助理:
第 4 章 安裝 Linux 著作權所有 © 旗標出版股份有限公司.
永远的 Autotools ——GNU Build System 简介(一)
操作系统实验 lab1-系统引导
作業系統 (Operating System)
中国科学技术大学计算机系 陈香兰(0512- ) 助教:孟宁 Fall 2009
Linux核心編譯與模組管理 2013/01/19.
第二章 Linux简介 Linux概述 Linux系统的特点 Linux中使用的应用程序 Linux的组成 Linux版本介绍
编辑文本文件 软件包管理 Samba 在Linux下使用Windows共享打印机
2017 Operating Systems 作業系統實習 助教:陳主恩、林欣穎 實驗室:720A Lab3.
利用ICE通信中间件构建分布式应用程序开发框架
第1章 概述 本章要点: C语言程序结构和特点 C语言程序的基本符号与关键字 C语言程序的编辑及运行 学习方法建议:
环境配置及使用.
如何有效率的學習Linux 培養組合能力 多用程式, 少寫程式 從錯誤訊息中學習 養成略讀 “各種文件” 加強英文基本閱讀能力 勤作筆記
2018 Operating Systems 作業系統實習 助教:林欣穎 實驗室:720A Lab3.
C语言环境配置.
杨振伟 清华大学 第一讲:Linux环境下编程(1)
本节内容 字符与字符串 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
实验一:编译运行Linux内核并使用gdb进行调试
第一章 C语言概述 目录 什么是语言、程序 C语言的历史与发展 C语言的书写形式与程序结构 运行C语言的步骤与方法
第12章 Linux與 嵌入式uClinux系統
作業一: 安裝Linux於btrfs上 中正大學 作業系統實驗室 指導教授:羅習五
杨振伟 清华大学 第一讲:Linux环境下编程(1)
嵌入式Linux编程环境.
劉庠宏、林合治編著 國立高雄大學應用數學系 2005年3月1日
课程介绍 1、嵌入式系统开发先序课程; 2、共32+8课时: 3、本期采用混合式教学成绩计算方式:
第六章 文件系统与文件管理 6.4 Linux文件管理 1、比较MS DOS 与 Linux的目录结构 一、Linux文件系统的树形结构
《操作系统设计与实现》 第5章 文件系统.
Presentation transcript:

第1讲 实验环境

实验环境 主要教学目标 实验任务:PA0 了解Linux 学习Linux下的C编程 掌握gdb符号调试器 学习程序维护工具make 了解反汇编的方法 示例与练习 实验任务:PA0

1、了解Linux

Linux的发展 Linux系统主要由内核、Shell、文件系统和实用程序组成。 Linux的诞生最早可以追溯到1991年,当时Linus Torvalds还是芬兰赫尔辛基大学的一名学生。他最初用汇编语言编写了一个在80386保护模式下处理多任务切换的程序。随后,从当时为教学而设计的Minix系统得到灵感,决定完成一个比Minix系统更加强大的类Unix操作系统,因而开始了Linux系统雏形的设计。 1991年10月,Linus Torvalds完成了Linux 0.0.2版,并将源代码发布在了Internet上。随即就引起世界范围内计算机爱好者和开发者的注意,他们通过Internet加入了Linux的内核开发之中。一大批高水平程序员的加入,使得Linux得到迅猛发展。他们为Linux修复错误、增加新功能,不断尽其所能地改进它。 1992年,Linux系统与GNU计划完成的其他组件结合起来,构成了一个完整的操作系统,所以该操作系统也被称为GNU/Linux。 如今,Linux操作系统日益壮大。这一方面得益于其开放源码的措施,通过Internet上成千上万计算机爱好者和开发者的不懈努力,Linux比以往任何时候都更健壮、更稳定、更可靠。另一方面,则得益于众多像Red Hat这样的商业软件公司的介入,弥补了自由软件的不足和发展障碍,也加快了其商品化的步伐,使Linux更多地受到了企业用户的重视。 Linux系统主要由内核、Shell、文件系统和实用程序组成。

Linux内核 内核是OS的核心,即最重要部分。 Linux内核源码完全公开,官方网站:http://www.kernel.org。 任何人只要遵循GPL(GNU General Public License),就可对内核进行修改并发布给他人使用。 内核版本号的格式为:主版本号.次版本号.修正号。 主版本号和次版本号标志着重要的功能变动 修正号表示较小的功能修改,这些修改不会影响内核的稳定性,只是为了修正一些BUG或优化内核的效率等 3.6.4中3代表主版本号,6代表次版本号,4代表修正号 次版本号还有特定的意义:偶数表示是稳定版,具有工业级强度,可以广泛地部署和应用;奇数表示加入了一些测试功能,可能存在BUG。

Linux Shell Shell也称命令行界面,是Unix传统的用户和计算机的交互界面 用户直接输入命令来执行各种各样的任务 Shell虽然不是Linux内核的一部分,但它调用内核功能来执行程序,建立文件,并以并行方式协调各程序的运行 深入理解和掌握Shell的特性和使用,是用好Linux系统的关键 Linux系统也提供了图形用户界面X Window,用户可以使用鼠标方便、直观和快捷地进行操作。目前比较流行的窗口管理器Gnome、KDE以及所有的GUI应用程序都在X Window的基础上建立

Linux文件系统 文件系统是一种存储和组织计算机文件和数据的方法,它使得对其访问和查找变得容易。Linux支持多种文件系统包括:EXT2、EXT3、EXT4、FAT、NTFS、ISO9660等。

Linux应用程序 包括编辑器、过滤器、交互程序等在内的多种应用程序。 编辑器用于文件的编辑,比较流行的有vi和emacs。编辑器是进行程序设计的必备工具。 过滤器用于接收并过滤数据。有多种类型过滤器,输入可以是一个文件,也可以是用户从键盘输入的数据。过滤器之间允许相互连接,即一个过滤器的输出可以是另一个过滤器的输入。 Linux是一个多用户操作系统,它提供了交互程序,允许用户发送信息或接收来自其他用户的信息。

Linux的优势 短短十几年发展迅猛,这是其独具的优势决定的。 成本低:由于Linux系统是基于GPL基础的产物,因此任何人都可以自由地获取Linux,即使购买Linux的发行版本,也只需要少许的费用。另一方面,Linux对硬件配置要求很低,而且支持多种硬件平台,这也是造成它流行的主要原因之一。 开放:Linux系统是一个开放的系统。用户可以在不支付任何费用的前提下获得它的源代码,并且还可以根据自己的需要对它进行修改并自由传播。这为广大的计算机爱好者提供了学习、探索以及修改计算机操作系统内核的机会,对于程序开发工程师来说尤其重要。 稳定性:Unix操作系统的稳定性是众所周知的,Linux继承了Unix核心的设计思想,具有执行效率高、安全性高和稳定性好的特点。 多任务、多用户:Linux是多任务、多用户的操作系统,可以支持多个使用者同时使用和共享系统的处理器、磁盘、外设等系统资源。 网络功能强大:网络是Linux系统的生命,强大的网络功能是Linux系统的一大特点,所以Linux在通信和网络功能方面优于其他操作系统。

2、C语言编译器GCC简介

用GCC进行程序开发 GCC是GNU推出的功能强大、性能优越的多平台编译器,其执行效率比一般的编译器平均高20~30% 预处理:调用cpp程序进行预处理,分析包括#include、#define之类的命令 编译:调用ccl程序进行编译,将源代码转换生成汇编语言程序 汇编:调用as程序将汇编语言程序生成扩展名为.o的可重定位目标文件 连接:调用ld程序将目标文件进行连接,最后生成可执行目标文件

例:“hello world”程序的处理过程 经典的“ hello.c ”C-源程序 hello.c的ASCII文本表示 1 #include <stdio.h> 2 3 int main() 4 { 5 printf("hello, world\n"); 6 } # i n c l u d e <sp> < s t d i o . 35 105 110 99 108 117 100 101 32 60 115 116 100 105 111 46 h > \n \n i n t <sp> m a i n ( ) \n { 104 62 10 10 105 110 116 32 109 97 105 110 40 41 10 123 \n <sp> <sp> <sp> <sp> p r i n t f ( " h e l 10 32 32 32 32 112 114 105 110 116 102 40 34 104 101 108 l o , <sp> w o r l d \ n " ) ; \n } 108 111 44 32 119 111 114 108 100 92 110 34 41 59 10 125 程序的功能是: 输出“hello,world” 计算机能够直接识别hello.c源程序吗? 不能,需要转换为机器语言代码! 即:编译、汇编等

GCC使用举例 使用GCC的命令是gcc,最常用的方式如下: #gcc -o filename sample1.c sample2.c sample3.c 使用[-o filename]参数,输出可执行文件名为filename;如果没有这个参数,GCC将使用缺省的可执行文件名a.out

GNU C/C++编译器的选项列表 选项 描述 -x language -c -S (-s) file -E -o file -l library -L directory -I directory -w -pedantic -Wall -g -ggdb -p -pg -o 指定语言(C、C++和汇编为有效值) 只进行编译和汇编(不连接) 编译(不汇编或连接) 只进行预处理(不编译、汇编或连接) 用来指定输出文件名 用来指定所用库 为库文件的搜索指定目录 为include文件的搜索指定目录 禁止警告消息 严格要求符合ANSI标准 显示附加的警告信息 产生排错信息(同gdb一起使用时) 产生排错信息(用于gdb) 产生proff所需的信息 产生groff所需的信息 优化

基本选项 例:对于源程序example.c ,使用如下命令进行预处理 gcc -E example.c -o example.i 说明:该例子使用了两个选项:-E和-o,其中-E表示在预处理结束后即停止编译过程;-o指定输出文件。 前面的选项不同,输出的文件类型也不相同,例如: -E为预处理后的文件(*.i) -S为汇编语言目标代码(*.s)

基本选项—预处理阶段 忽略掉不需预处理的输入文件,生成中间文件*.i C预处理器cpp用来完成宏的求值、条件编译以及其他一些需要把代码传递到编译器前的工作 通常所见的那些“#”号后面的语句由 cpp 来进行处理,如#ifdef、#include以及#define等 例:下面一段代码: #define FOO (5*2) … printf("%d\n",FOO*2); 经过cpp预处理后变成下面形式: printf("%d\n",(5*2)*2);

基本选项—编译阶段 输入中间文件*.i,生成汇编语言源程序文件*.s 对应的GCC命令如下例所示: gcc -S example.i -o example.s example.s即为生成的汇编语言源程序文件 该例其实可以直接从源代码编译,这时应该使用小写的s,即: gcc –s example.c -o example.s

编译器ccl优化选项 选项 说明 -O0 -O或-O1 -O2 -O3 -Os GCC具有优化代码的功能,它的优化功能也有多种不同的选项,主要的优化选项如表所示 选项 说明 -O0 不进行优化处理 -O或-O1 进行基本的优化,这些优化在大多数情况下都会使程序执行得更快 -O2 除了完成-O1级别的优化外,还要一些额外的调整工作,如处理器指令调度等,这是GNU发布软件的默认优化级别 -O3 除了完成-O2级别的优化外,还进行循环的展开以及其它一些与处理器特性相关的优化工作 -Os 生成最小的可执行文件,主要用在嵌入式领域

编译优化选项的选择 一般来讲,优化级别越高,生成的可执行文件的运行速度也越快,但消耗在编译上的时间就越长,因此在开发的时候最好不要使用优化选项,只有到软件发行或开发结束的时候,才考虑对最终生成的代码进行优化 推荐使用-O2选项,因为它在优化长度、编译时间和代码大小之间,取得了一个比较理想的平衡点,它是最安全的优化选项 对于桌面应用,可以尝试-O3选项,在优化时对循环进行了展开,这会使可执行文件增大,速度是否增加取决于特定环境。其实他们之间的速度差异也并不是很明显 -O2选项已经启用绝大多数安全的优化选项,-O3选项是在-O2选项的基础上又增添了一些,其实用户也可以根据需要,在-O2选项的基础自行添加,这样比直接使用-O3选项更加安全。例如增添如下选项: -finline-functions:允许编译器将一些简单的函数在其调用处展开 -funswitch-loops:将循环体中值不改变的变量移到循环体之外 具体的命令格式举例: gcc -O2 -finline-functions example.c -o example

实例:查看GCC优化选项的效果 首先不加任何优化选项,对上面的源程序进行编译: gcc example.c -o example 使用Linux系统下的time命令来大致统计程序的运行时间: time ./example time命令的输出结果由三部分组成: real:程序的总执行时间,包括进程的调度、切换等时间; user:用户进程执行的时间; sys:内核执行的时间。 接下来使用优化选项-O2对上面的源程序进行处理: gcc -O2 example.c -o example 再次统计程序的运行时间,可以看到程序的性能得到大幅度的改善 此外,还有一个比较重要的优化选项-march,它表示为特定的CPU类型编译二进制代码,进而取得最佳的优化效果。具体的命令格式为: gcc --march=<CPU类型> example.c -o example CPU类型如pentium4、pentium4m、pentium-m或athlon64等。

基本选项—汇编阶段 将输入的汇编语言源程序文件转换为可重定位目标代码文件(*.o),这可以通过使用-c选项完成,实际调用了汇编器as 对应的GCC命令如下例所示: gcc -c example.s -o example.o 注意:目标文件虽然是机器代码,但不可执行。 as 通常情况下是被gcc调用的,但也可直接使用。

基本选项—链接阶段 将生成的目标文件与其它目标文件(或库文件)链接成可执行的二进制代码文件。这一步骤可以使用如下的GCC命令来完成: gcc example.o -o example 运行example 如果只需要最终的可执行文件,可以直接对源文件进行编译链接,对应的GCC命令如下所示: gcc example.c -o example 对于一个程序的多个源文件进行编译链接时,可以使用如下格式: gcc -o test first.c second.c third.c 该命令将同时编译三个源文件,即first.c、second.c和third.c,然后将它们链接成一个可执行文件,名为test。 注意:生成可执行文件时,被编译和链接的多个源文件中有且只能有一个main函数,因为main函数是该程序的入口

链接器 ld 在编写一个较大程序时,经常把它分成许多独立的模块,这时需要链接器把所有的模块组合起来,并结合 C 函数库和初始化代码,产生最后的可执行文件。链接器在产生可执行文件之前,起到重要的作用。 通常情况下,ld被编译器所调用,产生可执行文件,但是,如果想更好地控制链接过程,最好手工调用ld。

链接器使用实例 使用GCC直接指定在创建可执行文件时所需包含的库文件 gcc example5.c -o example /usr/lib/i386-linux-gnu/libm.so 快捷选项-l,命令的格式为: gcc example5.c -o example5 -lm 与上面指定库文件的全路径/usr/lib/libm.so命令等价,避免了在命令行写长路径 在Linux下,库文件在命名时总以lib开头,因此在用-l选项指定库文件名时可省去lib,-lm表示链接名为libm.so的库文件 GCC编译器在默认情况下使用动态库,但如果使用了-static选项,则忽略动态库,强制使用静态链接库,即使用如下命令: gcc example5.c -o example5 -static -lm 此时静态库文件中的代码全部包含到可执行文件中,故生成的可执行文件较大 GCC编译器提供了-shared选项来生成动态库文件 与动态库链接的可执行文件只包含它需要的函数的引用表,而不是所有的函数代码,且只有在程序执行时函数代码才会被拷贝到内存之中。这样使可执行文件比较小,进而节省了磁盘空间;更重要的是,如果库文件本身被更新了,不需要重新编译与它连接的源程序。

3、gdb符号调试器

gdb符号调试器 gdb(GNU Debugger)是由GNU计划完成的、受通用公共许可证(GPL)保护的自由软件。它主要工作在字符模式下,是一个功能强大的交互式程序调试工具 gdb能在程序运行时观察程序的内部结构和内存的使用情况 gdb主要提供以下功能 监视程序中变量的值的变化 设置断点,使程序在指定的代码行上暂停执行,便于观察 单步执行代码 分析崩溃程序产生的core文件 命令形式如下:gdb filename

gdb调试—执行程序 gdb命令run(可以简写为r)执行装载代码在run命令之后可以加入执行参数来定制执行的方式 (gdb) r 如果程序中存在断点,则会在断点处自动暂停

gdb调试—设置断点 通过使用gdb逐步调试代码,可以看到程序内部是如何运行的,还可以知道什么命令正在执行,变量的值的变化以及其他一些细节问题 gdb调试示例——针对源程序test.c: 1. 调用gdb,装载子程序 $gdb test ( 若要在GDB启动后载入,则使用file命令:(gdb) file test )

gdb调试—设置断点 2、设置断点 可以通过使用break命令(可简写为b)指定一个特定的位置设置断点。指定一个特定的位置设置断点,当程序运行到这个位置时就被中断,然后把程序的控制权交给调试器和程序员 设置断点的最简单形式——在break命令后加入行号来在该行加入断点 (gdb)break test.c:21 Breakpoint 1 at 0x12000061c:file test,line 21 另一种方法 (gdb)break printmessage Breakpoint 1 at 0x120000848:file test.c,line 48

gdb调试—使用断点 在断点后继续运行程序,可使用continue命令(简写为c) (gdb) c break命令后也可以跟函数名,使程序在进入指定的函数之前停下来 设置断点时也可以进行条件判断,即只有条件为真,程序到达指定行或函数时才停下来 (gdb) b 9 if i>9 在加入断点之后,可通过info break命令来查看设置断点的信息,包括编号、类型、地址等 (gdb) info break

gdb调试—使用断点 可以通过delete(可以简写为d)命令来删除断点 也可以使用clear来删除指定代码行上的断点 (gdb) clear 9 《--删除第9行上的所有断点 clear命令后面可以跟一个范围 可以使用disable命令使某个断点暂时失效。disable命令可加断点号来禁用指定断点,否则会将所有断点禁用 断点在禁用之后可以用enable命令来恢复使用

gdb调试—列出源代码 程序在载入到gdb之后,就可以通过list命令(可简写为l)来查看源代码信息。 (gdb) list list命令默认情况下只列出10行代码。如果上面命令的基础上再次输入list命令,会接着列出后面的10行代码,当然,如果后面还有10行的话,否则只列到源文件末尾 也可以通过参数来指定list命令列出源文件的某一部分。例如:列出源文件example1.c的第3~5行代码 (gdb) l 3,5 list命令后也可直接跟行号,这样列出的是该行上下5行代码 (gdb) l 9

gdb调试—显示数据 使用print和display display和print 是显示数据最常用的两种命令,这两个命令的功能非常强大,并不限于简单地显示一个整数值 使用printf 该命令可以接受指定格式和变量列表为参数,使用起来类似于 C 中的 printf()函数 内存检查命令 gdb提供了命令x,来获得指针所指向的内容。 x/format address

gdb调试—设置观察点(窗口) 观察点也称为数据断点,用来监测某个变量或表达式的值是否有变化,如果有变化,则暂停程序的运行,这在调试程序的过程中是非常有用 设置观察点的命令为watch,后面跟需要查看的变量或表达式 (gdb) watch tol 设置变量tol的观察点 若程序继续运行,则可以看到GDB给出了变量tol的旧值0和新值1,同时也给出了下一条指令的行号和指令内容

gdb调试—查看栈信息 当程序调用了一个函数时,函数的地址、函数参数、函数内的局部变量都会被压入“栈”(Stack)中。可以用backtrace(简写为bt)来查看当前的栈中的信息。 如果要查看某一层的信息,需要切换当前的栈。程序停止时,最顶层的栈就是当前栈,如果要查看栈下面层的详细信息,首先要做的是切换当前栈,可使用frame (简写为f)命令,后面跟栈帧的编号 (gdb) f 1 查看当前栈帧的详细信息,可使用info frame命令(简写为info f) (gdb) info f 将显示调用函数的地址、被调用函数的地址、函数的编写语言、函数的参数、局部变量的地址、栈的层编号、当前的函数名、函数所在文件及行号、函数执行到的语句等信息。

gdb调试—程序执行控制 单步执行 即一步一步跟踪程序执行,是经常使用的一种调试操作 GDB中可以通过step(简写为s)或next(简写为n)来单步执行代码 step命令可以跟踪进入函数内部,在执行到函数调用部分时,GDB会给出提示信息,包括被调用函数的入口参数、起始行号等,同时也会给出函数中将要执行的语句及所在行的行号 next命令也可以实现程序代码的单步执行,但它将函数调用看作是一条语句,不跟踪进入函数内部 next命令后面还可以跟参数来指定执行操作的次数,直至程序因其他原因暂停运行

gdb调试—程序执行控制 return命令 执行到指定行 命令until加指定行号 需要注意的是如果执行中有断点则会停在断点处 finish命令 在退出当前函数前执行函数体 jump命令 跳过某一段代码继续执行,从而改变程序执行的顺序。命令后跟运行转到的行号。 jump不会改变程序栈的内容,所以当从一个函数跳到另一个函数后,函数返回所进行的出栈操作必定会发生错误,程序运行结果也可能非常奇怪,所以最好是在同一个函数内进行跳转

gdb调试—查看信息 查看寄存器信息:info registers命令 (gdb) info registers 查看单个寄存器:在print命令后加上寄存器名称(前加“$”符号) (gdb) p $eip 查看程序的汇编代码:disassemble命令 (gdb) disassemble printinfo 显示函数printinfo的汇编代码

4、程序维护工具make

程序维护工具make makefile文件主要包含5部分内容: 可执行文件和各程序文件的相互依赖关系被记录在一个指定的文件中,通常称为make文件(默认名称是GNUmakefile、makefile或者Makefile,也可以是任意一个文件 默认情况下,make命令会在当前目录下按顺序查找文件名为“GNUmakefile文件”、“Makefile文件”和“makefile文件”的文件,找到后解释这些文件 若makefile文件出现问题,则可查看当前环境中有没有定义这个变量 makefile文件主要包含5部分内容: 显式规则 隐式规则 变量定义 文件指示 注释

makefile文件简介 GNU的make命令工作时的执行步骤如下: (1) 读入所有的makefile文件。 (2) 读入被include包括的其他makefile文件。 (3) 初始化文件中的变量。 (4) 推导隐式规则,并分析所有规则。 (5) 为所有的目标文件创建依赖关系链。 (6) 根据依赖关系,决定哪些目标要重新生成。 (7) 执行生成命令。

Make命令语法规则 通过使用编辑软件(如vi、Emacs等)生成make文件,然后使用make命令,就可以对程序实现自动、高效的维护工作 make[-f make文件名][其他选项][目标名] 其中,-f之处描述依赖关系的文件名,如果使用的是默认名称中的一个文件名(GNUmakefile、makefile或者Makefile),就不需要这个选项;当使用其他名称时,则要在使用make命令时,加入-f可选项,一般情况下都使用Makefile

规则举例 foo.o: foo.c defs.h # foo模块 gcc -c -g foo.c 这个规则需要说明两点 文件的依赖关系:foo.o依赖于foo.c和defs.h文件,如果foo.c和defs.h文件的日期比foo.o文件的日期新,或者foo.o不存在,则发生依赖关系。 如果生成(或更新)foo.o文件,要用到gcc命令

5、汇编与反汇编

反汇编 两个源程序文件test1.c和test2.c,最终生成可执行文件为test gcc -O1 test1.c test2.c -o test 选项-O1表示一级优化,-O2为二级优化,选项-o指出输出文件名 目标文件可用“objdump -d test.o” 反汇编为汇编语言程序 00000000 <add>: 0: 55 push %ebp 1: 89 e5 mov %esp, %ebp 3: 83 ec 10 sub $0x10, %esp 6: 8b 45 0c mov 0xc(%ebp), %eax 9: 8b 55 08 mov 0x8(%ebp), %edx c: 8d 04 02 lea (%edx,%eax,1), %eax f: 89 45 fc mov %eax, -0x4(%ebp) 12: 8b 45 fc mov -0x4(%ebp), %eax 15: c9 leave 16: c3 ret gcc -E test.c -o test.i gcc -S test.i -o test.s 位移量 机器指令 汇编指令 test.s gcc –S test.c –o test.s add: pushl %ebp movl %esp, %ebp subl $16, %esp movl 12(%ebp), %eax movl 8(%ebp), %edx leal (%edx, %eax), %eax movl %eax, -4(%ebp) movl -4(%ebp), %eax leave ret 编译得到的与反汇编得到的汇编指令形式稍有差异

两种目标文件 test.o:可重定位目标文件 test:可执行目标文件 “objdump -d test” 结果 “objdump -d test.o”结果 00000000 <add>: 0: 55 push %ebp 1: 89 e5 mov %esp, %ebp 3: 83 ec 10 sub $0x10, %esp 6: 8b 45 0c mov 0xc(%ebp), %eax 9: 8b 55 08 mov 0x8(%ebp), %edx c: 8d 04 02 lea (%edx,%eax,1), %eax f: 89 45 fc mov %eax, -0x4(%ebp) 12: 8b 45 fc mov -0x4(%ebp), %eax 15: c9 leave 16: c3 ret 080483d4 <add>: 80483d4: 55 push ... 80483d5: 89 e5 … 80483d7: 83 ec 10 … 80483da: 8b 45 0c … 80483dd: 8b 55 08 … 80483e0: 8d 04 02 … 80483e3: 89 45 fc … 80483e6: 8b 45 fc … 80483e9: c9 … 80483ea: c3 ret test.o中的代码从地址0开始,test中的代码从80483d4开始!

6、举例与练习

例:“hello world”程序的处理过程 经典的“ hello.c ”C-源程序 hello.c的ASCII文本表示 1 #include <stdio.h> 2 3 int main() 4 { 5 printf("hello, world\n"); 6 } # i n c l u d e <sp> < s t d i o . 35 105 110 99 108 117 100 101 32 60 115 116 100 105 111 46 h > \n \n i n t <sp> m a i n ( ) \n { 104 62 10 10 105 110 116 32 109 97 105 110 40 41 10 123 \n <sp> <sp> <sp> <sp> p r i n t f ( " h e l 10 32 32 32 32 112 114 105 110 116 102 40 34 104 101 108 l o , <sp> w o r l d \ n " ) ; \n } 108 111 44 32 119 111 114 108 100 92 110 34 41 59 10 125 程序的功能是: 输出“hello,world” 计算机能够直接识别hello.c源程序吗? 不能,需要转换为机器语言代码! 即:编译、汇编等

Hello程序的数据流动过程 Unix>./hello hello, world unix> [Enter] Red:shell命令行处理 Blue:可执行文件加载 Cyan:hello程序执行过程 “hello” “hello,world/n” Hello程序被启动后,计算机的动作过程如下: Shell程序读取字符串“./hello”中各字符到寄存器,然后存放到主存; “Enter”键输入后,操作系统内核(载入程序)根据主存中的字符串“hello”到磁盘上找到特定的hello目标文件,将其包含的指令代码和数据(“hello, world\n”)从磁盘读到主存,并将控制权转交给hello程序,即将hello程序的第一条指令的地址送到PC中;处理器从hello主程序的指令代码开始执行;Hello程序将“hello, world\n”串中的字节从主存读到寄存器,再从寄存器输出到显示器上。 “hello” “hello,world/n” Hello可执行文件 数据经常在各存储部件间传送。故现代计算机大多采用“缓存”技术! 所有过程都是在CPU执行指令所产生的控制信号的作用下进行的。

练习:Linux下编写排序与求和算法 Homework0 1、使用gcc直接编译为执行文件: gcc -o main main.c bubblesort.c add.c printresult.c 2、使用gcc –c main.c语句为所有.c文件编译.o目标文件,可以用-o命令命名输 出目标文件。 3、用ld指令链接目标文件: ld -o main main.o bubblesort.o add.o printresult.o (注:ld链接时要包含很多系统库,可以用gcc –v main.c来查看系统链接需要哪些库) 4、反汇编:使用objdump指令进行反汇编 objdump –S main.o 5、调试:使用gdb命令调试,调试之前首先用gcc –g命令来生成调试信息,否则调试失败 gcc -g -o main main.c bubblesort.c add.c printresult.c gdb main 6、用info registers查看寄存器内容

计算机系统基础实验 ( PA0 ) 配置Linux实验环境

安装并配置虚拟机 本课程实验均在Linux 环境下进行。为方便在Windows系统上使用,推荐安装VirtualBox虚拟机软件,在其中的虚拟机上安装并使用Linux环境。 请从https://www.virtualbox.org/的“Downloads”区的“VirtualBox older builds”中下载VirtualBox 4.3.12版本软件 最新的VirtualBox 4.3.14版本有问题 其他虚拟机软件(如VMware)也可使用,请自行阅读相关安装、设置资料——后面内容以VirtualBox为准。

创建Linux虚拟机 在安装好的VirtualBox软件中新建一个Linux虚拟机 名称任选 类型选“Linux” 版本选“Debian (32 bit)” 内存设为“384MB”或以上 创建虚拟硬盘(默认8GB) 虚拟硬盘文件类型选“VDI”、动态分配

配置Linux虚拟机 在VirtualBox中选择新建的Linux虚拟机,配置右侧的不同栏目参数: 系统 >处理器:选中“启用PAE/NX” 系统 >硬件加速:如你的机器支持(未禁用),可选中其中选项,以提高虚拟机效率 网络>网卡1>高级:去除“接入网线”选中状态,以便安装Linux过程中跳过耗时的在线下载软件包(记得在完成安装后重新选中)

安装Linux虚拟机 为Linux虚拟机装载Linux安装光盘: 存储>存储树:选中“控制器:IDE”栏下的“没有盘片” 点击右侧光盘图标,在弹出菜单中选择“选择一个虚拟光盘” 选择下载的Linux安装光盘ISO镜像文件: debian-7.6.0-i386-netinst.iso

安装Linux虚拟机 启动虚拟机,将会看到Debian的初始安装界面 选择“Graphical Install”和“English”作为安装界面语言

United States: en_US:UTF-8 安装Linux虚拟机 选择Location为:Other>Asia>China 选择Locales(代表包含时间、货币、文字等一系列本地化属性的参数集合)为: United States: en_US:UTF-8 选择keyboard为“American English”

安装Linux虚拟机 设置网络主机名、域名、root口令、普通用户名及其口令 (虚拟)硬盘分区 选择“Guided - use entire disk” 选择“All files in one partition” Linux安装至少需要两个分 区:根分区(存放根文件系 统)和交换分区(用于运行 时内存交换swap) 根文件系统中的目录(如 home、usr、var、tmp) 也可分别放到不同分区(出 于管理的灵活性) 完成后,选择“Finish partitioning and write changes to disk”和“Write the changes to disks - Yes”

安装Linux虚拟机 选择package manager > mirror > China及其中任一Debian发行镜像站点,如 mirrors.163.com 选择安装软件集合:Standard system utilities 选择安装GRUB启动装载器(boot loader),缺省安装至虚拟硬盘的主引导区Master Boot Record (MBR) 结束安装,重启

使用Linux虚拟机 启动Linux虚拟机,在命令行登录界面输入安装时设置的用户名和口令,进入shell cd, ls, rm, mkdir:文件、目录操作命令 cat, more, less:查看文件内容(输出至屏幕或其它重定向目标设备) df:查看空闲的硬盘分区(已挂载文件系统)空间 su:切换至其它用户,如无参数切换至root vi:功能强大的文本编辑器 关闭Linux系统 以root权限执行“poweroff”、“shutdown -h now”、“reboot”(重启)等命令之一

使用Linux虚拟机 Debian软件包管理系统——APT APT软件包发布源:包含有大量Debian软件包的网络站点 配置文件:/etc/apt/sources.list,列出源站点域名及相应目录、软件包类别 deb http://mirrors.163.com/debian/ wheezy main contrib non-free deb http://ftp.cn.debian.org/debian/ wheezy main contrib non-free 安装软件包——aptitute/apt-get命令 不带参数调用将打开全屏软件包管理界面 + install <软件包名>:安装相应软件包 例如: aptitute install sudo

使用Linux虚拟机 sudo命令:允许在当前普通用户的命令行环境中以其它用户(特别是root)身份及其权限执行指定的命令 配置文件:/etc/sudoers,列出允许使用sudo的用户及允许其执行的命令集合 优点:不必使用su命令切换至相应用户的环境即可以其身份执行命令。方便了系统管理(不必切换至该用户)。 例如:sudo shutdown -h now ssh命令:secure shell客户端软件 配合ssh-server软件包实现安全的远程Linux主机访问 相对于类似功能但不够安全的telnet

使用Linux虚拟机 安装实验所需编程环境的相关软件包 build-essential:包含gcc, make, ld等binary utilities gdb:交互式程序调试工具 vim:文本/源代码编辑器 git:源代码版本控制工具(实验代码提交要求同时带上git记录)