澄清有关汇编的基本想法的问题

时间:2012-05-06 07:05:37

标签: assembly x86

我找不到开始学习装配的好地方。我在整个互联网上发现了很多相互矛盾的信息,关于汇编实际是什么,汇编器使用什么,汇编器是什么,以及是否有一种“核心”汇编语言由英特尔为其特定CPU系列发布(我有一个英特尔) x86 CPU这就是我希望学习汇编的方法。)

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

另外,从我所听到的,当有人说“汇编语言”时,这实际上指的是许多不同汇编语言提供的许多不同风格的汇编语言之一。 http://en.wikipedia.org/wiki/X86_assembly_language#Examples MASM样式组装与NASM样式组装

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

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

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

提前致谢,

Prgrmr

4 个答案:

答案 0 :(得分:4)

要迂腐,用于直接与CPU通信的真实语言是machine code。这意味着要计算出必须用于某些指令的实际字节值。这显然太繁琐且容易出错,因此人们使用汇编程序。汇编程序将机器代码的文本表示转换为机器代码本身,并处理各种繁琐的细节,如计算相对地址等。

对于特定的机器代码,可以有许多不同的汇编器,每个汇编器都有自己如何编写汇编的想法。对于x86处理器尤其如此 - 一般来说,有两种风格:Intel和AT& T.然后在其中,不同的汇编程序可以有不同的宏和指令集等等。

为了说明,下面是一些使用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

以下是使用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

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

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

当你说“x86汇编”时,人们理解你的意思是“将在x86架构的任何CPU上运行的汇编”。

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

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

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

x86系列可能是汇编语言的一个过于复杂的例子 - 它有一个terribly long and complex history going back 33+ years。 (32位)应用程序中使用的核心指令的机器代码与1978年发布的8086相同。它已经过多次修订,each adding more instructions

如果您想正确学习x86程序集,请考虑:

  • The Art of Assembly Language Programming,并为DOS,Windows和Linux提供了一个版本。 Windows和Linux版本使用作者发明的一种语言,称为高级程序集或HLA,它有点像x86程序集但不是真的。这可能是也可能不是你的一杯茶 - 它不是严格意义上的装配,但是概念都存在,并且学习如何在之后编写适当的装配并不会有太多的努力。值得称道的是,它还包含大量与装配有关的材料,例如:关于处理器架构,BIOS,视频等的信息.DOS版本教授直接MASM(英特尔)程序集。

  • Programming from the Ground Up在Linux中教授AT& T样式程序集

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

如果您对x86架构感到沮丧,并且愿意为其他架构学习汇编,请考虑从something smaller开始。

答案 1 :(得分:3)

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

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

我能在网上找到的最古老的x86汇编语言参考是1979年的《英特尔MCS-86宏汇编语言手册》。BitSavershere已保存了PDF副本。

原始ASM86的设计师之一埃里克·艾萨克森(Eric Isaacson)继续编写了一种精神上的继任者A86。 A86的方言与ASM86非常相似,但是对ASSUME和SEGMENT指令非常挑剔,诸如此类的内容(Eric Isaacson称它们为“繁文tape节”)被放松或取消了。在提供OP似乎正在寻找的裸机汇编语言精神方面,A86可能比ASM86更好。 A86仅16位;为了运行它,您需要DOS模拟器或运行旧版Windows的计算机(我有一个仍在运行Windows XP的旧IBM Thinkpad x23;我一直在DOS框中运行A86,没有任何问题)。

最后,在OS/2 Museum上有一篇有趣的博客文章,内容涉及在ISIS-2平台上使用ASM86构建原始IBM PC BIOS。

答案 2 :(得分:0)

我认为 核心汇编程序不存在这样的问题。 他们每个人都有自己的方言。 您也可能需要在选择之前考虑要编写代码的操作系统。

这似乎是一篇很好的文章,可能有助于选择一个人开始:http://webster.cs.ucr.edu/AsmTools/WhichAsm.html

答案 3 :(得分:0)

很难加入Michael Slades的答案,但我确实有一些评论。

每个处理器供应商或处理器机器代码的创建者都是通过使用助记符(该处理器的汇编语言)来实现的。通常,在原始处理器文档中定义的程序集,无论是午餐时的餐巾纸还是非常正式且漂亮的文档,都是该处理器的“原始”汇编语言。汇编程序(这里的松散术语,因为它们可以被不同地理解,这里用作解析汇编语言的程序并且理想地从中生成机器代码)被编写为读取该汇编语言,其中包含使代码正确运行所需的其他项目以及一些指令等使程序员的工作更容易(宏,等于(定义)等)。

理想情况下,如果您正在创建一个新的处理器,并且您希望获得任何类型的接受,您首先需要一个汇编程序,然后是其他语言(FORTRAN,BASIC,Pascal,C,现在)(C总是需要的)但显然今天你不需要帕斯卡或基本等)。如果处理器供应商想要销售芯片,那么它需要以某种方式制造或收缩或鼓励至少一个汇编程序。关于8088/8086,英特尔确实有自己的工具,但是,它们当时价格昂贵,其他工具更受欢迎(microsoft masm,msvc,borland tasm,pascal,tcc,bcc)。如果我没记错的话,有一个很好的免费汇编程序叫做a86。现在我们将nasm作为x86的一个好的免费汇编程序的例子。

英特尔x86比规则更为例外,英特尔语法之间存在宗教争论,它更接近于原始语法和AT& T语法。 gnu binutils倾向于不尊重处理器供应商(我会称之为使用不尊重这个词)通过进行更改,x86是最糟糕的,因为他们有AT& T作为默认值,但也支持英特尔与他们(有些,可能全部)工具(其他语言)。例如,长时间的汇编器使用了分号';'为了标记行的结尾以及后面的任何内容是注释,对于ARM来说,binutils当然会认为新行,新指令并使用@作为注释标记。理解是构成后端的是个体,有时这些个体是芯片供应商本身,我知道,不是一个有组织的团体做这些事情,一个人或团体做其余的初始工作,如果他们接受,采取工作的东西,并在它上面。

与注释符号一样,随着时间的推移,不同处理器的汇编程序使用了相似或相同的指令,其他令牌不是机器代码,例如ORG或.ORG表示地址。由于您有时需要拥有机器代码所在的物理地址来对指令进行编码,因此用户需要以某种方式指示该地址,并在您编写一个asm程序的那一天或许在一个文件中或包含的单个文件和汇编程序的输出是完整的二进制文件而不是不完整的对象,您需要该地址。这就是为什么你没有在gnu汇编程序(gas)中看到ORG语句的原因,gnu汇编程序会创建对象,使地址特定指令不完整。由于需要地址以及需要链接以解决未知标签。链接器部分是汇编程序,因为它执行编码剩余指令的最后步骤,它不是通过使用汇编语言ascii源代码而是使用目标文件格式的数据。

x86绝对是我建议你学习的最后一种汇编语言。这是一个有趣的历史课。处理器已经发展得如此之多并且在每一步都变得很早就变成了微编码(大多数处理器都不是微编码的,x86由于其丑陋的装配/机器语言几乎要求它竞争)。

拥有x86并不是学习x86的好理由。您希望学习一个指令集,其中包含可以与处理器对等的工具。当然有一个调试器,你可以单步,但有一个模拟器,你可以操纵输出任何东西,以任何你想要的方式观察任何东西,或者甚至更好的逻辑模拟器,你可以一次看到所有东西,将带来体验学习汇编语言远没那么痛苦。减少疼痛意味着你应该更多地享受它并坚持下去而不是放弃。虽然与任何语言一样需要基本的编程技能,但汇编可以让您快速轻松地解决问题。此外,你不想破坏你的计算机或类似的东西。 (再次,如果你到达你认为需要从asm进行系统调用的地方,请使用像pcemu,dosbox,后来的virtualbox,vmware,qemu这样的东西来运行虚拟机,当崩溃时,你会减少痛苦。