Tan*_*nik 5 assembly prerequisites
我决定学习汇编语言,因为我开始知道学习它有很多好处,我们可以直接与硬件交互,我们可以学习计算机如何更好,等等.当我开始学习它时,我开始知道它有点奇怪而且不像其他编程语言所以我想也许我会发现它很难学.所以,我只想问学习汇编语言的基本先决条件是什么.有关信息,我已经学习了C,C++,C#,PHP等编程语言.
你必须告诉我们你想学习什么机器的装配.ARM,x86(_64),Sparc,等都是不同ISA.
如果你只想介绍一般的汇编编程世界,Randal Hyde的装配艺术很好(尽管你所写的并不完全是汇编,但更多的是高级和低级语言之间的混合,它会介绍你很好地了解这个概念).
如果你已经把目光投向了x86,我可以推荐这本书:专业汇编语言.除了那本书,sandpile.org是一个很好的资源.
因为x86,环境的选择也很重要.以下是伊利诺伊大学厄本那香槟分校ACM学生分会 - SIGWINDOWS的Windows组装编程精彩教程.对于Unix,我遇到的一个很棒的教程就是这个.一个伟大的,更一般的资源是Dennis Yurichev的Reverse Engineering for Beginners.本书针对windows和unix环境,虽然它涉及逆向工程,但它可以帮助你学习很多关于计算机上运行的程序的机制.
因为ARM,这篇文章是一个很好的介绍.这篇文章也是对此事的另一个重要介绍
大约两个月前我开始在汇编中编程,到目前为止一切顺利。让我稍微总结一下我到目前为止所学到的东西。
句法
x86 汇编有两种主要语法:Intel和AT&T。各有利弊。Intel 语法似乎只用于基于 x86 的处理器,而 AT&T 语法用于几种不同的体系结构(例如 ARM)。如果您查看OpenBLAS的源代码,您会发现它们将 AT&T 语法用于多种不同的架构。但是,许多人认为 Intel 语法更具可读性。到目前为止,我一直在使用 Intel 语法进行编程,但我知道如何阅读大部分 AT&T 语法。
汇编器
您可以将内联汇编与 GCC 一起使用,但不能与 MSVC 64 位一起使用。到目前为止,我还没有为内联汇编烦恼。有多种汇编程序可供您选择,例如:MASM、NASM、YASM、FASM和GAS. 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
Run Code Online (Sandbox Code Playgroud)
然后查看文件,foo.s或者您可以使用objdump
gcc -O3 -c foo.c
objdump -d foo.o //AT&T syntax
objdump -d -Mintel foo.o //Intel syntax
Run Code Online (Sandbox Code Playgroud)
您应该了解操作系统的函数调用约定。32 位代码和 64 位代码的调用约定不同。对于 Windows 和 Linux,它们对于 32 位代码是相同的,但对于 64 位代码是不同的。到目前为止,我只使用 NASM 为 Linux 64 位编写了汇编代码。
SO 上的许多汇编问题似乎都是关于在汇编中编写整个函数,包括用户输入和输出。我不认为这是必要的。让 C 处理输入和输出。你可以看到这个问题的一个例子。我给出了 NASM 代码和 C 代码,并解释了如何组装、编译和链接它们。这是我在 x86 汇编中编写的第一件事。在那个问题中,我有一个功能
float triad(float *x, float *y, float *z, const int n);
Run Code Online (Sandbox Code Playgroud)
Linux x86-64(或 System V AMD64 ABI)调用约定传递rdi寄存器中的第一个参数,第二个参数rsi和第三个参数 it rdx。所以在这种情况下rdi=x, rsi=y, rdx=n。
一旦您了解调用约定并且可以将来自汇编的目标文件与 C 连接起来,您会发现使用汇编会容易得多。
最后,对我来说学习汇编的第二个最佳来源是Agner Fog 的 Optimizing Assembly 手册。手册的第一部分为初学者提供了很多很好的建议。一旦你获得了一些经验,手册的后面部分就会有很多很好的信息。