
机械工业出版社的《汇编语言程序设计》
又名: Professional Assembly Language
作者: (美)布鲁姆
是linux汇编 用gas等汇编器
前几天,在组内分享了关于链接器的一些东西,在这里总结一下。讨论的背景主要是基于C/C++,Linux平台相关。链接器相关的一些基本问题 学习或者了解链接器,有一些基本的问题需要关心:链接器做些什么;链接器和体系结构;程序是怎样生成的。下面做简要介绍。链接器做些什么 链接器之所以存在或者产生,基本上是由于程序开发的模块化。这里讲的模块,主要是编译概念上的模块,通常他们按照功能划分,比如一个.c或者.cpp文件就是一个编译单元,就是一个模块,编译后就产生一个.o目标文件。为了最终生成一个可执行文件、静态库或者动态库,就需要把各个编译单元按照特定的约定组合到一起。这里特定的约定指的就是“目标文件格式”,它定义了目标文件、库文件和可执行文件的格式,这里组合这一过程就叫做链接。一个编译模块中,通常是函数的定义和全局数据的定义,数据类型的定义通常在头文件中,编译时会被包含在编译模块中。函数和数据由符号来标识,一般符号有全局和静态之分,全局符号可以被其他模块引用,而静态符号只能在本模块中引用。编译各个模块时,编译器会解析该模块。重要的一项工作就是建立符号表,符号表中包含了本模块有哪些符号可以被其他模块引用(导出符号),还包括本模块引用(导入符号,即未定义符号)、但在其他模块中定义的符号。每一个符号都关联一个地址,这个地址指明了该符号在本模块中的偏移地址(通常是一个从0开始的地址)。
链接器在链接过程中,会扫描各个模块的符号表,得到一个“全局符号表”,链接器由此决定一个符号在哪里被定义,在哪里被引用。并且,将符号引用处替换为定义处的地址,这一过程就叫做符号解析。
链接器的一项终极目标就是生成可执行文件。通常,可执行文件和普通目标文件的重要区别就是地址空间的使用。主流 *** 作系统中,可执行文件都是基于虚拟地址空间的,即每个可执行文件都有相同且独立的地址空间,并且文件中各个段(代码段,数据段,以及进程空间中的堆栈段)都有相似的布局。而普通目标文件却使用从零开始的地址空间,这样一来,模块M中的符号m就可能和模块N中的符号n拥有“相同”的地址。在链接器链接各个模块时,会从各个模块中“提取”类型相同的段进行合并,并将合并后的段写入可执行文件中。这一过程被称为存储空间的分配。值得一提的是,栈、堆以及未初始化的数据这些“运行时”需要的空间不会在可执行文件中占据磁盘空间,但它们占用相应的地址空间。
由于存在上述“合并”过程,前面提到的符号解析就涉及到另外一个过程:重定位。由于各个模块中的函数/数据地址会被重新排放,那么对这些符号的引用也必须被相应地调整。这一调整过程被称作重定位。
符号解析,存储空间分配,还有重定位,这三个过程是一个有机的整体,是“同时”进行的,且这三个过程也是模块化所带来的必须要解决的问题。链接器和体系结构 在我们编写普通应用程序时,不需要过多的关系体系结构的问题,但对于链接器学习者/编写者来说,相当大的工作都必须围绕体系结构展开,比如目标平台的ABI,内存地址,指令格式,寻址方式等等,下面做大致介绍。
另外,多字节数据的字节序也是链接器需要考虑的。字节序是关于如何使用线性的连续字节来表示多字节数据的问题,有Little-endian和Big-endian两种字节序。小端序是指将多字节数据的低权重字节放在内存的低地址处,大端序则正好相反。直观讲,从内存的低地址向高地址方向看,先看到多字节数据的低权重字节的就是小端序,否则就是大端序。至于为什么会存在两种字节序,两者有何优劣,我觉得这只是个“个人喜好”问题,就好象剥鸡蛋先磕破哪一头,蹲厕所时脸里还是脸朝外一样,事实上,直到前些天,我才亲眼看到,真的是有“茅房拉屎脸朝内”的人的。
指令格式和寻址方式也会影响链接器的工作,因为在符号重定位的时候,链接器需要修改指令中 *** 作数部分,所以需要知道每种指令的指令格式及寻址方式,以便对指令做出适当的调整。程序是怎样生成的 事情渐渐明了了,编译器前端对语言进行词法、语法分析,建立语法树,编译器后端在语法树的基础上针对特定的平台生成指令,并按照特定的格式输出到磁盘中的目标文件。链接器按照前面所说的过程生成最终的可执行文件或程序库。(这里的程序库特指动态库,因为静态库只是目标文件的简单集合,理论上不需要链接器的参与)本文只针对链接器进行简单的讨论,关于编译器的功能和相关原理,有大量的资料可以参考。目标文件格式 目标文件格式是指令、数据在磁盘中存储形式的一种约定。它描述了指令、数据的存储格式和布局,并且针对不同类型的文件(普通目标文件,可执行文件,动态库)有不同描述侧重点。另外它还描述了一些供外部程序使用的元信息,例如普通目标文件中的符号表的内容和组织形式,待重定位符号的信息;可执行文件中各个段的信息,程序的入口点(程序从何处开始执行),哪些符号需要在运行时解析,这些符号包含在哪些动态库中,以及解析这些库需要哪种动态链接器等等;动态库为了实现同时被多个进程链接需要什么样的组织形式,本身又引用了其他动态库的哪些符号等等。通常,不同的平台都会有自己的目标文件的格式标准:COM:DOS最初采用的一种非常简单的格式,除了指令、数据之外,基本不包含其他信息。PE:Windows当前采用的目标格式,继承自COFF,是一种主流的现代目标格式,相比COM有更强大的功能支持。a.out:最初UNIX平台采用的目标格式,简单且功能强大,但对于C++这样的高级语言支持不足。ELF:当前Linux/Unix平台采用的主流格式,继承自a.out,且对高级语言支持很友好。 除了ABI,目标格式的不同,也是在一种 *** 作系统下编译的程序无法在另一种 *** 作系统中执行的原因。程序库 终于到库了,研究库很有趣,也相当实用。概念上,库可以分为静态库,动态库,且这两种库都可以实现为“共享库”,但在实现上,静态共享库由于需要考虑态度的问题、实现太过复杂且得不偿失,现实中很少有这种类型的库。所以,应用中只存在两种库:静态库和动态共享库,下面分别做简要介绍,关于在Linux中如何创建这两种库,可以参考我之前写的一篇博客,或者其他更详尽更优秀的资料。静态库 在功能特性上,静态库是指这样一种库,在链接时,其中被引用的代码、数据被“复制”到引用该库的程序中。在格式上,静态库十分简单,他是普通目标文件的集合,是一种简单的拼接。事实上,Linux平台下静态库.a文件使用独立的归档工具ar建立,为了使链接器能够有效地查找库中包含的各个目标文件以及符号,经常还需要一个叫做ranlib的工具在.a文件中建立索引。
在链接时,链接器想普通目标文件一样使用静态库,仅仅多了在库中查找符号及对应目标文件的过程。动态链接库 动态链接库和静态库差异较大,Linux平台,它由ELF格式直接支持。但由于共享库的特殊性,它需要一些特殊特性的支持:
PIC(Position Independent Code),位置无关代码。动态共享库需要在运行时动态地加载到内存,为了在各个进程中调用共享库中的代码和数据,就需要将该库映射到不同进程的进程空间。由于各个进程的地址空间使用情况不尽相同,很难将共享库映射到各进程相同的位置。这样一来,就对共享库的代码提出了挑战,它需要能够在不同的地址区间上都正确的执行。位置无关代码就是因此而提出的。
位置无关代码的基本思想是这样的:将共享中对绝对地址的引用转化为相对地址的形式。对于函数调用,实现起来很简单,因为代码是只读的,指令间的相对地址也是固定的,只需要将函数调用转化会相对地址即可。但对于数据的引用就复杂很多了,由于各个进程都需要访问共享库中的数据,而这些进程通常是毫无关联的,一个进程对共享库数据的修改不应该被其他进程看到。一种好的方法就是让各个进程都拥有自己的一份数据拷贝。但这又引出一个问题,共享库是被动态映射的,数据空间也只能在映射时才需要分配,那么在共享库代码中如何引用这些数据,以达到不同进程使用相同的代码访问不同的数据呢?
于是另外一种结构被引入了,即GOT(Global Offset Table),全局偏移量表。它的基本思想也是相对地址引用。在共享库的数据段加入GOT,GOT的表项保存各个数据的地址。由于共享库中指令和数据段的相对地址在链接后是固定的,这样在指令中就可以使用相对地址来找到GOT的起始地址,然后根据各个数据在GOT的偏移量来找到其对应的地址。而该地址是在共享库被映射到进程空间时,由动态链接器在相应的进程空间中分配并设置的。
接下来的问题就是,进程中如何调用共享库中的代码呢?ELF使用一种延迟加载的方法,即当进程调用共享库中一个函数时,才解析该函数的地址,且只有第一次才解析,第一次解析之后的调用就不会被再次解析,而是将之前解析到的地址保存下来。这里又引入一种机制,叫做PLT(Procedure Linkage Table),它和GOT一起(使用共享库的进程也有一个GOT)引入了一个函数调用的间接层。
类似共享库的GOT,进程的GOT表项保存了本进程引用的共享库中的函数地址,但在第一次对该函数的调用之前,该表项保存的并不是函数的地址,而是指向PLT中一个指令的地址。为了方便说明问题,假设进程中main函数引用了libmath.so中的函数add,那么PLT大致是这个样子的,1 2 3 4 5 6 7 8 9 10 11 12 13 .plt0:0x080483d0: pushl 0x8049ff80x080483d6:jmp*0x8049ffc...add@plt:0x080483e0 <+0>:jmp*0x804a0000x080483e6 <+6>:push $0x00x080483eb <+11>:jmp0x80483d0... main:...0x080484ec <+24>:call0x80483e0 <add@plt># 对add函数的调用 ... 第十二行对add函数的调用跳转到第五行,这是一条jmp指令,0x804a000是它的地址 *** 作数,该地址即是add在GOT中的地址项,最初该地址处保存的地址是0x080483e6,即jmp指令的下一条push指令。于是最初jmp指令执行后没有任何效果,直接执行下一条指令。push指令将add在重定位项的索引入栈,通过该重定位项可以得到add符号本身(即字符串add)。然后又是一条jmp指令它跳转到第二行,又是一个push指令,接下来又是jmp指令,这个jmp指令也使用了GOT中的一个表项,该表项存储的是动态链接器(ld.so)的加载/解析函数。在解析函数中,查找add符号在共享库中的地址,将该地址填入add对应的GOT表项,然后跳转至add函数开始执行。到下一次调用add函数,第五行的jmp指令就直接跳转到add函数了。
动态链接基本就是这个过程了。在这个过程中有许多有意思的指令,将栈玩弄于鼓掌,像变魔术一样,有兴趣的话可以使用gdb等相关工具调试一下。一些工具 玩弄二进制,很多实用工具是离不了的,最重要的就是GNU Binutils二进制工具链了。包括查看ELF文件信息的readelf,对目标文件、可执行文件、共享库、core内存转储文件等反汇编的objdump,重量级的调试器gdb,查看共享库使用情况的ldd等等。一些参考资料 了解链接器工作原理,现成的资料并不多,《Linkers and Loaders》算是经典了,中文版也可以买得到,翻译得还算中规中矩。另外,《程序员的自我修养:链接、装载与库》写的很浅显,不错的一本书。
为了更好的理解链接器,必须对ELF的细节有所了解,Executable and Linkable Format这份文档可以参考。
研究二进制,汇编知识是必须的,如果是Linux平台,了解些GNU 汇编(AT&T汇编)是再好不过了,不过讲解GNU汇编的资料更是少上加少,布鲁姆的《汇编语言程序设计》虽然内容不多,但对非专业汇编程序员也足够用了,这本书是有英文电子版的。
有了相关工具和入门资料,剩下的就是折腾了。
汇编语言那本书比较好?你好!
1、入门级《汇编语言》,推荐清华大学出版社王爽的《汇编语言》,很简单,很好入门。书中内容的编排有一定连贯性,要用到哪部分知识就介绍哪部分知识。其它书籍不适合入门的原因是一开始就将所有的寄存器、寻址方式列举出来,记忆已经相当困难,何况是活用?所以还没有体会到编程的快乐,就被推进了无尽的苦难中!
2、如果需要学到一定的深度,清华大学出版社的《80x86汇编语言程序设计》(作者不详)《IBM-PC 汇编语言》是比较好的教材(沈美明,温冬婵著)。这些教材我全部都读过,基本上是按照由浅入深的顺序。
需要说明的:汇编语言在当前高级语言的发展环境下,用途范围越来越狭窄,因为面向对象编程思想逐步取代过程语言设计,可以说汇编语言仅在电子产品的底层能够发挥其长处。但是可以借助汇编语言了解计算机的工作原理,为高级语言打下坚实的基础
希望能够帮到你!
大家认为最好的汇编语言入门教材是哪本
最好就是滴水三期的汇编视屏,我就是看它入门的,最关键是免费,
这3本书我都阅读过,最后还是我推荐的视频让我入得门,真心少走弯路
学习汇编语言选哪本书好?
入门级《汇编语言》,推荐清华大学出版社王爽的《汇编语言》,很简单,很好入门。书中内容的编排有一定连贯性,要用到哪部分知识就介绍哪部分知识。其它书籍不适合入门的原因是一开始就将所有的寄存器、寻址方式列举出来,记忆已经相当困难,何况是活用?所以还没有体会到编程的快乐,就被推进了无尽的苦难中!
如果需要学到一定的深度,清华大学出版社的《80x86汇编语言程序设计》(作者不详)《IBM-PC 汇编语言》是比较好的教材(沈美明,温冬婵著)。这些教材我全部都读过,基本上是按照由浅入深的顺序。
需要说明的是,汇编语言在当前高级语言的发展环境下,用途范围越来越狭窄,因为面向对象编程思想逐步取代过程语言设计,可以说汇编语言仅在电子产品的憨层能够发挥其长处。但是可以借助汇编语言了解计算机的工作原理,为高级语言打下坚实的基础。
了解汇编语言看什么书比较好
王爽老师的汇编语言通俗易懂,比较好入门。我就是看的这本书,挺不错的
初学c语言,推荐几本书看一下,要不要买一本王爽的汇编语言呢?
初学,建议你就下载视频教程。建议孙鑫老师的
对有一定基础了买书才看得懂。。
汇编也是建议有基础了。然后再看。不然只会把自己搞乱的。
打字不容易,感觉ok就给个好评采纳吧,谢谢。。。。。
看完王爽的《汇编语言第三版》,之后该看哪本书?
参考以前问题:
zhidao.baidu/question/292589535
包括那些没有采纳的答案,都很有见地。
学习汇编语言的入门书籍有哪些啊
大多时候,一些初学者不知道应该读什么书入门,有一定基础的开发者不知道如何进阶。本文总结了一个C++优秀书籍清单,希望能够为你带来一定的帮助。因为多读一些优秀的书籍,对于开发者稳固编程基础、提高编程技能有很大帮助,这些书大多数都有中文版,并且可以很容易在网上找到。
阶段1
《Essential C++》
这是一本内容不多但很实用的C++入门书籍,强调快速上手与理解C++编程。本书主要围绕一系列逐渐复杂的程序问题,以及用以解决这些问题的语言特性展开讲解。你不只学到C++的函数和结构,也会学习到它们的设计目的和基本原理。
《C++ Primer》
本书对C++基本概念、技术、以及现代C++编程风格进行了全面而且权威的阐述,是C++初学者的最佳指南;本书可以帮助你编写实用的程序,而无需首先精通每个语言细节。对于中高级程序员,本书也是不可或缺的参考书。
阶段2
《Effective C++》和《More effective C++》
作者是Scott Meyers.你应该熟读它们,并清楚地理解每个项目。该书围绕55条准则,每一条都介绍了一个可让你写出更好的C++程序代码的方法,并以特别设计过的例子详加讨论。
《Exceptional C++(C++编程剖析)》和《More exceptional C++》
这两本书中都包含了40个C++编程问题,这些问题会让你磨练自己的技能,最终成为优秀的C++程序员。这些问题是Herb Sutter精心挑选,与ISO/ANSI C++官方标准相一致,帮助程序员在设计、架构和编码过程中保持良好的风格,从而使编写的C++软件更健壮、更高效。
《Thinking in C++(C++编程思想)》
C++ 领域权威著作,介绍了C++实用的编程技术和最佳的实践方法。
阶段3
《Inside the C++ object model(深度探索C++对象模型)》
本书专注于C++面向对象程序设计的底层机制,包括结构式语意、临时性对象的生成、封装、继承,以及虚拟——虚拟函数和虚拟继承,帮助你理解程序的底层实现,以便写出更高效的代码。
《The design and evolution of C++(C++语言的设计与演化)》
本书作者也是C++语言的设计者Bjarne Stroustrup,作者在书中综合性地介绍了C++的发展历史,C++中各种重要机制的本质意义和设计背景,这些机制的基本用途和使用方法,讨论了C++所适合的应用领域及其未来的发展前景,既没有忽略关键性的详情,又没有过多地陷入技术细节。
阶段4
《The C++ standard library(C++标准程序库)》
这是标准模板库字典,你可以在本书中找到STL相关的一切知识。本书焦点放在标准模板库、检查容器、迭代器、函数对象和STL算法上。每一个元素都有深刻的呈现,包括其介绍、设计、运用实例、细节解说、陷阱、意想不到的危险,以及相关类别和函数等。
《Effective STL》
这是Scott Meyers的第三本C++专著,也是学习STL最权威的书籍。作者对书中的50个指导方针都作了详尽的分析,并配以示例。通过这些规则,C++开发者可以最大限度地使用STL.
《Generic programming and the STL(泛型编程与STL)》
本书阐述......
学汇编哪些书比较好
呵呵 好书多呀!入门: 王爽《汇编语言》(推荐)保护模式: 周明德《保护方式下的80386及其编》 杨季文《80X86汇编语言程序设计教程》Win32编程: 罗云彬《Windows环境下32位汇编语言程序设计》(推荐) iczelion《Win32汇编教程》 (美)欧文《Intel 汇编语言程序设计(第五版)》 反正我呀,就是看了王爽《汇编语言》和罗云彬《Windows环境下32位汇编语言程序设计》而已,其他的随便看了,或者没看完,觉得汇编估计也就这两本经典了!《保护方式下的80386及其编》已经绝种,我是在学校图书馆找到的,不过电子书网上有下载,它可以当做指令大全来看!!
想学汇编语言。请问大学本科是用哪本教材的。
先学习一门语言,比如c,VB,再学汇编,汇编教材入门有王爽汇编,清华出版的汇编语言程序设计
Intel汇编语言程序设计 和 王爽的汇编语言 那本比较好?
话说怎么这么巧,这三本我都看过。。。
王爽的简单,容易明白,容易入门,没法精通。
Intel汇编语言,内容详细,缺点就是太厚了,你可以和王爽的比下,快3本了。
所以他写的比较全面。
windows32,这个我曾经是作为后续才看到,因为它是WIN32汇编,不是X8086汇编了,
他使用的是WINDOWS界面编程。win32汇编和8086汇编类似于MFC和C的的关系一样。
调用的都是API,就不是单纯的MOV ADD JMP了。
需要学习WIN32汇编,最好是在8086汇编的基础上去学习,就像是从简单的学起,。
下面是我的建议:
如果你只想了解,开拓视野。建议去学王爽的,简单,容易理解,加个汇编交流群,百度一个小甲鱼汇编视频,一半个月就自学会了。
如果你想玩黑客,破解。。。那最好去学习,intel的。如果你连这都看不明白,那么想深入的搞清楚汇编语言,一个字,难。
如果你是学计算机的,想在windows下进行编程,并且想最个有界面的,可以先学,王爽,然后学习win32.
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)