Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 英特尔X86-64汇编教程或书籍_Assembly_X86 64_Intel - Fatal编程技术网

Assembly 英特尔X86-64汇编教程或书籍

Assembly 英特尔X86-64汇编教程或书籍,assembly,x86-64,intel,Assembly,X86 64,Intel,我试图用示例或好书搜索英特尔x64汇编教程,但在英特尔网站上也找不到 那么,你能为我推荐一本好的教程或书吗?? 我正在linux上使用nasm 谢谢不可否认,你喜欢如何学习编程是个人偏见 但特别是关于汇编语言,我发现一种方法对我来说比阅读指令集参考手册和/或汇编语言书籍(如果有的话)更有用 在我还没有使用过的操作系统平台上,我通常要做的是利用开发人员工具链来了解汇编如何为一个新的CPU/一个我不知道的CPU工作。就像这样: 为目标CPU安装一个(交叉)编译器和反汇编程序。如今,GNU gcc/

我试图用示例或好书搜索英特尔x64汇编教程,但在英特尔网站上也找不到

那么,你能为我推荐一本好的教程或书吗?? 我正在linux上使用nasm


谢谢

不可否认,你喜欢如何学习编程是个人偏见

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

在我还没有使用过的操作系统平台上,我通常要做的是利用开发人员工具链来了解汇编如何为一个新的CPU/一个我不知道的CPU工作。就像这样:

  • 为目标CPU安装一个(交叉)编译器和反汇编程序。如今,GNU gcc/binutils的普遍性通常意味着
    gcc
    objdump-d

  • 创建一堆小程序/一小段源代码,如:

  • 通过编译器优化编译这些代码,并反汇编生成的目标代码。
    代码的结构非常简单,可以演示ABI在wrt中的行为。函数调用、传递参数和返回值、管理寄存器空间wrt。在进行函数调用时保留/可变的寄存器。它还将向您展示一些用于初始化常量数据的基本汇编代码,以及堆栈访问和管理之类的“粘合”

  • 将其扩展到简单的C语言结构,如循环和
    if
    /
    else
    switch
    语句。始终保留对外部未定义函数的一些调用,因为这样做将防止编译器优化器抛出所有“测试代码”,并且当您使用
    switch()
    if()
    测试时,对
    argc
    (或其他函数参数)进行谓词,因为编译器无法预测(从而“古怪地”优化代码的构建块)

  • 通过使用
    struct{}
    class{}
    定义(包含不同基元数据类型的序列)扩展此功能,以了解编译器如何在内存中排列这些基元数据类型,哪些汇编指令用于访问字节/字/整数/长/浮点等。
    所有这些测试代码都可以有意识地改变(比如,使用与
    +
    不同的操作),和/或使其更复杂,以便了解更多有关指令集和ABI的特定部分

完成此操作并查看输出后,找到副本(电子版或非电子版)平台ABI的。其中包含关于如何完成上述操作/为什么这样做的规则手册,它将帮助您了解为什么这些规则适用于特定平台。了解上述内容非常重要,因为当您编写自己的汇编代码时,您必须将其与其他非汇编代码进行交互(除非是纯粹的演示)。这是你需要遵守规则的地方,所以即使你不知道这些规则,至少你知道规则手册在哪里

只有在这之后,我才建议您实际跟踪特定平台的指令集参考

这是因为当你首先经历了以上内容之后,你已经有了足够的经验/你已经看到了足够多的东西,可以从一个小C程序开始,编译到汇编源代码,稍微修改一下,组装并链接它,看看你的修改是否达到了预期的效果

在那个阶段,尝试使用一些更不常见/专门化的指令会容易得多,因为您已经了解了函数调用的工作原理,需要什么类型的粘合代码来将程序集与程序的其他部分连接起来,您已经使用了工具链,所以您不需要从头开始re

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

旁注:

为什么我建议在分析编译器生成的汇编代码以获得如此简单的示例时使用编译器优化?

这个问题的答案是,与某些人的直觉相反,如果你让编译器进行优化,生成的汇编代码会简单得多。没有优化,编译器通常会创建“愚蠢的”代码,例如,将所有变量放入堆栈中,保存并从堆栈中还原它们,而你看不到任何原因。寄存器保存/还原/初始化只是为了覆盖下一条指令中的reg和更多类似的内容。因此,发出的代码量要大得多。它充满了粗糙,更难找到旁观者。编译器优化迫使我们将这部分内容精简到最基本的部分,这是您想要了解平台ABI和Assembly的内容。因此,请使用编译器优化。

我不知道nasm教程,但您可以获得,您应该会发现它非常有用。intel.com上的教程?这听起来很有帮助开个蹩脚的玩笑。从开始。令人惊讶的是,它是基于NASM的。当你掌握32位汇编时,请切换到64位。我推荐Ray Seyfarth为Linux介绍64位英特尔汇编语言编程。这本书使用YASM而不是NASM,但YASM接受AFAIK几乎所有NASM代码,还支持DWARF2调试数据格式等正如一些SSE和AVX代码一样,它只假设了一些编程背景,甚至解释了二进制和十六进制数字等。我在DOS时代学习过x86汇编,但这本书是关于如何在Linux x86-64汇编中完成事情的有用参考。这是一个非常好的idead/答案。非常感谢。这是最好的一本书我从来没有见过这样的答案。
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;
}