如何正确学习GNU汇编?
How should I correctly learn GNU assembly?
最近在ubuntu学习汇编,发现了一些assemble,比如NASM、MASM、GAS。它们的语法不同(特别是伪指令),NASM 和 MASM 支持 Intel 语法,GAS 支持 AT&T 语法。
现在,我想学习 AT&T 汇编,所以,我使用 GAS assemble,我找到了一系列关于 GAS 的手册,但对我来说读起来很痛苦,比如 缺少具体例子或者简单介绍基本语法.
我找到了有代表性的部分“指南”:
- https://sourceware.org/binutils/docs/as.html
- https://en.wikibooks.org/wiki/X86_Assembly/GNU_assembly_syntax
- GCC's assembly output of an empty program on x86, win32
- https://flint.cs.yale.edu/cs421/papers/x86-asm/asm.html
像这个例子https://sourceware.org/binutils/docs/as.html#Scl,我想知道我们有什么storage-class value
? gccs-assembly-output-of-an-empty-program-on-x86-win32
告诉我 .scl 2
表示外部存储 class,但我找不到关于此值的任何其他信息。等等。
可能是我学习方向不对,或者是我找资料的方式不对。所以我想问你有一些关于 AT&T 的指南或手册,有例子和清晰的解释给初学者。
我对伪指令感到困惑,标准汇编程序结构是什么样的?
学习汇编时,您可以主要关注指令,以及.section
和.globl
指令.除非你想了解 GAS 指令如何生成元数据,包括调试信息和其他对调试有用的东西 high-level 语言比 hand-written asm.
很多 debug-info 指令,显然 .scl
只记录了它们的语法,没有关于值的含义或其他可能关心你放在那里的值的真正细节。
您可以编写工作 hand-written asm 来玩弄几乎只使用 .section
和 .globl
。 (对于静态数据,.byte
/.short
/.long
/.quad
和.ascii
/.asciz
用于初始化,.space
在BSS,如果需要的话 .p2align
。
这就是为什么 Matt Godbolt 的“编译器浏览器”站点默认过滤掉指令,除了数据初始值设定项,因为当然数据在 .data
或 .rdata
中,而代码在 [=25= 中],关于编译器 asm 输出的有趣部分是实际指令(和静态数据)。参见
完全符合 Windows 对堆栈展开的 SEH 元数据的期望(尤其是在 64 位代码中)可能需要一些额外的指令,对于 x86-64 SysV 也是如此 .cfi
stack-unwind 元数据。但是,如果您需要在稳健的 production-quality 上下文中使用 hand-written asm,而不是仅仅作为了解指令工作原理的 one-off 实验。
https://whosebug.com/tags/x86/info has some links to tutorials (and manuals), and Programming from the Ground Up is a good free book for 32-bit x86 with AT&T syntax. (And GAS directives). It's aimed at running on Linux, so it can teach some OS / computing concepts along the way, the kind of background knowledge necessary for assembly (and system calls) to make sense. Online HTML version
要在现代 64 位 GNU/Linux 发行版上遵循它,您可能需要 as --32
和 ld -m elf_i386
将默认值覆盖为 32 位。并且 gcc -m32 -fno-pie -no-pie
书中说 gcc
.
的任何地方
如果您正在比较有关 C 编译方式的书籍示例,您可能还希望 -fno-stack-protector
进一步简化 C 的 asm 输出。但请注意,不同的 GCC 版本将以不同的方式编译,尤其是默认调整选项多年来发生了变化。 -mtune=pentium
或 -mtune=pentium3
也可能让 GCC 选择 code-gen 更像是一本旧书的策略。当然,当前GCC的选择也是正确的,更适合较新的CPU,只是与旧的GCC不同!
此外,Linux 上使用的 i386 SysV ABI 已更改为需要在 call
指令之前进行 16 字节堆栈对齐,这是由于 GCC 不小心生成了 32 位代码,例如使用依赖于 GCC 选择执行的性能优化的 movaps
。调用 libc 函数通常仍然碰巧在只有 4 字节堆栈对齐的 32 位代码中工作,但是如果您看到现代 GCC 保留的 space 比它需要的多,这通常就是原因。
吹毛求疵:
I found some of assemblers, like NASM, MASM, and GAS. Their syntax is different(particularly pseudo-directives), NASM and MASM support Intel syntax, GAS support AT&T Syntax.
指令与指令语法正交,英特尔语法有不同的风格,尤其是在 MASM 与 NASM 之间。 (以及指令的 MASM 和 NASM 之间的主要区别)。
此外,GAS 还支持 .intel_syntax noprefix
使用某种 MASM-like 指令语法,但仍然是 GAS 指令。
(同样,YASM 有一个 AT&T 模式使用 AT&T 指令语法,但仍然 NASM/YASM 预处理器和指令。)
最近在ubuntu学习汇编,发现了一些assemble,比如NASM、MASM、GAS。它们的语法不同(特别是伪指令),NASM 和 MASM 支持 Intel 语法,GAS 支持 AT&T 语法。
现在,我想学习 AT&T 汇编,所以,我使用 GAS assemble,我找到了一系列关于 GAS 的手册,但对我来说读起来很痛苦,比如 缺少具体例子或者简单介绍基本语法.
我找到了有代表性的部分“指南”:
- https://sourceware.org/binutils/docs/as.html
- https://en.wikibooks.org/wiki/X86_Assembly/GNU_assembly_syntax
- GCC's assembly output of an empty program on x86, win32
- https://flint.cs.yale.edu/cs421/papers/x86-asm/asm.html
像这个例子https://sourceware.org/binutils/docs/as.html#Scl,我想知道我们有什么storage-class value
? gccs-assembly-output-of-an-empty-program-on-x86-win32
告诉我 .scl 2
表示外部存储 class,但我找不到关于此值的任何其他信息。等等。
可能是我学习方向不对,或者是我找资料的方式不对。所以我想问你有一些关于 AT&T 的指南或手册,有例子和清晰的解释给初学者。
我对伪指令感到困惑,标准汇编程序结构是什么样的?
学习汇编时,您可以主要关注指令,以及.section
和.globl
指令.除非你想了解 GAS 指令如何生成元数据,包括调试信息和其他对调试有用的东西 high-level 语言比 hand-written asm.
很多 debug-info 指令,显然 .scl
只记录了它们的语法,没有关于值的含义或其他可能关心你放在那里的值的真正细节。
您可以编写工作 hand-written asm 来玩弄几乎只使用 .section
和 .globl
。 (对于静态数据,.byte
/.short
/.long
/.quad
和.ascii
/.asciz
用于初始化,.space
在BSS,如果需要的话 .p2align
。
这就是为什么 Matt Godbolt 的“编译器浏览器”站点默认过滤掉指令,除了数据初始值设定项,因为当然数据在 .data
或 .rdata
中,而代码在 [=25= 中],关于编译器 asm 输出的有趣部分是实际指令(和静态数据)。参见
完全符合 Windows 对堆栈展开的 SEH 元数据的期望(尤其是在 64 位代码中)可能需要一些额外的指令,对于 x86-64 SysV 也是如此 .cfi
stack-unwind 元数据。但是,如果您需要在稳健的 production-quality 上下文中使用 hand-written asm,而不是仅仅作为了解指令工作原理的 one-off 实验。
https://whosebug.com/tags/x86/info has some links to tutorials (and manuals), and Programming from the Ground Up is a good free book for 32-bit x86 with AT&T syntax. (And GAS directives). It's aimed at running on Linux, so it can teach some OS / computing concepts along the way, the kind of background knowledge necessary for assembly (and system calls) to make sense. Online HTML version
要在现代 64 位 GNU/Linux 发行版上遵循它,您可能需要 as --32
和 ld -m elf_i386
将默认值覆盖为 32 位。并且 gcc -m32 -fno-pie -no-pie
书中说 gcc
.
如果您正在比较有关 C 编译方式的书籍示例,您可能还希望 -fno-stack-protector
进一步简化 C 的 asm 输出。但请注意,不同的 GCC 版本将以不同的方式编译,尤其是默认调整选项多年来发生了变化。 -mtune=pentium
或 -mtune=pentium3
也可能让 GCC 选择 code-gen 更像是一本旧书的策略。当然,当前GCC的选择也是正确的,更适合较新的CPU,只是与旧的GCC不同!
此外,Linux 上使用的 i386 SysV ABI 已更改为需要在 call
指令之前进行 16 字节堆栈对齐,这是由于 GCC 不小心生成了 32 位代码,例如使用依赖于 GCC 选择执行的性能优化的 movaps
。调用 libc 函数通常仍然碰巧在只有 4 字节堆栈对齐的 32 位代码中工作,但是如果您看到现代 GCC 保留的 space 比它需要的多,这通常就是原因。
吹毛求疵:
I found some of assemblers, like NASM, MASM, and GAS. Their syntax is different(particularly pseudo-directives), NASM and MASM support Intel syntax, GAS support AT&T Syntax.
指令与指令语法正交,英特尔语法有不同的风格,尤其是在 MASM 与 NASM 之间。 (以及指令的 MASM 和 NASM 之间的主要区别)。
此外,GAS 还支持 .intel_syntax noprefix
使用某种 MASM-like 指令语法,但仍然是 GAS 指令。
(同样,YASM 有一个 AT&T 模式使用 AT&T 指令语法,但仍然 NASM/YASM 预处理器和指令。)