22 | 生成汇编代码(一):汇编语言其实不难学
该思维导图由 AI 生成,仅供参考
了解汇编语言
- 深入了解
- 翻译
- 解释
- 总结
学习汇编语言对于理解编译器后端生成汇编代码的原理和从上层到底层认知的贯通十分有益。汇编语言是可读性更好的机器语言,基本上每条指令都可以直接翻译成一条机器码。文章介绍了汇编语言的基础知识,包括汇编语言的组成元素,如指令、伪指令、标签和注释。此外,还介绍了如何通过C语言生成汇编代码,并通过编译器将其转换为目标文件和可执行文件。通过学习汇编语言,读者可以掌握一些汇编技能,应用到某项工作中,比如在C语言里嵌入汇编,实现某个特殊功能,或者读懂某些底层类库或驱动程序的代码。文章内容简洁明了,适合初学者快速了解汇编语言的基本概念。文章还详细介绍了汇编语言中的指令格式和常用指令,以及x86-64架构的寄存器的使用方法,为读者提供了全面的汇编语言基础知识。文章内容丰富,适合对汇编语言感兴趣的读者阅读学习。
《编译原理之美》,新⼈⾸单¥59
全部留言(18)
- 最新
- 精选
- 沉淀的梦想没太看懂文稿中的"leaq L_.str(%rip), %rdi"里面的"L_.str(%rip)"的含义,能再解释一下吗?
作者回复: 就是一个间接内存访问。基数是%rip,也就是指令寄存器中的值,也就是leaq这行代码的下一行代码的地址。L_.str会被汇编器算出一个直接数来,比如0x20,也就是32个字节。这行指令就等价于:0x20(%rip)。 0x20是什么意思?就是这个字符串常量的地址与%rip值的差。这种寻址方式叫做rip相对寻址。因为代码区在下面,静态数据区在上面,所以静态数据的地址一定大于指令的地址。在这里,是多0x20个字节,也就是32个字节。 为什么要这么麻烦呢?为什么不使用这个字符串的确定地址呢?这主要是为了让程序代码更加位置无关。在使用动态库之类的场景的时候有好处。 另外,lea这个指令除了获取地址以外,还有一个“奇怪”的用法,它可以用计算地址的方法,实际上对寄存器的值同时完成加法和乘法的计算,相当于一个三元计算,并且只使用一个时钟周期。比如:lea 0x20(,%eax,2) %eax,本来是用来算一个地址,结果被用来一次性的做了一个乘法和一个加法计算。 提供3篇文章作为参考: https://stackoverflow.com/questions/40329260/why-is-the-address-of-static-variables-relative-to-the-instruction-pointer https://stackoverflow.com/questions/3250277/how-to-use-rip-relative-addressing-in-a-64-bit-assembly-program https://zhuanlan.zhihu.com/p/58774036
2019-10-12426 - 不的老师,为啥要设计成区分调用者、被调用者保护的寄存器,统一被调用者或者调用者保护,有啥问题么
作者回复: 这里有一个效率的问题。 如果全部都是调用者保护,那么其实你调用的对象根本不会破坏你的寄存器,你也要保护起来,那就增加了成本,对于逻辑比较简单的被调用者,是用不到几个寄存器的。 如果全部都是被调用者保护,也是一样的逻辑。如果调用者用了很少几个寄存器,被调用者却要保护很多,也不划算。 所以最优的方法,其实是比较中庸主义的。我觉得这可以用概率的方法做比较严谨的证明。
2019-10-2311 - 有学识的兔子一直想着学习逆向工程,奈何汇编理解不足 学习摸不着头脑,老师的课程给我带来了启发。
作者回复: Great! 计算机科学里很多知识都是通着的,可以触类旁通!
2020-06-164 - 李圣悦确实汇编并不难,最近一直在查内核宕机问题,阅读内涵汇编代码没什么阻碍。难就难在如何恢复c代码…
作者回复: 感谢分享心得!
2020-06-081 - 牛逼中…这里面说到地址,指的是可执行文件中的相对地址么?肯定不是内存吧,这个时候还没加载运行,和内存无关吧?
作者回复: 汇编代码中到处会用到地址,这个地址就是内存地址。因为汇编代码中的操作数会采用直接内存访问和间接内存访问两种方式。 不过,这些地址一般都不会指定一个绝对数值,而是一个相对值,比如-8(%rsp)是比%rsp的值减8的地址。这是在栈里使用内存的标准方式。其中%rsp指向的是栈顶的地址。而栈顶的地址,是在运行期可以确定的。 至于函数(过程)和全局变量的地址,在链接的时候是可以确定的。
2020-03-26 - Dylan记得汇编入门的时候是从写一个简单的斐波那契数列开始~~当时真的觉得神奇,后来和内核驱动程序打交道,看多了大神们写的汇编,感觉好像也没那么难
作者回复: 你说的是对的。并没有太难。 如有可能,大家都加强一下汇编的素养。这样,在思考某些技术问题的时候,因为知道最底层的机制,会思考得比较彻底。
2020-03-212 - 宝鹏老师,as工具生成的文件不能直接运行,as hello.s -o hello,生成的hello并不是可执行文件
作者回复: 没错!是我的疏忽。在其他章节里是先生成.o,然后再用gcc链接一下。这里疏忽了。我已经把文稿改了!
2020-02-262 - 好雨知时节宫老师,想问下:文中在示例中提到: 8(%rbp),是比 %rbp 寄存器的值加 8。 //想知道这里的%rbp 寄存器中存储的内容一个地址还是具体的数据值?8(%rbp) 的含义是:%rbp 寄存器中存储的地址加8后的新地址 还是 %rbp 寄存器中具体数据值+8 得到的具体值? -8(%rbp),是比 %rbp 寄存器的值减 8。//
作者回复: 在寄存器里存的就是一个数。至于这个数的语义是地址,还是别的数字,汇编代码是不管的。你完全可以用%rbp来做纯数学计算。因为根据现在的系统调用约定,其实不强制要求%rbp一定用来表示栈底地址,只对%rsp有要求。
2020-02-23 - 权华刚刚的问题,xorl %eax, %eax,将返回值置为0。
作者回复: 对的。
2019-11-12 - 权华leaq L_.str(%rip), %rdi leaq L_.str.1(%rip), %rsi xorl %eax, %eax callq _printf xorl %eax, %eax 宫老师你好,这是文章前面的汇编代码的一部分,我不明白 xorl %eax, %eax 这两行代码,它的作用是什么?为什么没有给寄存器 eax 就直接 xorl 操作了。
作者回复: 修昂党羽给eax赋值为0,但用xorl使用的时钟周期更少。
2019-11-12