As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center提供指导。




已关闭8年。




我尝试搜索带有示例或一本好书的intel x64汇编教程,但即使在intel网站上也找不到。

所以,您能为我推荐一本很好的教程或书吗?
我在Linux上使用nasm。

谢谢

最佳答案

诚然,您更喜欢学习编程是个人的偏见。

但是特别是对于汇编语言,我发现一种方法对我来说比阅读汇编语言的指令集引用手册和/或书籍(如果有的话)更有用。

我通常要弄清楚如何为新CPU/我尚未使用的OS平台上的CPU assembly 程序,是利用开发人员工具链。像那样:

  • 为目标CPU安装(交叉)编译器和反汇编程序。如今,GNU gcc的/binutils无处不在通常意味着gccobjdump -d
  • 创建一堆小程序/小段源代码,例如:
  • extern int funcA(int arg);
    extern int funcB(int arg1, int arg2);
    extern int funcC(int arg1, int arg2, int arg3);
    extern int funcD(int arg1, int arg2, int arg3, int arg4);
    extern int funcE(int arg1, int arg2, int arg3, int arg4);
    extern int funcF(int arg1, int arg2, int arg3, int arg4, int arg5);
    extern int funcG(int arg1, int arg2, int arg3, int arg4, int arg5, int arg6);
    extern int funcH(int arg1, int arg2, int arg3, int arg4, int arg5, int arg6,
                     int arg7);
    
    int main(int argc, char **argv)
    {
        printf("sum of all funcs: %d\n",
            funcA(1) + funcB(2, 3) + funcC(4, 5, 6) + funcD(7, 8, 9, 10) +
            funcE(11, 12, 13, 14, 15) + funcF(16, 17, 18, 19, 20, 21) +
            funcG(22, 23, 24, 25, 26, 27, 28) + funcH(29, 30, 31, 32, 33, 34, 35));
        return 12345;
    }
  • 通过编译器优化对它们进行编译,并反汇编生成的目标代码。
    该代码的结构非常简单,足以演示ABI的行为。函数调用,传递参数和返回值,管理寄存器空间wrt。进行函数调用时,寄存器将保留/保留到哪个寄存器中。它还将向您展示一些用于初始化常量数据的基本汇编代码,以及诸如堆栈访问和管理之类的“胶水”。
  • 将此扩展为简单的C语言构造,例如循环和if/elseswitch语句。始终保持对外部未定义函数的某些调用,因为这样做会阻止编译器优化器抛出所有“测试代码”,并且当您使用if()switch()测试时,请基于argc(或其他函数参数)断言,因为编译器无法预测两者之一(因此“最奇怪”地优化了代码的构建块)。
  • 将其扩展为使用包含不同原始数据类型序列的struct {}class {}定义,以便找出编译器如何将它们安排在内存中,这些汇编指令用于访问字节/字/整数/长整数/浮点数等。
    您可以故意改变所有这些测试代码(例如,使用不同于+的操作),和/或使其更复杂,以便更多地了解指令集和ABI的特定部分。

  • 完成之后,查看输出,找到Platform ABI的副本(无论是电子版本还是非电子版本)。其中包含有关如何完成上述操作的规则手册/为什么以这种方式完成操作,这将帮助您了解为什么这些规则适用于特定平台。了解以上内容至关重要,因为在编写自己的汇编代码时,必须将其与其他非汇编接口(interface)(除非是纯演示)。那是您需要遵守规则的地方,因此,即使您内心不了解规则,至少也要知道规则书在哪里。

    只有在那之后,我才建议您实际跟踪特定平台的指令集引用。

    这是因为当您先完成上述内容后,您便已经有足够的经验/您已经足够了解使用小型C程序开始,将其编译为汇编源代码,对其进行少许修改,进行汇编和链接以及看看您的修改是否达到了预期的效果。

    在那个阶段尝试使用更多不常见/专门的指令会容易得多,因为您已经了解了函数调用的工作原理,将程序集与程序的其他部分接口(interface)所需的粘合代码类型,我们已经使用过工具链,因此您不再需要完全从头开始。

    也就是说,总而言之,我的建议是从上至下而不是从下至上学习组装。

    旁注:

    为什么在分析如此简单的示例的编译器生成的汇编代码时,建议使用编译器优化?
    好吧,答案是因为,与某些人相反,如果让编译器从根本上优化 hell ,则生成的汇编代码要简单得多。如果不进行优化,编译器通常会创建“愚蠢”的代码,例如将所有变量放入堆栈,从那里无所不包地保存并恢复它们,确实注册保存/恢复/初始化只是为了覆盖下一条指令的reg,还有更多类似的事情。因此,发出的代码量要大得多。杂乱无章,很难理解。编译器优化会强制将这一问题精简为基本内容,这是您为了了解平台ABI和组件而希望看到的内容。因此,请使用编译器优化。

    关于assembly - 英特尔X86-64组装教程或书籍,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/15297842/

    10-13 07:06