【问题标题】:Prerequisites for learning Assembly Language [closed]学习汇编语言的先决条件[关闭]
【发布时间】:2014-10-30 16:14:59
【问题描述】:

我决定学习汇编语言,因为我开始知道学习它有很多好处,我们可以直接与硬件交互,我们可以更好地学习计算机,等等。当我第一次开始学习它时,我开始知道它有点奇怪,不像其他编程语言,所以我想也许我会觉得很难学。所以,我只是问学习汇编语言的基本先决条件是什么。有关信息,我已经学习了 C、C++、C#、PHP 等编程语言。

【问题讨论】:

  • IMO,您应该熟悉数字的十六进制和二进制表示法、按位逻辑运算(andor xor、...)以及目标的内存模型架构/操作系统。一些关于汇编编程的书籍/教程可能会解释这些事情,其他人可能会假设您已经了解它们。

标签: assembly prerequisites


【解决方案1】:

你必须告诉我们你想学习什么机器的组装。 ARMx86(_64)Sparc 等都是不同的 ISA。

如果您只是想大致了解汇编编程的世界,Randal Hyde's Art of Assembly 是一个不错的选择(虽然您所写的并不完全是汇编,但更多的是高级和低级语言的混合,它会很好地向您介绍这个概念)。

如果你已经将目光投向了x86,我可以推荐这本书:Professional Assembly Language。除了那本书,sandpile.org 是一个很好的资源。

对于x86,环境的选择也很重要。 Here 是伊利诺伊大学厄巴纳香槟分校 ACM 学生分会 - SIGWINDOWS 编写的 Windows 汇编编程的精彩教程。对于 Unix,我遇到的一个很棒的教程是 this one。一个很棒的、更通用的资源是 Dennis Yurichev 的 Reverse Engineering for Beginners。这本书同时针对 windows 和 unix 环境,虽然它涉及逆向工程,但它可以帮助您了解很多关于在您的计算机上运行的程序的机制。

对于ARMthis article 是一个很好的介绍。 This article is also another great introduction to the matter

【讨论】:

  • +1,sandpile.org 链接太棒了!
【解决方案2】:

大约两个月前我开始使用汇编编程,到目前为止一切顺利。让我简单总结一下我到目前为止所学到的知识。

语法

x86 汇编有两种主要语法:IntelAT&T。各有利弊。 Intel 语法似乎只用于基于 x86 的处理器,而 AT&T 语法用于几种不同的架构(例如 ARM)。如果您查看 OpenBLAS 的源代码,您会发现它们使用 AT&T 语法用于几种不同的架构。但是,许多人认为 Intel 语法更具可读性。到目前为止,我一直在使用 Intel 语法进行编程,但我大部分时间都知道如何阅读 AT&T 语法。

汇编器

您可以将内联汇编与 GCC 一起使用,但不能与 MSVC 64 位一起使用。到目前为止,我还没有为内联汇编而烦恼。您可以选择多种汇编程序,例如:MASMNASMYASMFASMGAS。 MASM 仅使用 Intel 语法,并且据我所知仅真正用于 Windows(我不认为它可以是 Linux 的 ELF 目标文件)。 NASM 也仅使用 Intel 语法,但可以创建多个不同的目标文件,例如适用于 Windows 和 Linux。据我所知,YASM 在很大程度上是 NASM,但也支持 AT&T 语法。 FASM 使用 Intel 语法,也可以创建几个不同的目标文件,但它在几个方面与 NASM 和 YASM 不同。我还没有使用过 FASM,但它看起来很诱人。 GAS 使用 AT&T 语法(尽管可以使用 Intel 语法),实际上是使用 GCC 编译时使用的语法。 GCC 生成组件,然后发送到 GAS。

了解每个汇编程序都只有方言很重要,因此您不能期望用 MASM 编写的代码必须在 NASM 中开箱即用地进行汇编。据我了解,NASM 和 YASM 在很大程度上是兼容的。

您应该选择哪个汇编程序?到目前为止,我只使用过 NASM。

调用约定和用 C 链接

到目前为止,对我来说学习汇编的最佳来源是 GCC。用 C 编写代码,然后查看程序集。例如,如果你有一个简单的函数foo 你可以这样做

gcc -O3 -S foo.c             //AT&T syntax
gcc -O3 -S -masm=intel foo.c //Intel syntax

然后查看文件foo.s 或者你可以使用objdump

gcc -O3 -c foo.c
objdump -d foo.o             //AT&T syntax
objdump -d -Mintel foo.o     //Intel syntax

您应该知道您的操作系统的function calling conventions。 32 位代码和 64 位代码的调用约定不同。对于 Windows 和 Linux,它们对于 32 位代码是相同的,但对于 64 位代码是不同的。到目前为止,我只用 NASM 为 Linux 64 位编写了汇编代码。

关于 SO 的许多汇编问题似乎是关于在汇编中编写整个函数,包括用户输入和输出。我不认为这是必要的。让 C 处理输入和输出。您可以在this question 中看到一个示例。我给出了 NASM 代码和 C 代码,并解释了如何组装、编译和链接它们。这是我在 x86 汇编中写的第一件事。在那个问题中,我有一个功能

float triad(float *x, float *y, float *z, const int n);

Linux x86-64(或者更确切地说是 System V AMD64 ABI)调用约定传递rdi 寄存器中的第一个参数,rsi 中的第二个参数和rdx 中的第三个参数。所以在这种情况下rdi=x, rsi=y, rdx=n

一旦您掌握了调用约定,并且可以将汇编中的目标文件与 C 接口,您会发现使用汇编更加容易。

最后,我学习汇编的第二个最佳来源是Agner Fog's Optimizing Assembly manual。手册的第一部分为初学者提供了很多很好的建议。一旦你获得了一些经验,手册的后面部分就会有很多很好的信息。

【讨论】:

  • 对于内联 asm,我强烈建议 不要 使用它,直到您已经习惯在 asm 中编写整个函数,以及 how compilers turn C into asm。对于 GNU C 内联汇编,您必须获得完全正确的约束才能向优化器描述您的代码。踩到编译器的脚趾是一个常见的错误,如果你只告诉编译器你想要"r"(pointer),而不告诉它你想要指向的内存,那么即使取消引用寄存器中的指针来读取内存也是一个错误。
【解决方案3】:

一台计算机、一个汇编器、一本描述相关汇编语言的书。由于您了解 C,因此某些 C 编译器甚至允许您在 C 之间编写程序集。

【讨论】:

  • 我实际上是在问汇编语言的学习先决条件是什么,而不是学习汇编语言需要什么材料。
  • 我不认为有任何真正的先决条件。与物理学不同,你必须先学习代数才能学习牛顿物理学。
【解决方案4】:

如果你选对了书,你真的不需要任何先决条件。

我通过Assembly Language Step-by-Step: Programming with Linux 3rd Edition 自己(没有任何导师)学习了汇编语言(基础,只是不需要更多)作为我的第一门编程语言。它教授基础知识,但读完这本书后,您可以毫无问题地阅读任何其他高级汇编书籍。

【讨论】:

    【解决方案5】:

    Assembly 不同于您已经学习过的任何高级语言。

    x86 寄存器是一个很好的起点,我找到了一个网站来解释它们:

    http://www.eecg.toronto.edu/~amza/www.mindsec.com/files/x86regs.html

    祝你好运!

    编辑:

    此外,开始并坚持使用某种汇编语言总是好的,例如我从 NASM 开始,它拥有相当规模的社区,并具有一些很酷的功能,如符号管理和命名空间。

    【讨论】:

    • 这就是我们需要的所有东西吗?这就是我们学习这种复杂语言所需的全部内容吗?
    • 不,我说这是一个很好的起点。