澄清关于什么是程序集的基本思想的问题

Pro*_*rmr 3 x86 assembly

我很难找到一个开始学习汇编的好地方。我在整个互联网上发现了许多相互矛盾的信息,这些信息涉及实际是什么程序集、要使用哪些汇编程序、什么是汇编程序,以及英特尔是否为其特定 CPU 系列发布了一种“核心”汇编语言(我有一个英特尔x86 CPU 所以这就是我想学习汇编的目的)。

有人可以解释上述问题。据我所知,英特尔发布了带有指令集/参考的 CPU 系列(例如 x86),并且各种汇编程序(MASM、FASM、NASM 等)提供了一种更高级别的人类可读语言,用于使机器码指令。

另外,据我所知,当有人说“汇编语言”时,这实际上是指由许多不同的汇编程序提供的许多不同风格的汇编语言中的一种。 http://en.wikipedia.org/wiki/X86_assembly_language#Examples MASM 风格汇编与 NASM 风格汇编

我正在寻找的是“第一个”汇编程序,没有 MASM、NASM 等提供的变体(例如大型宏库)。所有这些组装者一定来自某个地方,这就是我正在寻找的。

基本上,我正在寻找第一个 x86 汇编器/汇编语言,在 MASM、NASM 等之前。有人能给我提供第一个汇编器的链接吗?

顺便说一句,如果我关于组装的整个逻辑是错误的,有人可以澄清一下!

提前致谢,

程序

Mic*_*ade 7

说到迂腐,您将用来直接与 CPU 对话的真正语言是机器代码。这意味着要弄清楚某些指令必须使用的实际字节值。这显然太乏味且容易出错,所以人们改用汇编器。汇编程序将机器代码的文本表示转换为机器代码本身,并处理各种繁琐的细节,例如计算相对地址等。

对于特定的机器代码,可以有许多不同的汇编程序,每个程序集都有自己的关于如何编写程序集的想法。x86 处理器尤其如此——广义上讲,有两种类型:Intel 和 AT&T。然后在其中,不同的汇编器可以有不同的宏和指令集等等。

为了说明这一点,以下是从一些 C 代码生成的汇编示例,其中包含gcc -S -masm=intel

    cmp     eax, ebx
    jl      .L63
    mov     eax, DWORD PTR inbuffd
    mov     DWORD PTR [esp+8], 8192
    mov     DWORD PTR [esp+4], OFFSET FLAT:inbuf
    mov     DWORD PTR [esp], eax
    call    read
    cmp     eax, -1
    mov     ebx, eax
    mov     DWORD PTR inbytes, eax
    je      .L64
    test    eax, eax
    je      .L36
    mov     eax, 1
    xor     edx, edx
    jmp     .L33
Run Code Online (Sandbox Code Playgroud)

这是生成的相同片段gcc -S -masm=att

    cmpl    %ebx, %eax
    jl      .L63
    movl    inbuffd, %eax
    movl    $8192, 8(%esp)
    movl    $inbuf, 4(%esp)
    movl    %eax, (%esp)
    call    read
    cmpl    $-1, %eax
    movl    %eax, %ebx
    movl    %eax, inbytes
    je      .L64
    testl   %eax, %eax
    je      .L36
    movl    $1, %eax
    xorl    %edx, %edx
    jmp     .L33
Run Code Online (Sandbox Code Playgroud)

这两个片段产生相同的机器代码- 区别仅在于汇编语法。特别注意参数的顺序是如何不同的(Intel 是目标优先,AT&T 是源优先),指令名称的细微差别,%在 AT&T 中使用来指定寄存器,等等。

然后是不同的CPU。CPU 具有特定的架构。这意味着它将执行该架构的指令集。对于该架构,将有一个核心指令集,可能还有用于增强功能或特殊应用程序的额外指令组。x86 是一个很好的例子 - 你有浮点指令,MMx,3DNow!和 SSE 1 到 5。该架构的不同 CPU 可能会也可能不会理解额外的指令;通常有一些方法可以询问 CPU 它支持什么。

当您说“x86 程序集”时,人们理解您的意思是“将在 x86 架构的任何 CPU 上运行的程序集”。

更复杂的 CPU - 特别是那些具有内存管理(包括 x86)的 CPU,不仅仅是执行指令。从80286开始,x86 架构有两种主要模式——实模式和保护模式。核心指令集可以在任何一种模式下按原样使用,但内存在每种模式下的工作方式完全不同,以至于尝试编写在任何一种模式下都可以工作的现实世界代码是不切实际的。

后来的 CPU 引入了更多模式。386 引入了虚拟 8086 模式又名 v86 模式,以允许保护模式操作系统运行实模式程序,而无需将 CPU 实际切换到实模式。AMD64 处理器以长模式运行 64 位代码。

一个 CPU 可以支持多种架构——Itanium 架构被认为是一个独立的架构,Intel 发布的所有支持 Itanium 的 CPU 也支持 x86,并具有在它们之间切换的能力。

x86 家族可能是汇编语言的一个过于复杂的例子——它有着可追溯到 33 年以上的极其漫长而复杂的历史。(32 位)应用程序中使用的核心指令的机器码与 1978 年发布的 8086 相同。它经过了多次修订,每次都增加了更多指令

如果您想正确学习 x86 汇编,请考虑:

  • The Art of Assembly Language Programming,并针对 DOS、Windows 和 Linux 各有一个版本。Windows 和 Linux 版本使用作者发明的一种称为高级汇编或 HLA 的语言,它有点像 x86 汇编,但实际上并非如此。这可能是也可能不是你的一杯茶——严格来说这不是真正的组装,但概念都在那里,之后学习编写正确的组装不会有太多努力。值得称赞的是,它还包含大量与组装相关的材料,例如有关处理器架构、BIOS、视频等的信息。DOS 版本教授直接 MASM(英特尔)组装。

  • 从头开始编程教授 Linux 中的 AT&T 风格的汇编

对于实际的汇编程序(免费的),请在 Windows 或Linux上尝试MASM32(英特尔风格)as。碰巧的是,Linuxas将组装 Intel 或 AT&T 样式的程序集。

如果你觉得在x86架构吓倒,并愿意学习汇编一些其他架构,考虑开始与一些 较小


Pag*_*ini 5

除了迈克尔·斯莱德(Michael Slade)的出色回答之外,这里还有一些历史信息:

第一个 x86 汇编程序称为“ASM86”。它由 Intel 生产,最初运行在其 8 位“ISIS”操作系统上。在 DOS 下运行的更高版本已由在线软件历史博物馆 WinWorld 保存。你可以在这里找到它。随附的手册存档包括 Intel 1985 年的 ASM86 方言参考手册。它支持熟悉的指令,例如 ASSUME、SEGMENT、DB/DW、END 等,以及更高级别的宏。

我能在网上找到的最古老的 x86 汇编语言参考是 1979 年的 Intel MCS-86 宏汇编语言手册。BitSavers 已在此处保留了 PDF 副本。

最初的 ASM86 的设计者之一埃里克·艾萨克森 (Eric Isaacson) 继续编写了 A86,一种精神上的继承者。A86 的方言与 ASM86 非常相似,但放松或消除了对 ASSUME 和 SEGMENT 指令等的大量挑剔(Eric Isaacson 将它们称为“繁文缛节”)。A86 在提供 OP 似乎正在寻找的裸机汇编语言精神方面可能比 ASM86 更好。A86 仅 16 位;为了运行它,你需要一个 DOS 模拟器,或者一台运行旧版本 Windows 的机器(我有一台旧的 IBM Thinkpad x23,它仍然运行 Windows XP;我一直在 DOS 框中运行 A86,没有任何问题)。

最后, OS/2 博物馆有一篇关于在 ISIS-2 平台上使用 ASM86 构建原始 IBM PC BIOS 的精彩博客文章。

  • *裸机汇编语言的精神* - NASM 和 YASM 都可以发出平面二进制文件,并且适合制作 16 位引导加载程序和类似的东西,在这种情况下,您没有操作系统的程序加载器将重定位应用于 `mov ax, @ `.exe` 中的 segname` 或其他内容。(NASM 从来不需要对大型 16 位多段程序提供花哨的支持,并且[不实现“假设”指令](https://nasm.us/doc/nasmdoc2.html#section-2.2.4)。如果你想要段覆盖前缀,你必须明确地编写它们。对我来说听起来相当裸机。)不过,还是对历史表示支持。 (2认同)