软件调试(硬件基础)_第1页
软件调试(硬件基础)_第2页
软件调试(硬件基础)_第3页
软件调试(硬件基础)_第4页
软件调试(硬件基础)_第5页
已阅读5页,还剩549页未读, 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

软件调试(第2版)卷1硬件基础TOC\h目录\h第一篇绪论\h第1章软件调试基础\h1.1简介\h1.1.1定义\h1.1.2基本过程\h1.2基本特征\h1.2.1难度大\h1.2.2难以估计完成时间\h1.2.3广泛的关联性\h1.3简要历史\h1.3.1单步执行\h1.3.2断点指令\h1.3.3分支监视\h1.4分类\h1.4.1按调试目标的系统环境分类\h1.4.2按目标代码的执行方式分类\h1.4.3按目标代码的执行模式分类\h1.4.4按软件所处的阶段分类\h1.4.5按调试器与调试目标的相对位置分类\h1.4.6按调试目标的活动性分类\h1.4.7按调试工具分类\h1.5调试技术概览\h1.5.1断点\h1.5.2单步执行\h1.5.3输出调试信息\h1.5.4日志\h1.5.5事件追踪\h1.5.6转储文件\h1.5.7栈回溯\h1.5.8反汇编\h1.5.9观察和修改内存数据\h1.5.10控制被调试进程和线程\h1.6错误与缺欠\h1.6.1内因与表象\h1.6.2谁的bug\h1.6.3bug的生命周期\h1.6.4软件错误的开支曲线\h1.7重要性\h1.7.1调试与编码的关系\h1.7.2调试与测试的关系\h1.7.3调试与逆向工程的关系\h1.7.4学习调试技术的意义\h1.7.5调试技术尚未得到应有的重视\h1.8本章小结\h参考资料\h第二篇CPU及其调试设施\h第2章CPU基础\h2.1指令和指令集\h2.1.1基本特征\h2.1.2寻址方式\h2.1.3指令的执行过程\h2.2英特尔架构处理器\h2.2.180386处理器\h2.2.280486处理器\h2.2.3奔腾处理器\h2.2.4P6系列处理器\h2.2.5奔腾4处理器\h2.2.6Core2系列处理器\h2.2.7Nehalem微架构\h2.2.8SandyBridge微架构\h2.2.9IvyBridge微架构\h2.2.10Haswell微架构\h2.2.11Broadwell微架构\h2.2.12Skylake微架构\h2.2.13KabyLake微架构\h2.3CPU的操作模式\h2.4寄存器\h2.4.1通用数据寄存器\h2.4.2标志寄存器\h2.4.3MSR寄存器\h2.4.4控制寄存器\h2.4.5其他寄存器\h2.4.664位模式时的寄存器\h2.5理解保护模式\h2.5.1任务间的保护机制\h2.5.2任务内的保护\h2.5.3特权级\h2.5.4特权指令\h2.6段机制\h2.6.1段描述符\h2.6.2描述符表\h2.6.3段选择子\h2.6.4观察段寄存器\h2.7分页机制\h2.7.132位经典分页\h2.7.2PAE分页\h2.7.3IA-32e分页\h2.7.4大内存页\h2.7.5WinDBG的有关命令\h2.8PC系统概貌\h2.9ARM架构基础\h2.9.1ARM的多重含义\h2.9.2主要版本\h2.9.3操作模式和状态\h2.9.432位架构核心寄存器\h2.9.5协处理器\h2.9.6虚拟内存管理\h2.9.7伪段支持\h2.9.864位ARM架构\h2.10本章小结\h参考资料\h第3章中断和异常\h3.1概念和差异\h3.1.1中断\h3.1.2异常\h3.1.3比较\h3.2异常的分类\h3.2.1错误类异常\h3.2.2陷阱类异常\h3.2.3中止类异常\h3.3异常例析\h3.3.1列表\h3.3.2错误代码\h3.3.3示例\h3.4中断/异常的优先级\h3.5中断/异常处理\h3.5.1实模式\h3.5.2保护模式\h3.5.3IA-32e模式\h3.6ARM架构中的异常机制\h3.7本章小结\h参考资料\h第4章断点和单步执行\h4.1软件断点\h4.1.1INT3\h4.1.2在调试器中设置断点\h4.1.3断点命中\h4.1.4恢复执行\h4.1.5特殊用途\h4.1.6断点API\h4.1.7系统对INT3的优待\h4.1.8观察调试器写入的INT3指令\h4.1.9归纳和提示\h4.2硬件断点\h4.2.1调试寄存器概览\h4.2.2调试地址寄存器\h4.2.3调试控制寄存器\h4.2.4指令断点\h4.2.5调试异常\h4.2.6调试状态寄存器\h4.2.7示例\h4.2.8硬件断点的设置方法\h4.2.9归纳\h4.3陷阱标志\h4.3.1单步执行标志\h4.3.2高级语言的单步执行\h4.3.3任务状态段陷阱标志\h4.3.4按分支单步执行标志\h4.4实模式调试器例析\h4.4.1Debug.exe\h4.4.28086Monitor\h4.4.3关键实现\h4.5反调试示例\h4.6ARM架构的断点支持\h4.6.1断点指令\h4.6.2断点寄存器\h4.6.3监视点寄存器\h4.6.4单步跟踪\h4.7本章小结\h参考资料\h第5章分支记录和性能监视\h5.1分支监视概览\h5.2使用寄存器的分支记录\h5.2.1LBR\h5.2.2LBR栈\h5.2.3示例\h5.2.4在Windows操作系统中的应用\h5.3使用内存的分支记录\h5.3.1DS区\h5.3.2启用DS机制\h5.3.3调试控制寄存器\h5.4DS示例:CpuWhere\h5.4.1驱动程序\h5.4.2应用界面\h5.4.32.0版本\h5.4.4局限性和扩展建议\h5.4.5Linux内核中的BTS驱动\h5.5性能监视\h5.5.1奔腾处理器的性能监视机制\h5.5.2P6处理器的性能监视机制\h5.5.3P4处理器的性能监视\h5.5.4架构性的性能监视机制\h5.5.5酷睿微架构处理器的性能监视机制\h5.5.6资源\h5.6实时指令追踪\h5.6.1工作原理\h5.6.2RTIT数据包\h5.6.3Linux支持\h5.7ARM架构的性能监视设施\h5.7.1PMUv1和PMUv2\h5.7.2PMUv3\h5.7.3示例\h5.7.4CoreSight\h5.8本章小结\h参考资料\h第6章机器检查架构\h6.1奔腾处理器的机器检查机制\h6.2MCA\h6.2.1概览\h6.2.2MCA的全局寄存器\h6.2.3MCA的错误报告寄存器\h6.2.4扩展的机器检查状态寄存器\h6.2.5MCA错误编码\h6.3编写MCA软件\h6.3.1基本算法\h6.3.2示例\h6.3.3在Windows系统中的应用\h6.3.4在Linux系统中的应用\h6.4本章小结\h参考资料\h第7章JTAG调试\h7.1简介\h7.1.1ICE\h7.1.2JTAG\h7.2JTAG原理\h7.2.1边界扫描链路\h7.2.2TAP信号\h7.2.3TAP寄存器\h7.2.4TAP控制器\h7.2.5TAP指令\h7.3JTAG应用\h7.3.1JTAG调试\h7.3.2调试端口\h7.4IA处理器的JTAG支持\h7.4.1P6处理器的JTAG实现\h7.4.2探测模式\h7.4.3ITP接口\h7.4.4XDP端口\h7.4.5ITP-XDP调试仪\h7.4.6直接连接接口\h7.4.7典型应用\h7.5ARM处理器的JTAG支持\h7.5.1ARM调试接口\h7.5.2调试端口\h7.5.3访问端口\h7.5.4被调试器件\h7.5.5调试接插口\h7.5.6硬件调试器\h7.5.7DS-5\h7.6本章小结\h参考资料\h第三篇GPU及其调试设施\h第8章GPU基础\h8.1GPU简史\h8.1.1从显卡说起\h8.1.2硬件加速\h8.1.3可编程和通用化\h8.1.4三轮演进\h8.2设备身份\h8.2.1“喂模式”\h8.2.2内存复制\h8.2.3超时检测和复位\h8.2.4与CPU之并立\h8.3软件接口\h8.3.1设备寄存器\h8.3.2批命令缓冲区\h8.3.3状态模型\h8.4GPU驱动模型\h8.4.1WDDM\h8.4.2DRI和DRM\h8.5编程技术\h8.5.1着色器\h8.5.2Brook和CUDA\h8.5.3OpenCL\h8.6调试设施\h8.6.1输出调试信息\h8.6.2发布断点\h8.6.3其他断点\h8.6.4单步执行\h8.6.5观察程序状态\h8.7本章小结\h参考资料\h第9章NvidiaGPU及其调试设施\h9.1概要\h9.1.1一套微架构\h9.1.2三条产品线\h9.1.3封闭\h9.2微架构\h9.2.1G80(特斯拉1.0微架构)\h9.2.2GT200(特斯拉2.0微架构)\h9.2.3GF100(费米微架构)\h9.2.4GK110(开普勒微架构)\h9.2.5GM107(麦斯威尔微架构)\h9.2.6GP104(帕斯卡微架构)\h9.2.7GV100(伏特微架构)\h9.2.8持续改进\h9.3硬件指令集\h9.3.1SASS\h9.3.2指令格式\h9.3.3谓词执行\h9.3.4计算能力\h9.3.5GT200的指令集\h9.3.6GV100的指令集\h9.4PTX指令集\h9.4.1汇编和反汇编\h9.4.2状态空间\h9.4.3虚拟寄存器\h9.4.4数据类型\h9.4.5指令格式\h9.4.6内嵌汇编\h9.5CUDA\h9.5.1源于Brook\h9.5.2算核\h9.5.3执行配置\h9.5.4内置变量\h9.5.5Warp\h9.5.6显式并行\h9.6异常和陷阱\h9.6.1陷阱指令\h9.6.2陷阱后缀\h9.6.3陷阱处理\h9.7系统调用\h9.7.1vprintf\h9.7.2malloc和free\h9.7.3__assertfail\h9.8断点指令\h9.8.1PTX的断点指令\h9.8.2硬件的断点指令\h9.9Nsight的断点功能\h9.9.1源代码断点\h9.9.2函数断点\h9.9.3根据线程组和线程编号设置条件断点\h9.10数据断点\h9.10.1设置方法\h9.10.2命中\h9.10.3数量限制\h9.10.4设置时机\h9.11调试符号\h9.11.1编译选项\h9.11.2ELF载体\h9.11.3DWARF\h9.12CUDAGDB\h9.12.1通用命令\h9.12.2扩展\h9.12.3局限\h9.13CUDA调试器API\h9.13.1头文件\h9.13.2调试事件\h9.13.3工作原理\h9.14本章小结\h参考资料\h第10章AMDGPU及其调试设施\h10.1演进简史\h10.1.1三个发展阶段\h10.1.2两种产品形态\h10.2Terascale微架构\h10.2.1总体结构\h10.2.2SIMD核心\h10.2.3VLIW\h10.2.4四类指令\h10.3GCN微架构\h10.3.1逻辑结构\h10.3.2CU和波阵\h10.3.3内存层次结构\h10.3.4工作组\h10.3.5多执行引擎\h10.4GCN指令集\h10.4.17种指令类型\h10.4.2指令格式\h10.4.3不再是VLIW指令\h10.4.4指令手册\h10.5编程模型\h10.5.1地幔\h10.5.2HSA\h10.5.3ROCm\h10.5.4StreamSDK和APPSDK\h10.5.5Linux系统的驱动\h10.6异常和陷阱\h10.6.19种异常\h10.6.2启用\h10.6.3陷阱状态寄存器\h10.6.4陷阱处理器基地址\h10.6.5陷阱处理过程\h10.7控制波阵的调试接口\h10.7.15种操作\h10.7.2指定目标\h10.7.3发送接口\h10.7.4限制\h10.8地址监视\h10.8.14种监视模式\h10.8.2数量限制\h10.8.3报告命中\h10.8.4寄存器接口\h10.8.5用户空间接口\h10.9单步调试支持\h10.9.1单步调试模式\h10.9.2控制方法\h10.10根据调试条件实现分支跳转的指令\h10.10.1两个条件标志\h10.10.24条指令\h10.11代码断点\h10.11.1陷阱指令\h10.11.2在GPU调试SDK中的使用\h10.12GPU调试模型和开发套件\h10.12.1组成\h10.12.2进程内调试模型\h10.12.3面向事件的调试接口\h10.13ROCm-GDB\h10.13.1源代码\h10.13.2安装和编译\h10.13.3常用命令\h10.14本章小结\h参考资料\h第11章英特尔GPU及其调试设施\h11.1演进简史\h11.1.1i740\h11.1.2集成显卡\h11.1.3G965\h11.1.4Larabee\h11.1.5GPU\h11.1.6第三轮努力\h11.1.7公开文档\h11.2GEN微架构\h11.2.1总体架构\h11.2.2片区布局\h11.2.3子片布局\h11.2.4EU\h11.2.5经典架构图\h11.3寄存器接口\h11.3.1两大类寄存器\h11.3.2显示功能的寄存器\h11.4命令流和环形缓冲区\h11.4.1命令\h11.4.2环形缓冲区\h11.4.3环形缓冲区寄存器\h11.5逻辑环上下文和执行列表\h11.5.1LRC\h11.5.2执行链表提交端口\h11.5.3理解LRC的提交和执行过程\h11.6GuC和通过GuC提交任务\h11.6.1加载固件和启动GuC\h11.6.2以MMIO方式通信\h11.6.3基于共享内存的命令传递机制\h11.6.4提交工作任务\h11.7媒体流水线\h11.7.1G965的媒体流水线\h11.7.2MFX引擎\h11.7.3状态模型\h11.7.4多种计算方式\h11.8EU指令集\h11.8.1寄存器\h11.8.2寄存器区块\h11.8.3指令语法\h11.8.4VLIW和指令级别并行\h11.9内存管理\h11.9.1GGTT\h11.9.2PPGTT\h11.9.3I915和GMMLIB\h11.10异常\h11.10.1异常类型\h11.10.2系统过程\h11.11断点支持\h11.11.1调试控制位\h11.11.2操作码匹配断点\h11.11.3IP匹配断点\h11.11.4初始断点\h11.12单步执行\h11.13GT调试器\h11.13.1架构\h11.13.2调试事件\h11.13.3符号管理\h11.13.4主要功能\h11.13.5不足\h11.14本章小结\h参考资料\h第12章MaliGPU及其调试设施\h12.1概况\h12.1.1源于挪威\h12.1.2纳入ARM\h12.1.3三代微架构\h12.1.4发货最多的图形处理器\h12.1.5精悍的团队\h12.1.6封闭的技术文档\h12.1.7单元化设计\h12.2Midgard微架构\h12.2.1逻辑结构\h12.2.2三流水线着色器核心\h12.2.3VLIW指令集\h12.3Bifrost微架构\h12.3.1逻辑结构\h12.3.2执行核心\h12.3.3标量指令集和Warp\h12.4Mali图形调试器\h12.4.1双机模式\h12.4.2面向帧调试\h12.5Gator\h12.5.1Gator内核模块(gator.ko)\h12.5.2Gator文件系统(gatorfs)\h12.5.3Gator后台服务(gatord)\h12.5.4Kbase驱动中的gator支持\h12.5.5含义\h12.6Kbase驱动的调试设施\h12.6.1GPU版本报告\h12.6.2编译选项\h12.6.3DebugFS下的虚拟文件\h12.6.4SysFS下的虚拟文件\h12.6.5基于ftrace的追踪设施\h12.6.6Kbase的追踪设施\h12.7其他调试设施\h12.7.1Caiman\h12.7.2devlib\h12.7.3Mali离线编译器\h12.8缺少的调试设施\h12.8.1GPGPU调试器\h12.8.2GPU调试SDK\h12.8.3反汇编器\h12.8.4ISA文档\h12.9本章小结\h参考资料\h第13章PowerVRGPU及其调试设施\h13.1概要\h13.1.1发展简史\h13.1.2两条产品线\h13.1.3基于图块延迟渲染\h13.1.4IntelGMA\h13.1.5开放性\h13.2Rogue微架构\h13.2.1总体结构\h13.2.2USC\h13.2.3ALU流水线\h13.3参考指令集\h13.3.1寄存器\h13.3.2指令组\h13.3.3指令修饰符\h13.3.4指令类型\h13.3.5标量指令\h13.3.6并行模式\h13.4软件模型和微内核\h13.4.1软件模型\h13.4.2微内核的主要功能\h13.4.3优点\h13.4.4存在的问题\h13.5断点支持\h13.5.1bpret指令\h13.5.2数据断点\h13.5.3ISP断点\h13.6离线编译和反汇编\h13.6.1离线编译\h13.6.2反汇编\h13.7PVR-GDB\h13.7.1跟踪调试\h13.7.2寄存器访问\h13.7.3其他功能\h13.7.4全局断点和局限性\h13.8本章小结\h参考资料\h第14章GPU综述\h14.1比较\h14.1.1开放性\h14.1.2工具链\h14.1.3开发者文档\h14.2主要矛盾\h14.2.1专用性和通用性\h14.2.2强硬件和弱软件\h14.3发展趋势\h14.3.1从固定功能单元到通用执行引擎\h14.3.2从向量指令到标量指令\h14.3.3从指令并行到线程并行\h14.4其他GPU\h14.4.1Adreno\h14.4.2VideoCore\h14.4.3图芯GPU\h14.4.4TITMS34010\h14.5学习资料和工具\h14.5.1文档\h14.5.2源代码\h14.5.3工具\h14.6本章小结\h参考资料\h第四篇可调试性\h第15章可调试性概览\h15.1简介\h15.2观止和未雨绸缪\h15.2.1NT3.1的故事\h15.2.2未雨绸缪\h15.3基本原则\h15.3.1最短距离原则\h15.3.2最小范围原则\h15.3.3立刻终止原则\h15.3.4可追溯原则\h15.3.5可控制原则\h15.3.6可重复原则\h15.3.7可观察原则\h15.3.8易辨识原则\h15.3.9低海森伯效应原则\h15.4不可调试代码\h15.4.1系统的异常分发函数\h15.4.2提供调试功能的系统函数\h15.4.3对调试器敏感的函数\h15.4.4反跟踪和调试的程序\h15.4.5时间敏感的代码\h15.4.6应对措施\h15.5可调试性例析\h15.5.1健康性检查和BSOD\h15.5.2可控制性\h15.5.3公开的符号文件\h15.5.4WER\h15.5.5ETW和日志\h15.5.6性能计数器\h15.5.7内置的内核调试引擎\h15.5.8手动触发崩溃\h15.6与安全、商业秘密和性能的关系\h15.6.1可调试性与安全性\h15.6.2可调试性与商业秘密\h15.6.3可调试性与性能\h15.7本章小结\h参考资料\h第16章可调试性的实现\h16.1角色和职责\h16.1.1架构师\h16.1.2程序员\h16.1.3测试人员\h16.1.4产品维护和技术支持工程师\h16.1.5管理者\h16.2可调试架构\h16.2.1日志\h16.2.2输出调试信息\h16.2.3转储\h16.2.4基类\h16.2.5调试模型\h16.3通过栈回溯实现可追溯性\h16.3.1栈回溯的基本原理\h16.3.2利用DbgHelp函数库回溯栈\h16.3.3利用RTL函数回溯栈\h16.4数据的可追溯性\h16.4.1基于数据断点的方法\h16.4.2使用对象封装技术来追踪数据变化\h16.5可观察性的实现\h16.5.1状态查询\h16.5.2WMI\h16.5.3性能计数器\h16.5.4转储\h16.5.5打印或者输出调试信息\h16.5.6日志\h16.6自检和自动报告\h16.6.1BIST\h16.6.2软件自检\h16.6.3自动报告\h16.7本章小结目录\h版权信息\h版权\h内容提要\h历史回眸\h第2版前言\h第1版前言\h资源与支持\h第一篇绪论\h第1章软件调试基础\h1.1简介\h1.1.1定义\h1.1.2基本过程\h1.2基本特征\h1.2.1难度大\h1.2.2难以估计完成时间\h1.2.3广泛的关联性\h1.3简要历史\h1.3.1单步执行\h1.3.2断点指令\h1.3.3分支监视\h1.4分类\h1.4.1按调试目标的系统环境分类\h1.4.2按目标代码的执行方式分类\h1.4.3按目标代码的执行模式分类\h1.4.4按软件所处的阶段分类\h1.4.5按调试器与调试目标的相对位置分类\h1.4.6按调试目标的活动性分类\h1.4.7按调试工具分类\h1.5调试技术概览\h1.5.1断点\h1.5.2单步执行\h1.5.3输出调试信息\h1.5.4日志\h1.5.5事件追踪\h1.5.6转储文件\h1.5.7栈回溯\h1.5.8反汇编\h1.5.9观察和修改内存数据\h1.5.10控制被调试进程和线程\h1.6错误与缺欠\h1.6.1内因与表象\h1.6.2谁的bug\h1.6.3bug的生命周期\h1.6.4软件错误的开支曲线\h1.7重要性\h1.7.1调试与编码的关系\h1.7.2调试与测试的关系\h1.7.3调试与逆向工程的关系\h1.7.4学习调试技术的意义\h1.7.5调试技术尚未得到应有的重视\h1.8本章小结\h参考资料\h第二篇CPU及其调试设施\h第2章CPU基础\h2.1指令和指令集\h2.1.1基本特征\h2.1.2寻址方式\h2.1.3指令的执行过程\h2.2英特尔架构处理器\h2.2.180386处理器\h2.2.280486处理器\h2.2.3奔腾处理器\h2.2.4P6系列处理器\h2.2.5奔腾4处理器\h2.2.6Core2系列处理器\h2.2.7Nehalem微架构\h2.2.8SandyBridge微架构\h2.2.9IvyBridge微架构\h2.2.10Haswell微架构\h2.2.11Broadwell微架构\h2.2.12Skylake微架构\h2.2.13KabyLake微架构\h2.3CPU的操作模式\h2.4寄存器\h2.4.1通用数据寄存器\h2.4.2标志寄存器\h2.4.3MSR寄存器\h2.4.4控制寄存器\h2.4.5其他寄存器\h2.4.664位模式时的寄存器\h2.5理解保护模式\h2.5.1任务间的保护机制\h2.5.2任务内的保护\h2.5.3特权级\h2.5.4特权指令\h2.6段机制\h2.6.1段描述符\h2.6.2描述符表\h2.6.3段选择子\h2.6.4观察段寄存器\h2.7分页机制\h2.7.132位经典分页\h2.7.2PAE分页\h2.7.3IA-32e分页\h2.7.4大内存页\h2.7.5WinDBG的有关命令\h2.8PC系统概貌\h2.9ARM架构基础\h2.9.1ARM的多重含义\h2.9.2主要版本\h2.9.3操作模式和状态\h2.9.432位架构核心寄存器\h2.9.5协处理器\h2.9.6虚拟内存管理\h2.9.7伪段支持\h2.9.864位ARM架构\h2.10本章小结\h参考资料\h第3章中断和异常\h3.1概念和差异\h3.1.1中断\h3.1.2异常\h3.1.3比较\h3.2异常的分类\h3.2.1错误类异常\h3.2.2陷阱类异常\h3.2.3中止类异常\h3.3异常例析\h3.3.1列表\h3.3.2错误代码\h3.3.3示例\h3.4中断/异常的优先级\h3.5中断/异常处理\h3.5.1实模式\h3.5.2保护模式\h3.5.3IA-32e模式\h3.6ARM架构中的异常机制\h3.7本章小结\h参考资料\h第4章断点和单步执行\h4.1软件断点\h4.1.1INT3\h4.1.2在调试器中设置断点\h4.1.3断点命中\h4.1.4恢复执行\h4.1.5特殊用途\h4.1.6断点API\h4.1.7系统对INT3的优待\h4.1.8观察调试器写入的INT3指令\h4.1.9归纳和提示\h4.2硬件断点\h4.2.1调试寄存器概览\h4.2.2调试地址寄存器\h4.2.3调试控制寄存器\h4.2.4指令断点\h4.2.5调试异常\h4.2.6调试状态寄存器\h4.2.7示例\h4.2.8硬件断点的设置方法\h4.2.9归纳\h4.3陷阱标志\h4.3.1单步执行标志\h4.3.2高级语言的单步执行\h4.3.3任务状态段陷阱标志\h4.3.4按分支单步执行标志\h4.4实模式调试器例析\h4.4.1Debug.exe\h4.4.28086Monitor\h4.4.3关键实现\h4.5反调试示例\h4.6ARM架构的断点支持\h4.6.1断点指令\h4.6.2断点寄存器\h4.6.3监视点寄存器\h4.6.4单步跟踪\h4.7本章小结\h参考资料\h第5章分支记录和性能监视\h5.1分支监视概览\h5.2使用寄存器的分支记录\h5.2.1LBR\h5.2.2LBR栈\h5.2.3示例\h5.2.4在Windows操作系统中的应用\h5.3使用内存的分支记录\h5.3.1DS区\h5.3.2启用DS机制\h5.3.3调试控制寄存器\h5.4DS示例:CpuWhere\h5.4.1驱动程序\h5.4.2应用界面\h5.4.32.0版本\h5.4.4局限性和扩展建议\h5.4.5Linux内核中的BTS驱动\h5.5性能监视\h5.5.1奔腾处理器的性能监视机制\h5.5.2P6处理器的性能监视机制\h5.5.3P4处理器的性能监视\h5.5.4架构性的性能监视机制\h5.5.5酷睿微架构处理器的性能监视机制\h5.5.6资源\h5.6实时指令追踪\h5.6.1工作原理\h5.6.2RTIT数据包\h5.6.3Linux支持\h5.7ARM架构的性能监视设施\h5.7.1PMUv1和PMUv2\h5.7.2PMUv3\h5.7.3示例\h5.7.4CoreSight\h5.8本章小结\h参考资料\h第6章机器检查架构\h6.1奔腾处理器的机器检查机制\h6.2MCA\h6.2.1概览\h6.2.2MCA的全局寄存器\h6.2.3MCA的错误报告寄存器\h6.2.4扩展的机器检查状态寄存器\h6.2.5MCA错误编码\h6.3编写MCA软件\h6.3.1基本算法\h6.3.2示例\h6.3.3在Windows系统中的应用\h6.3.4在Linux系统中的应用\h6.4本章小结\h参考资料\h第7章JTAG调试\h7.1简介\h7.1.1ICE\h7.1.2JTAG\h7.2JTAG原理\h7.2.1边界扫描链路\h7.2.2TAP信号\h7.2.3TAP寄存器\h7.2.4TAP控制器\h7.2.5TAP指令\h7.3JTAG应用\h7.3.1JTAG调试\h7.3.2调试端口\h7.4IA处理器的JTAG支持\h7.4.1P6处理器的JTAG实现\h7.4.2探测模式\h7.4.3ITP接口\h7.4.4XDP端口\h7.4.5ITP-XDP调试仪\h7.4.6直接连接接口\h7.4.7典型应用\h7.5ARM处理器的JTAG支持\h7.5.1ARM调试接口\h7.5.2调试端口\h7.5.3访问端口\h7.5.4被调试器件\h7.5.5调试接插口\h7.5.6硬件调试器\h7.5.7DS-5\h7.6本章小结\h参考资料\h第三篇GPU及其调试设施\h第8章GPU基础\h8.1GPU简史\h8.1.1从显卡说起\h8.1.2硬件加速\h8.1.3可编程和通用化\h8.1.4三轮演进\h8.2设备身份\h8.2.1“喂模式”\h8.2.2内存复制\h8.2.3超时检测和复位\h8.2.4与CPU之并立\h8.3软件接口\h8.3.1设备寄存器\h8.3.2批命令缓冲区\h8.3.3状态模型\h8.4GPU驱动模型\h8.4.1WDDM\h8.4.2DRI和DRM\h8.5编程技术\h8.5.1着色器\h8.5.2Brook和CUDA\h8.5.3OpenCL\h8.6调试设施\h8.6.1输出调试信息\h8.6.2发布断点\h8.6.3其他断点\h8.6.4单步执行\h8.6.5观察程序状态\h8.7本章小结\h参考资料\h第9章NvidiaGPU及其调试设施\h9.1概要\h9.1.1一套微架构\h9.1.2三条产品线\h9.1.3封闭\h9.2微架构\h9.2.1G80(特斯拉1.0微架构)\h9.2.2GT200(特斯拉2.0微架构)\h9.2.3GF100(费米微架构)\h9.2.4GK110(开普勒微架构)\h9.2.5GM107(麦斯威尔微架构)\h9.2.6GP104(帕斯卡微架构)\h9.2.7GV100(伏特微架构)\h9.2.8持续改进\h9.3硬件指令集\h9.3.1SASS\h9.3.2指令格式\h9.3.3谓词执行\h9.3.4计算能力\h9.3.5GT200的指令集\h9.3.6GV100的指令集\h9.4PTX指令集\h9.4.1汇编和反汇编\h9.4.2状态空间\h9.4.3虚拟寄存器\h9.4.4数据类型\h9.4.5指令格式\h9.4.6内嵌汇编\h9.5CUDA\h9.5.1源于Brook\h9.5.2算核\h9.5.3执行配置\h9.5.4内置变量\h9.5.5Warp\h9.5.6显式并行\h9.6异常和陷阱\h9.6.1陷阱指令\h9.6.2陷阱后缀\h9.6.3陷阱处理\h9.7系统调用\h9.7.1vprintf\h9.7.2malloc和free\h9.7.3__assertfail\h9.8断点指令\h9.8.1PTX的断点指令\h9.8.2硬件的断点指令\h9.9Nsight的断点功能\h9.9.1源代码断点\h9.9.2函数断点\h9.9.3根据线程组和线程编号设置条件断点\h9.10数据断点\h9.10.1设置方法\h9.10.2命中\h9.10.3数量限制\h9.10.4设置时机\h9.11调试符号\h9.11.1编译选项\h9.11.2ELF载体\h9.11.3DWARF\h9.12CUDAGDB\h9.12.1通用命令\h9.12.2扩展\h9.12.3局限\h9.13CUDA调试器API\h9.13.1头文件\h9.13.2调试事件\h9.13.3工作原理\h9.14本章小结\h参考资料\h第10章AMDGPU及其调试设施\h10.1演进简史\h10.1.1三个发展阶段\h10.1.2两种产品形态\h10.2Terascale微架构\h10.2.1总体结构\h10.2.2SIMD核心\h10.2.3VLIW\h10.2.4四类指令\h10.3GCN微架构\h10.3.1逻辑结构\h10.3.2CU和波阵\h10.3.3内存层次结构\h10.3.4工作组\h10.3.5多执行引擎\h10.4GCN指令集\h10.4.17种指令类型\h10.4.2指令格式\h10.4.3不再是VLIW指令\h10.4.4指令手册\h10.5编程模型\h10.5.1地幔\h10.5.2HSA\h10.5.3ROCm\h10.5.4StreamSDK和APPSDK\h10.5.5Linux系统的驱动\h10.6异常和陷阱\h10.6.19种异常\h10.6.2启用\h10.6.3陷阱状态寄存器\h10.6.4陷阱处理器基地址\h10.6.5陷阱处理过程\h10.7控制波阵的调试接口\h10.7.15种操作\h10.7.2指定目标\h10.7.3发送接口\h10.7.4限制\h10.8地址监视\h10.8.14种监视模式\h10.8.2数量限制\h10.8.3报告命中\h10.8.4寄存器接口\h10.8.5用户空间接口\h10.9单步调试支持\h10.9.1单步调试模式\h10.9.2控制方法\h10.10根据调试条件实现分支跳转的指令\h10.10.1两个条件标志\h10.10.24条指令\h10.11代码断点\h10.11.1陷阱指令\h10.11.2在GPU调试SDK中的使用\h10.12GPU调试模型和开发套件\h10.12.1组成\h10.12.2进程内调试模型\h10.12.3面向事件的调试接口\h10.13ROCm-GDB\h10.13.1源代码\h10.13.2安装和编译\h10.13.3常用命令\h10.14本章小结\h参考资料\h第11章英特尔GPU及其调试设施\h11.1演进简史\h11.1.1i740\h11.1.2集成显卡\h11.1.3G965\h11.1.4Larabee\h11.1.5GPU\h11.1.6第三轮努力\h11.1.7公开文档\h11.2GEN微架构\h11.2.1总体架构\h11.2.2片区布局\h11.2.3子片布局\h11.2.4EU\h11.2.5经典架构图\h11.3寄存器接口\h11.3.1两大类寄存器\h11.3.2显示功能的寄存器\h11.4命令流和环形缓冲区\h11.4.1命令\h11.4.2环形缓冲区\h11.4.3环形缓冲区寄存器\h11.5逻辑环上下文和执行列表\h11.5.1LRC\h11.5.2执行链表提交端口\h11.5.3理解LRC的提交和执行过程\h11.6GuC和通过GuC提交任务\h11.6.1加载固件和启动GuC\h11.6.2以MMIO方式通信\h11.6.3基于共享内存的命令传递机制\h11.6.4提交工作任务\h11.7媒体流水线\h11.7.1G965的媒体流水线\h11.7.2MFX引擎\h11.7.3状态模型\h11.7.4多种计算方式\h11.8EU指令集\h11.8.1寄存器\h11.8.2寄存器区块\h11.8.3指令语法\h11.8.4VLIW和指令级别并行\h11.9内存管理\h11.9.1GGTT\h11.9.2PPGTT\h11.9.3I915和GMMLIB\h11.10异常\h11.10.1异常类型\h11.10.2系统过程\h11.11断点支持\h11.11.1调试控制位\h11.11.2操作码匹配断点\h11.11.3IP匹配断点\h11.11.4初始断点\h11.12单步执行\h11.13GT调试器\h11.13.1架构\h11.13.2调试事件\h11.13.3符号管理\h11.13.4主要功能\h11.13.5不足\h11.14本章小结\h参考资料\h第12章MaliGPU及其调试设施\h12.1概况\h12.1.1源于挪威\h12.1.2纳入ARM\h12.1.3三代微架构\h12.1.4发货最多的图形处理器\h12.1.5精悍的团队\h12.1.6封闭的技术文档\h12.1.7单元化设计\h12.2Midgard微架构\h12.2.1逻辑结构\h12.2.2三流水线着色器核心\h12.2.3VLIW指令集\h12.3Bifrost微架构\h12.3.1逻辑结构\h12.3.2执行核心\h12.3.3标量指令集和Warp\h12.4Mali图形调试器\h12.4.1双机模式\h12.4.2面向帧调试\h12.5Gator\h12.5.1Gator内核模块(gator.ko)\h12.5.2Gator文件系统(gatorfs)\h12.5.3Gator后台服务(gatord)\h12.5.4Kbase驱动中的gator支持\h12.5.5含义\h12.6Kbase驱动的调试设施\h12.6.1GPU版本报告\h12.6.2编译选项\h12.6.3DebugFS下的虚拟文件\h12.6.4SysFS下的虚拟文件\h12.6.5基于ftrace的追踪设施\h12.6.6Kbase的追踪设施\h12.7其他调试设施\h12.7.1Caiman\h12.7.2devlib\h12.7.3Mali离线编译器\h12.8缺少的调试设施\h12.8.1GPGPU调试器\h12.8.2GPU调试SDK\h12.8.3反汇编器\h12.8.4ISA文档\h12.9本章小结\h参考资料\h第13章PowerVRGPU及其调试设施\h13.1概要\h13.1.1发展简史\h13.1.2两条产品线\h13.1.3基于图块延迟渲染\h13.1.4IntelGMA\h13.1.5开放性\h13.2Rogue微架构\h13.2.1总体结构\h13.2.2USC\h13.2.3ALU流水线\h13.3参考指令集\h13.3.1寄存器\h13.3.2指令组\h13.3.3指令修饰符\h13.3.4指令类型\h13.3.5标量指令\h13.3.6并行模式\h13.4软件模型和微内核\h13.4.1软件模型\h13.4.2微内核的主要功能\h13.4.3优点\h13.4.4存在的问题\h13.5断点支持\h13.5.1bpret指令\h13.5.2数据断点\h13.5.3ISP断点\h13.6离线编译和反汇编\h13.6.1离线编译\h13.6.2反汇编\h13.7PVR-GDB\h13.7.1跟踪调试\h13.7.2寄存器访问\h13.7.3其他功能\h13.7.4全局断点和局限性\h13.8本章小结\h参考资料\h第14章GPU综述\h14.1比较\h14.1.1开放性\h14.1.2工具链\h14.1.3开发者文档\h14.2主要矛盾\h14.2.1专用性和通用性\h14.2.2强硬件和弱软件\h14.3发展趋势\h14.3.1从固定功能单元到通用执行引擎\h14.3.2从向量指令到标量指令\h14.3.3从指令并行到线程并行\h14.4其他GPU\h14.4.1Adreno\h14.4.2VideoCore\h14.4.3图芯GPU\h14.4.4TITMS34010\h14.5学习资料和工具\h14.5.1文档\h14.5.2源代码\h14.5.3工具\h14.6本章小结\h参考资料\h第四篇可调试性\h第15章可调试性概览\h15.1简介\h15.2观止和未雨绸缪\h15.2.1NT3.1的故事\h15.2.2未雨绸缪\h15.3基本原则\h15.3.1最短距离原则\h15.3.2最小范围原则\h15.3.3立刻终止原则\h15.3.4可追溯原则\h15.3.5可控制原则\h15.3.6可重复原则\h15.3.7可观察原则\h15.3.8易辨识原则\h15.3.9低海森伯效应原则\h15.4不可调试代码\h15.4.1系统的异常分发函数\h15.4.2提供调试功能的系统函数\h15.4.3对调试器敏感的函数\h15.4.4反跟踪和调试的程序\h15.4.5时间敏感的代码\h15.4.6应对措施\h15.5可调试性例析\h15.5.1健康性检查和BSOD\h15.5.2可控制性\h15.5.3公开的符号文件\h15.5.4WER\h15.5.5ETW和日志\h15.5.6性能计数器\h15.5.7内置的内核调试引擎\h15.5.8手动触发崩溃\h15.6与安全、商业秘密和性能的关系\h15.6.1可调试性与安全性\h15.6.2可调试性与商业秘密\h15.6.3可调试性与性能\h15.7本章小结\h参考资料\h第16章可调试性的实现\h16.1角色和职责\h16.1.1架构师\h16.1.2程序员\h16.1.3测试人员\h16.1.4产品维护和技术支持工程师\h16.1.5管理者\h16.2可调试架构\h16.2.1日志\h16.2.2输出调试信息\h16.2.3转储\h16.2.4基类\h16.2.5调试模型\h16.3通过栈回溯实现可追溯性\h16.3.1栈回溯的基本原理\h16.3.2利用DbgHelp函数库回溯栈\h16.3.3利用RTL函数回溯栈\h16.4数据的可追溯性\h16.4.1基于数据断点的方法\h16.4.2使用对象封装技术来追踪数据变化\h16.5可观察性的实现\h16.5.1状态查询\h16.5.2WMI\h16.5.3性能计数器\h16.5.4转储\h16.5.5打印或者输出调试信息\h16.5.6日志\h16.6自检和自动报告\h16.6.1BIST\h16.6.2软件自检\h16.6.3自动报告\h16.7本章小结\h参考资料版权信息书名:软件调试(第2版)卷1:硬件基础ISBN:978-7-115-49250-0本书由人民邮电出版社发行数字版。版权所有,侵权必究。您购买的人民邮电出版社电子书仅供您个人使用,未经授权,不得以任何方式复制和传播本书内容。我们愿意相信读者具有这样的良知和觉悟,与我们共同保护知识产权。如果购买者有侵权行为,我们可能对该用户实施包括但不限于关闭该帐号等维权措施,并可能追究法律责任。版权著张银奎责任编辑陈冀康人民邮电出版社出版发行北京市丰台区成寿寺路11号邮编100164电子邮件315@网址\h读者服务热线:(010)81055410反盗版热线:(010)81055315

内容提要本书堪称是软件调试的“百科全书”。作者围绕软件调试的“生态”系统(ecosystem)、异常(exception)和调试器3条主线,介绍软件调试的相关原理和机制,探讨可调试性(debuggability)的内涵、意义以及实现软件可调试性的原则和方法,总结软件调试的方法和技巧。第1卷主要围绕硬件技术展开介绍。全书分为4篇,共16章。第一篇“绪论”(第1章),介绍了软件调试的概念、基本过程、分类和简要历史,并综述了本书后面将详细介绍的主要调试技术。第二篇“CPU及其调试设施”(第2~7章),以英特尔和ARM架构的CPU为例系统描述了CPU的调试支持。第三篇“GPU及其调试设施”(第8~14章),深入探讨了Nvidia、AMD、英特尔、ARM和Imagination这五大厂商的GPU。第四篇“可调试性”(第15~16章),介绍了提高软件可调试性的意义、基本原则、实例和需要注意的问题,并讨论了如何在软件开发实践中实现可调试性。本书理论与实践紧密结合,既涵盖了相关的技术背景知识,又针对大量具有代表性和普遍意义的技术细节进行了讨论,是学习软件调试技术的宝贵资料。本书适合所有从事软件开发工作的读者阅读,特别适合从事软件开发、测试、支持的技术人员,从事反病毒、网络安全、版权保护等工作的技术人员,以及高等院校相关专业的教师和学生学习参考。

历史回眸我是1949年进入麻省理工学院(MIT)的。就在那一年,第一台存储程序计算机在英国的剑桥和曼彻斯特开始运行。我的一个本科同学KennethRalston是学数学的,他偶尔会和我如痴如醉地谈起一台神秘的机器,说这台机器当时正在MIT附近的Smart街上的Barta楼内组装。我的好奇心后来在1954年的秋天得到了满足,那时我开始学习我的第一门计算机课程“数字计算机编码与逻辑”。那门课程是CharlesAdams教的,他是自动编程(现在称为编译)领域的先锋。当时使用的机器叫作“旋风”,被放置在一间充满了真空管电路的房间内。它由美国海军投资建立,用来研究飞机模拟。因为我的知识背景及我所完成的电子工程专业的硕士课程,一个助研基金约请我在旋风计算机上用“最速下降法”解决一个最优化问题。这让我彻底熟悉了那一套烦琐的程序准备工作。我们以旋风机器的汇编语言编写程序,然后使用Friden电传打字机将以字符和数字表示的代码以打孔的方式输出到纸带上。纸带是用一个Ferrante光电读出器读入计算机的,然后交给“综合系统2”的“系统软件”进行处理。处理结果是一个二进制纸带,以大约每秒钟10行的速度打孔出来,每行代表一个6位字符。而后,用户可以调用一个简单的装载程序(装载程序是保存在几个可以来回交换的内存单元中的)将二进制的纸带装入2048字的内存中,之后就期待着程序的正常运行。用户也可以在控制台的电传打字机上调用“综合系统”的输出例程来把结果打印出来,或者把它们写到一个原始的磁带单元中,留待以后离线打印。那时最漂亮的输出设备是CRT显示屏,用户可以在上面一个点一个点地画出图表和图片。上面配备了一部照相机,可以把显示的图片录制在胶片上。系统程序员已经开发好了“崩溃照相”功能,可以把程序出错时内存中的内容显示在CRT显示屏上。用户可以在第二天早上取到显影后的胶片,然后用一个缩微胶卷阅读器来研究上面的八进制数字。在那时,这是调试旋风程序的主要方法,除此之外,就是把中间结果打印出来。大多数我们这样的普通用户不知道的是,在Barta楼里有一个后屋,在那里第一个基于计算机的飞机跟踪和威胁检测系统上的分类工作正在进行。那里放置了一些更先进的设备,有很多台PPI(计划和位置标识器)显示器,并且已经开发出了第一个定点设备——光笔,用来跟计算机实时交互。旋风计算机最初的主内存是威廉斯管型的,这还不足以满足实时操作的可靠性标准。这一需求带动了相关研究工作并促进了磁心内存的产生。旋风工程师建造了一个非常简单的计算机,称作内存测试机(MTC),用来测试新的内存。因为新内存表现良好,所以立刻把它安装在旋风计算机上,而后MTC也就功成身退了。旋风计算机上的工作促使了MIT林肯实验室的成立,实验室的主要责任是基于旋风计算机上的实时系统技术开发一个美国国家空中防御系统。同时,林肯实验室也进行了计算机技术的研究,并建立了两台使用新的晶体管技术的机器TX-0和TX-2。之所以编号都是偶数,是因为奇数(odd)在英文中同时有古怪的意思,主管设计者之一WesleyClark曾经说:“林肯不做奇数的(古怪的)计算机”。TX-0和TX-2的关系类似于MTC和旋风的关系:TX-0用于测试非常大的(按当时标准)内存,然后这些内存再用于功能更强大的TX-2。这些新机器继承了旋风系统中使用CRT显示屏和发光笔这些与用户实时交互的能力,同时也保留了使用纸带作为程序的主要介质。在开发TX-0的同时,在MIT安装了一台IBM704机器。它用来补充并最终接替了旋风作为MIT一般用户的主计算机。当林肯实验室不再需要TX-0后,MIT电子工程系长期租用了它。MIT的师生(特别是电子研究实验室的师生),都为拥有了一台计算机而大喜过望,因为从此研究人员便可以自由使用并亲手操作这台计算机,这要比IBM704计算机采用的批处理方式方便得多。我于1958年8月完成了我的博士论文,成为一个四处寻找机遇的学校教员。我的新办公室在康普顿实验室楼(26号楼)的二楼。有一天那里发生的事情引起了我的注意,人们正在一块宽广的区域安装一台TX-0,它的位置就在IBM704计算机的正上方。与TX-0一起到来的软件工具只有两个,一个是简单的汇编器程序,另一个是“UT-3”(3号工具纸带)。两个程序都是二进制打孔纸带的形式,没有源代码。因为它们是以八进制代码手工输入的。UT-3通过一个控制台打字机与用户交互(这里仍然是一个电传打字机,它包含了普通打字机的功能,可以被用户或被TX-0所驱动,将输入的字符传递到计算机或打印在纸上;这台打字机还带有一个机械纸带打孔器和阅读器,可以将字符打在纸带上或从纸带把字符读入计算机中)。用户可以以八进制形式把数据输入到指定的内存位置,也可以要求打印指定内存位置或区域的内容。在MIT,我们马上着手给这两个程序增加功能。汇编器最后演化为一个叫作MACRO的程序,除了有其他熟悉的汇编语言功能外,它还支持宏指令(宏功能是从DougMcIlroy在贝尔实验室的研究工作中得到启发的)。有了汇编器后,就使得大范围重写和扩展UT-3成为可能。TomStockham和我使新的程序支持符号,新的程序可以使用汇编器生成的符号表。我们把这个程序称作FLIT(电传打字机询问纸带),这个名字仿用了当时一个很常用的杀虫喷雾剂的名字(当GraceHopper在哈佛的继电器计算机上工作时,跟踪到一次故障是由于继电器触点上的一只飞蛾造成的,从此人们开始把计算机的问题称作bug,即“臭虫”)。FLIT最重要的功能是为调试程序(“除虫”)提供了断点设施。用户可以要求FLIT在被测试程序中向指定的指令位置插入最多4个断点。当被测试的程序遇到一个断点时,FLIT会通知用户,并且允许用户分析或修改内存的内容。分析结束后,用户可以要求FLIT继续执行程序,就像没有中断过一样。FLIT程序是后来的DDT(另一种杀虫剂)调试程序的典范,DDT是MIT的学生为DEC公司生产的PDP-1计算机开发的。FLIT(以及TX-0)的缺点之一是,没有办法防止被测试程序向调试程序占用的内存里存储数据,这会使调试程序停止工作。在给DECPDP-1建立分时系统时,我们做了特别的设计,使得DDT与待测试的程序在各自的地址空间中执行,但DDT仍可以观察和改变被测试程序中的信息。我们把它称为“隐身调试器”。为了提供这种保护,需要对PDP-1增加一些逻辑,它们是随着为支持分时系统而做的更改和补充一起安装的。这个系统在1963年前后开始运行。PDP-1上的分时系统为伯克利加州大学在SDS940上建立的分时系统提供了典范(L.PerterDeutsch兜里装着的那个小操作系统从MIT转移到了伯克利加州大学)。我隐约地相信,隐身调试器的机制对于DECPDP-11/45的设计产生了重要影响,贝尔实验室就为这个系统开发了UNIX。JackB.Dennis2008年4月于马萨诸塞州贝尔蒙特

第2版前言在900多年前的一个秋夜,一轮明月高高地挂在黄州的天空。夜深了,很多人都已经入睡。但在承天寺的庭院里,还有两个人在散步。他们一边交谈,一边欣赏美丽的夜景。洁白的月光泼洒在庭院里,像是往庭院里注入了一汪汪清水,把地面变成了水面,清澈透明。翠竹和松柏的影子映在其中,随风摇摆,仿佛水草在晃动。这两个人中,一位是大文豪苏轼,另一位是他的好朋友张怀民。这一年是公元1083年,苏轼46岁。可能是在当晚,也可能是在第二日,苏轼写了一篇短文来记录这次夜游。这篇短文便是著名的《记承天寺夜游》。第一次看到这篇散文,我便爱不释手。每次读苏轼文集,都喜欢把这一篇再读一遍。文章很短,不足百字,但意境隽永,令人回味无穷。“元丰六年十月十二日夜,解衣欲睡,月色入户,欣然起行。念无与为乐者,遂至承天寺寻张怀民。怀民亦未寝,相与步于中庭。庭下如积水空明,水中藻荇交横,盖竹柏影也。”文末的议论尤其脍炙人口:“何夜无月?何处无竹柏?但少闲人如吾两人者耳。”诚然,月夜常有,竹子和松树也很平常,但是这样的夜游不常有。2013年深秋,与十几位喜欢调试技术的朋友在庐山五老峰下的白鹿洞书院聚会,吃过晚饭大家坐在古老的书院里交流调试技术,直到夜里10点左右。然后,大家又聚集在延宾馆的庭院里,一边海阔天空地聊天,一边欣赏美丽的夜景。说话的间隙可以听见院子外面贯道溪的哗哗水声;抬起头,便看到满天的星斗。2008年6月3日,作者收到了出版社快递给我的《软件调试》第1版,喜不自禁,写了一篇博客,名为“手捧汗水的感觉”。弹指一挥间

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论