汇编 订阅
汇编程序是指把汇编语言书写的程序翻译成与之等价的机器语言程序的翻译程序。汇编程序输入的是用汇编语言书写的源程序,输出的是用机器语言表示的目标程序。汇编语言是为特定计算机或计算机系列设计的一种面向机器的语言,由汇编执行指令和汇编伪指令组成。采用汇编语言编写程序虽不如高级程序设计语言简便、直观,但是汇编出的目标程序占用内存较少、运行效率较高,且能直接引用计算机的各种设备资源。它通常用于编写系统的核心部分程序,或编写需要耗费大量运行时间和实时性要求较高的程序段。 展开全文
汇编程序是指把汇编语言书写的程序翻译成与之等价的机器语言程序的翻译程序。汇编程序输入的是用汇编语言书写的源程序,输出的是用机器语言表示的目标程序。汇编语言是为特定计算机或计算机系列设计的一种面向机器的语言,由汇编执行指令和汇编伪指令组成。采用汇编语言编写程序虽不如高级程序设计语言简便、直观,但是汇编出的目标程序占用内存较少、运行效率较高,且能直接引用计算机的各种设备资源。它通常用于编写系统的核心部分程序,或编写需要耗费大量运行时间和实时性要求较高的程序段。
信息
外文名
assembler
汉语拼音
huibian chengxu
中文名
汇编程序
学    科
计算机
汇编程序背景信息
汇编执行指令是机器指令的符号化表示,其操作码用记忆符表示,地址码直接用标号、变量名字、常数等表示。汇编执行指令经汇编程序翻译为机器指令,二者之间基本上保持一一对应的关系。汇编伪指令又称作汇编指示,用于向汇编程序提供用户自定义的符号、数据的类型、数据空间的长度,以及目标程序的格式、存放位置等提示性信息,其作用是指示汇编程序如何进行汇编。使用汇编语言编写的源代码,需要通过使用相应的汇编程序将它们转换成可执行的机器代码。这一过程被称为汇编过程。许多汇编程序可以识别代表地址和常量的标签(label)和符号(symbols),这样就可以用字符来代表操作数而无需采取写死的方式。普遍地说,特定的汇编语言和特定的机器语言指令集是一一对应的。许多汇编程序为程序开发、汇编控制、辅助调试提供了额外的支持机制。有的汇编语言编程工具经常会提供宏,它们也被称为宏汇编器。汇编语言不像其他大多数的程序设计语言一样被广泛用于程序设计;在实际应用中,它通常被应用在底层硬件操作和高要求的程序优化的场合。驱动程序、嵌入式操作系统和实时运行程序都需要汇编语言 [1]  。
收起全文
精华内容
下载资源
问答
  • 什么是汇编语言

    万次阅读 多人点赞 2018-11-19 21:21:37
    汇编语言(assembly language)是一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。在汇编语言中,用助记符(Mnemonics)代替机器指令的操作码,用地址符号(Symbol)或标号...

           汇编语言(assembly language)是一种用于电子计算机微处理器微控制器或其他可编程器件的低级语言,亦称为符号语言。在汇编语言中,助记符(Mnemonics)代替机器指令操作码,用地址符号(Symbol)或标号(Label)代替指令或操作数地址。在不同的设备中,汇编语言对应着不同的机器语言指令集,通过汇编过程转换成机器指令。普遍地说,特定的汇编语言和特定的机器语言指令集是一一对应的,不同平台之间不可直接移植。

           许多汇编程序为程序开发、汇编控制、辅助调试提供了额外的支持机制。有的汇编语言编程工具经常会提供宏,它们也被称为宏汇编器。

           汇编语言不像其他大多数的程序设计语言一样被广泛用于程序设计。在今天的实际应用中,它通常被应用在底层,硬件操作和高要求的程序优化的场合。驱动程序、嵌入式操作系统和实时运行程序都需要汇编语言。

            Microsoft 宏汇编器(称为 MASM)是windows下常用的汇编器。Microsoft Visual Studio 的大多数版本(专业版,旗舰版,精简版……)都包含 MASM。在运行 Microsoft Windows 的 x86 系统中,其他一些有名的汇编器包括:TASM(Turbo 汇编器),NASM(Netwide 汇编器)和 MASM32(MASM 的一种变体)。GAS(GNU 汇编器)和 NASM 是两种基于 Linux 的汇编器。在这些汇编器中,NASM 的语法与 MASM 的最相似。汇编语言最古老的编程语言,在所有的语言中,它与原生机器语言最为接近。它能直接访问计算机硬件,要求用户了解计算机架构和操作系统。

    什么是汇编器和链接器?

           汇编器(assembler)是一种工具程序,用于将汇编语言源程序转换为机器语言。链接器(linker)也是一种工具程序,它把汇编器生成的单个文件组合为一个可执行程序。还有一个相关的工具,称为调试器(debugger),使程序员可以在程序运行时,单步执行程序并检查寄存器和内存状态。

    MASM 能创建哪些类型的程序?

    32 位保护模式(32-Bit Protected Mode)32 位保护模式程序运行于所有的 32 位和 64 位版本的 Microsoft Windows 系统。它们通常比实模式程序更容易编写和理解。从现在开始,将其简称为 32 位模式。
    64 位模式(64-Bit Mode)64 位程序运行于所有的 64 位版本 Microsoft Windows 系统。
    16 位实地址模式(16-Bit Real-Address Mode)16 位程序运行于 32 位版本 Windows 和嵌入式系统。 64 位 Windows 不支持这类程序。

    汇编语言与机器语言有什么关系?

           机器语言(machine language)是一种数字语言, 专门设计成能被计算机处理器(CPU)理解。所有 x86 处理器都理解共同的机器语言。
    汇编语言(assembly language)包含用短助记符如 ADD、MOV、SUB 和 CALL 书写的语句。汇编语言与机器语言是一对一(one-to-one)的关系:每一条汇编语言指令对应一条机器语言指令。寄存器(register)是 CPU 中被命名的存储位置,用于保存操作的中间结果

    C++ 和 Java 与汇编语言有什么关系?

           高级语言如 Python、C++ 和 Java 与汇编语言和机器语言的关系是一对多(one-to-many)。比如,C++ 的一条语句就会扩展为多条汇编指令或机器指令。

    汇编语言可移植吗?

    一种语言,如果它的源程序能够在各种各样的计算机系统中进行编译和运行,那么这种语言被称为是可移植的(portable)。
    例如,一个 C++ 程序,除非需要特别引用某种操作系统的库函数,否则它就几乎可以在任何一台计算机上编译和运行。Java 语言的一大特点就是,其编译好的程序几乎能在所有计算机系统中运行。
    汇编语言不是可移植的,因为它是为特定处理器系列设计的。目前广泛使用的有多种不同的汇编语言,每一种都基于一个处理器系列。
    对于一些广为人知的处理器系列如 Motorola 68x00、x86、SUN Sparc、Vax 和 IBM-370,汇编语言指令会直接与该计算机体系结构相匹配,或者在执行时用一种被称为微代码解释器(microcode interpreter)的处理器内置程序来进行转换。

    发展历程

           说到汇编语言的产生,首先要讲一下机器语言。机器语言是机器指令的集合。机器指令展开来讲就是一台机器可以正确执行的命令。电子计算机的机器指令是一列二进制数字。计算机将之转变为一列高低电平,以使计算机的电子器件受到驱动,进行运算。

           上面所说的计算机指的是可以执行机器指令,进行运算的机器。这是早期计算机的概念。在我们常用的PC机中,有一个芯片来完成上面所说的计算机的功能。这个芯片就是我们常说的CPU(Central Processing Unit,中央处理单元)。每一种微处理器,由于硬件设计和内部结构的不同,就需要用不同的电平脉冲来控制,使它工作。所以每一种微处理器都有自己的机器指令集,也就是机器语言。CPU 只负责计算,本身不具备智能。你输入一条指令(instruction),它就运行一次,然后停下来,等待下一条指令。这些指令都是二进制的,称为操作码(opcode),比如加法指令就是00000011。编译器的作用,就是将高级语言写好的程序,翻译成一条条操作码。对于人类来说,二进制程序是不可读的,根本看不出来机器干了什么。为了解决可读性的问题,以及偶尔的编辑需求,就诞生了汇编语言。汇编语言是二进制指令的文本形式,与指令是一一对应的关系。比如,加法指令00000011写成汇编语言就是 ADD。只要还原成二进制,汇编语言就可以被 CPU 直接执行,所以它是最底层的低级语言

           早期的程序设计均使用机器语言。程序员们将用0, 1数字编成的程序代码打在纸带或卡片上,1打孔,0不打孔,再将程序通过纸带机或卡片机输入计算机,进行运算。这样的机器语言由纯粹的0和1构成,十分复杂,不方便阅读和修改,也容易产生错误。程序员们很快就发现了使用机器语言带来的麻烦,它们难于辨别和记忆,给整个产业的发展带来了障碍,于是汇编语言产生了。

           汇编语言的主体是汇编指令。汇编指令和机器指令的差别在于指令的表示方法上。汇编指令是机器指令便于记忆的书写格式。

    操作:寄存器BX的内容送到AX中
    1000100111011000              机器指令
    mov ax,bx                    汇编指令

           此后,程序员们就用汇编指令编写源程序。可是,计算机能读懂的只有机器指令,那么如何让计算机执行程序员用汇编指令编写的程序呢?这时,就需要有一个能够将汇编指令转换成机器指令的翻译程序,这样的程序我们称其为编译器。程序员用汇编语言写出源程序,再用汇编编译器将其编译为机器码,由计算机最终执行。 

    语言特点

           汇编语言是直接面向处理器(Processor)的程序设计语言。处理器是在指令的控制下工作的,处理器可以识别的每一条指令称为机器指令。每一种处理器都有自己可以识别的一整套指令,称为指令集。处理器执行指令时,根据不同的指令采取不同的动作,完成不同的功能,既可以改变自己内部的工作状态,也能控制其它外围电路的工作状态。

           汇编语言的另一个特点就是它所操作的对象不是具体的数据,而是寄存器或者存储器,也就是说它是直接和寄存器和存储器打交道,这也是为什么汇编语言的执行速度要比其它语言快,但同时这也使编程更加复杂,因为既然数据是存放在寄存器或存储器中,那么必然就存在着寻址方式,也就是用什么方法找到所需要的数据。例如上面的例子,我们就不能像高级语言一样直接使用数据,而是先要从相应的寄存器AX、BX 中把数据取出。这也就增加了编程的复杂性,因为在高级语言中寻址这部分工作是由编译系统来完成的,而在汇编语言中是由程序员自己来完成的,这无异增加了编程的复杂程度和程序的可读性。

           再者,汇编语言指令是机器指令的一种符号表示,而不同类型的CPU 有不同的机器指令系统,也就有不同的汇编语言,所以,汇编语言程序与机器有着密切的关系。所以,除了同系列、不同型号CPU 之间的汇编语言程序有一定程度的可移植性之外,其它不同类型(如:小型机和微机等)CPU 之间的汇编语言程序是无法移植的,也就是说,汇编语言程序的通用性和可移植性要比高级语言程序低。

           正因为汇编语言有“与机器相关性”的特性,程序员用汇编语言编写程序时,可充分对机器内部的各种资源进行合理的安排,让它们始终处于最佳的使用状态。这样编写出来的程序执行代码短、执行速度快。汇编语言是各种编程语言中与硬件关系最密切、最直接的一种,在时间和空间的效率上也最高的一种。

    总体特点

    1.机器相关性

           这是一种面向机器的低级语言,通常是为特定的计算机或系列计算机专门设计的。因为是机器指令的符号化表示,故不同的机器就有不同的汇编语言。使用汇编语言能面向机器并较好地发挥机器的特性,得到质量较高的程序。

    2.高速度和高效率

           汇编语言保持了机器语言的优点,具有直接和简捷的特点,可有效地访问、控制计算机的各种硬件设备,如磁盘、存储器、CPUI/O端口等,且占用内存少,执行速度快,是高效的程序设计语言

    3.编写和调试的复杂性

           由于是直接控制硬件,且简单的任务也需要很多汇编语言语句,因此在进行程序设计时必须面面俱到,需要考虑到一切可能的问题,合理调配和使用各种软、硬件资源。这样,就不可避免地加重了程序员的负担。与此相同,在程序调试时,一旦程序的运行出了问题,就很难发现。

    优点

    1、因为用汇编语言设计的程序最终被转换成机器指令,故能够保持机器语言的一致性,直接、简捷,并能像机器指令一样访问、控制计算机的各种硬件设备,如磁盘、存储器CPUI/O端口等。使用汇编语言,可以访问所有能够被访问的软、硬件资源。

    2、目标代码简短,占用内存少,执行速度快,是高效的程序设计语言,经常与高级语言配合使用,以改善程序的执行速度和效率,弥补高级语言在硬件控制方面的不足,应用十分广泛。

    缺点

    1、汇编语言是面向机器的,处于整个计算机语言层次结构的底层,故被视为一种低级语言,通常是为特定的计算机或系列计算机专门设计的。不同的处理器有不同的汇编语言语法和编译器,编译的程序无法在不同的处理器上执行,缺乏可移植性;

    2、难于从汇编语言代码上理解程序设计意图,可维护性差,即使是完成简单的工作也需要大量的汇编语言代码,很容易产生bug,难于调试;

    3、使用汇编语言必须对某种处理器非常了解,而且只能针对特定的体系结构和处理器进行优化,开发效率很低,周期长且单调。 

    语言组成

    数据传送指令

    这部分指令包括通用数据传送指令MOV、条件传送指令CMOVcc、堆栈操作指令PUSH/PUSHA/PUSHAD/POP/POPA/POPAD、交换指令XCHG/XLAT/BSWAP、地址或段描述符选择子传送指令LEA/LDS/LES/LFS/LGS/LSS等。注意,CMOVcc不是一条具体的指令,而是一个指令簇,包括大量的指令,用于根据EFLAGS寄存器的某些位状态来决定是否执行指定的传送操作。

    整数和逻辑运算指令

    这部分指令用于执行算术和逻辑运算,包括加法指令ADD/ADC、减法指令SUB/SBB、加一指令INC、减一指令DEC、比较操作指令CMP、乘法指令MUL/IMUL、除法指令DIV/IDIV、符号扩展指令CBW/CWDE/CDQE、十进制调整指令DAA/DAS/AAA/AAS、逻辑运算指令NOT/AND/OR/XOR/TEST等。

    移位指令

    这部分指令用于将寄存器或内存操作数移动指定的次数。包括逻辑左移指令SHL、逻辑右移指令SHR、算术左移指令SAL、算术右移指令SAR、循环左移指令ROL、循环右移指令ROR等。

    位操作指令

    这部分指令包括位测试指令BT、位测试并置位指令BTS、位测试并复位指令BTR、位测试并取反指令BTC、位向前扫描指令BSF、位向后扫描指令BSR等。

    条件设置指令

    这不是一条具体的指令,而是一个指令簇,包括大约30条指令,用于根据EFLAGS寄存器的某些位状态来设置一个8位的寄存器或者内存操作数。比如SETE/SETNE/SETGE等等。

    控制转移指令

    这部分包括无条件转移指令JMP、条件转移指令Jcc/JCXZ、循环指令LOOP/LOOPE/LOOPNE、过程调用指令CALL、子过程返回指令RET、中断指令INTn、INT3、INTOIRET等。注意,Jcc是一个指令簇,包含了很多指令,用于根据EFLAGS寄存器的某些位状态来决定是否转移;INT n是软中断指令,n可以是0到255之间的数,用于指示中断向量号。

    串操作指令

    这部分指令用于对数据串进行操作,包括串传送指令MOVS、串比较指令CMPS、串扫描指令SCANS、串加载指令LODS、串保存指令STOS,这些指令可以有选择地使用REP/REPE/REPZ/REPNE和REPNZ的前缀以连续操作。

    输入输出指令

    这部分指令用于同外围设备交换数据,包括端口输入指令IN/INS、端口输出指令OUT/OUTS。

    高级语言辅助指令

    这部分指令为高级语言的编译器提供方便,包括创建栈帧的指令ENTER和释放栈帧的指令LEAVE。

    控制和特权指令

    这部分包括无操作指令NOP、停机指令HLT、等待指令WAIT/MWAIT、换码指令ESC、总线封锁指令LOCK、内存范围检查指令BOUND、全局描述符表操作指令LGDT/SGDT、中断描述符表操作指令LIDT/SIDT、局部描述符表操作指令LLDT/SLDT、描述符段界限值加载指令LSR、描述符访问权读取指令LAR、任务寄存器操作指令LTR/STR、请求特权级调整指令ARPL、任务切换标志清零指令CLTS、控制寄存器和调试寄存器数据传送指令MOV、高速缓存控制指令INVD/WBINVD/INVLPG、型号相关寄存器读取和写入指令RDMSR/WRMSR、处理器信息获取指令CPUID、时间戳读取指令RDTSC等。

    浮点和多媒体指令

    这部分指令用于加速浮点数据的运算,以及用于加速多媒体数据处理的单指令多数据(SIMD及其扩展SSEx)指令。这部分指令数据非常庞大,无法一一列举,请自行参考INTEL手册。

    虚拟机扩展指令

    这部分指令包括INVEPT/INVVPID/VMCALL/VMCLEAR/VMLAUNCH/VMRESUME/VMPTRLD/VMPTRST/VMREAD/VMWRITE/VMXOFF/VMON等。 

    相关技术

    汇编器

    典型的现代汇编器(assembler)建造目标代码,由解译组语指令集的易记码(mnemonics)到操作码(OpCode),并解析符号名称(symbolic names)成为存储器地址以及其它的实体。使用符号参考是汇编器的一个重要特征,它可以节省修改程序后人工转址的乏味耗时计算。基本就是把机器码变成一些字母而已,编译的时候再把输入的指令字母替换成为晦涩难懂机器码。

    编译环境

    用汇编语言等非机器语言书写好的符号程序称为源程序,汇编语言编译器的作用是将源程序翻译成目标程序。目标程序是机器语言程序,当它被安置在内存的预定位置上后,就能被计算机的CPU处理和执行。

    汇编的调试环境总的来说比较少,也很少有非常好的编译器。编译器的选择依赖于目标处理器的类型和具体的系统平台。一般来说,功能良好的编译器用起来应当非常方便,比如,应当可以自动整理格式、语法高亮显示,集编译、链接和调试为一体,方便实用。

    对于广泛使用的个人计算机来说,可以自由选择的汇编语言编译器有MASMNASMTASMGAS、FASM、RADASM等,但大都不具备调试功能。如果是为了学习汇编语言,轻松汇编因为拥有一个完善的集成环境,是一款非常适合初学者的汇编编译器。 

    发展前景

    汇编语言是机器语言的助记符,相对于比枯燥的机器代码易于读写、易于调试和修改,同时优秀的汇编语言设计者经过巧妙的设计,使得汇编语言汇编后的代码比高级语言执行速度更快,占内存空间少等优点,但汇编语言的运行速度和空间占用是针对高级语言并且需要巧妙设计,而且部分高级语言在编译后代码执行效率同样很高,所以此优点慢慢弱化。而且在编写复杂程序时具有明显的局限性,汇编语言依赖于具体的机型,不能通用,也不能在不同机型之间移植。常说汇编语言是低级语言,并不是说汇编语言要被弃之,相反,汇编语言仍然是计算机(或微机)底层设计程序员必须了解的语言,在某些行业与领域,汇编是必不可少的,非它不可适用。只是,现在计算机最大的领域为IT软件,也是我们常说的计算机应用软件编程,在熟练的程序员手里,使用汇编语言编写的程序,运行效率与性能比其它语言写的程序相对提高,但是代价是需要更长的时间来优化,如果对计算机原理及编程基础不扎实,反而增加其开发难度,实在是得不偿失,对比2010年前后的软件开发,已经是市场化的软件行业,加上高级语言的优秀与跨平台,一个公司不可以让一个团队使用汇编语言来编写所有的东西,花上几倍甚至几十倍的时间,不如使用其它语言来完成,只要最终结果不比汇编语言编写的差太多,就能抢先一步完成,这是市场经济下的必然结果。

     

    但是,迄今为止,还没有程序员敢断定汇编语言是不需要学的,同时,汇编语言(Assembly Language)是面向机器的程序设计语言,设计精湛的汇编程序员,部分已经脱离软件开发,挤身于工业电子编程中。对于功能相对小巧但硬件对语言设计要求苛刻的行业,如4位单片机,由于其容量及运算,此行业的电子工程师一般负责从开发设计电路及软件控制,主要开发语言就是汇编,c语言使用只占极少部分,而电子开发工程师是千金难求,在一些工业公司,一个核心的电子工程师比其它任何职员待遇都高,对比起来,一般电子工程师待遇是程序员的十倍以上。这种情况是因为21世纪以来,学习汇编的人虽然也不少,但是真正能学到精通的却不多,它相对于高级语言难学,难用,适用范围小,虽然简单,但是过于灵活,学习过高级语言的人去学习汇编比一开始学汇编的人难得多,但是学过汇编的人学习高级语言却很容易,简从繁易,繁从简难。对于一个全面了解微机原理的程序员,汇编语言是必修语言。

    实际应用

    随着现代软件系统越来越庞大复杂,大量经过了封装的高级语言如C/C++Pascal/Object Pascal也应运而生。这些新的语言使得程序员在开发过程中能够更简单,更有效率,使软件开发人员得以应付快速的软件开发的要求。而汇编语言由于其复杂性使得其适用领域逐步减小。但这并不意味着汇编已无用武之地。由于汇编更接近机器语言,能够直接对硬件进行操作,生成的程序与其他的语言相比具有更高的运行速度,占用更小的内存,因此在一些对于时效性要求很高的程序、许多大型程序的核心模块以及工业控制方面大量应用。 

    历史上,汇编语言曾经是非常流行的程序设计语言之一。随着软件规模的增长,以及随之而来的对软件开发进度和效率的要求,高级语言逐渐取代了汇编语言。但即便如此,高级语言也不可能完全替代汇编语言的作用。就拿Linux内核来讲,虽然绝大部分代码是用C语言编写的,但仍然不可避免地在某些关键地方使用了汇编代码。由于这部分代码与硬件的关系非常密切,即使是C语言也会显得力不从心,而汇编语言则能够很好扬长避短,最大限度地发挥硬件的性能。

    首先,汇编语言的大部分语句直接对应着机器指令,执行速度快,效率高,代码体积小,在那些存储器容量有限,但需要快速和实时响应的场合比较有用,比如仪器仪表和工业控制设备中。

    其次,在系统程序的核心部分,以及与系统硬件频繁打交道的部分,可以使用汇编语言。比如操作系统的核心程序段、I/O接口电路的初始化程序、外部设备的低层驱动程序,以及频繁调用的子程序动态连接库、某些高级绘图程序、视频游戏程序等等。

    再次,汇编语言可以用于软件的加密和解密、计算机病毒的分析和防治,以及程序的调试和错误分析等各个方面。

    最后,通过学习汇编语言,能够加深对计算机原理和操作系统等课程的理解。通过学习和使用汇编语言,能够感知、体会和理解机器的逻辑功能,向上为理解各种软件系统的原理,打下技术理论基础;向下为掌握硬件系统的原理,打下实践应用基础。

    附注:寄存器和内存模型

    学习汇编语言,首先必须了解两个知识点:寄存器和内存模型。

    先来看寄存器。CPU 本身只负责运算,不负责储存数据。数据一般都储存在内存之中,CPU 要用的时候就去内存读写数据。但是,CPU 的运算速度远高于内存的读写速度,为了避免被拖慢,CPU 都自带一级缓存和二级缓存。基本上,CPU 缓存可以看作是读写速度较快的内存。

    但是,CPU 缓存还是不够快,另外数据在缓存里面的地址是不固定的,CPU 每次读写都要寻址也会拖慢速度。因此,除了缓存之外,CPU 还自带了寄存器(register),用来储存最常用的数据。也就是说,那些最频繁读写的数据(比如循环变量),都会放在寄存器里面,CPU 优先读写寄存器,再由寄存器跟内存交换数据。

    寄存器不依靠地址区分数据,而依靠名称。每一个寄存器都有自己的名称,我们告诉 CPU 去具体的哪一个寄存器拿数据,这样的速度是最快的。有人比喻寄存器是 CPU 的零级缓存。

    1、寄存器的种类

    早期的 x86 CPU 只有8个寄存器,而且每个都有不同的用途。现在的寄存器已经有100多个了,都变成通用寄存器,不特别指定用途了,但是早期寄存器的名字都被保存了下来。

    EAX

    EBX

    ECX

    EDX

    EDI

    ESI

    EBP

    ESP

    上面这8个寄存器之中,前面七个都是通用的。ESP 寄存器有特定用途,保存当前 Stack 的地址。

    我们常常看到 32位 CPU、64位 CPU 这样的名称,其实指的就是寄存器的大小。32 位 CPU 的寄存器大小就是4个字节。

    2、内存模型:Heap

    寄存器只能存放很少量的数据,大多数时候,CPU 要指挥寄存器,直接跟内存交换数据。所以,除了寄存器,还必须了解内存怎么储存数据。

    程序运行的时候,操作系统会给它分配一段内存,用来储存程序和运行产生的数据。这段内存有起始地址和结束地址,比如从0x1000到0x8000,起始地址是较小的那个地址,结束地址是较大的那个地址

    程序运行过程中,对于动态的内存占用请求(比如新建对象,或者使用malloc命令),系统就会从预先分配好的那段内存之中,划出一部分给用户,具体规则是从起始地址开始划分(实际上,起始地址会有一段静态数据,这里忽略)。举例来说,用户要求得到10个字节内存,那么从起始地址0x1000开始给他分配,一直分配到地址0x100A,如果再要求得到22个字节,那么就分配到0x1020。

    这种因为用户主动请求而划分出来的内存区域,叫做 Heap(堆)。它由起始地址开始,从低位(地址)向高位(地址)增长。Heap 的一个重要特点就是不会自动消失,必须手动释放,或者由垃圾回收机制来回收。

    3、内存模型:Stack

    除了 Heap 以外,其他的内存占用叫做 Stack(栈)。简单说,Stack 是由于函数运行而临时占用的内存区域

    请看下面的例子。

    int main(){int a=2;int b=3;}

    上面代码中,系统开始执行main函数时,会为它在内存里面建立一个帧(frame),所有main的内部变量(比如a和b)都保存在这个帧里面。main函数执行结束后,该帧就会被回收,释放所有的内部变量,不再占用空间。

    如果函数内部调用了其他函数,会发生什么情况?

    int main(){int a=2;int b=3;return add_a_and_b(a,b);}

    上面代码中,main函数内部调用了add_a_and_b函数。执行到这一行的时候,系统也会为add_a_and_b新建一个帧,用来储存它的内部变量。也就是说,此时同时存在两个帧:main和add_a_and_b。一般来说,调用栈有多少层,就有多少帧。

    等到add_a_and_b运行结束,它的帧就会被回收,系统会回到函数main刚才中断执行的地方,继续往下执行。通过这种机制,就实现了函数的层层调用,并且每一层都能使用自己的本地变量。

    所有的帧都存放在 Stack,由于帧是一层层叠加的,所以 Stack 叫做栈。生成新的帧,叫做"入栈",英文是 push;栈的回收叫做"出栈",英文是 pop。Stack 的特点就是,最晚入栈的帧最早出栈(因为最内层的函数调用,最先结束运行),这就叫做"后进先出"的数据结构。每一次函数执行结束,就自动释放一个帧,所有函数执行结束,整个 Stack 就都释放了。

    Stack 是由内存区域的结束地址开始,从高位(地址)向低位(地址)分配。比如,内存区域的结束地址是0x8000,第一帧假定是16字节,那么下一次分配的地址就会从0x7FF0开始;第二帧假定需要64字节,那么地址就会移动到0x7FB0。

    汇编语言保留字

    保留字(reserved words)有特殊意义并且只能在其正确的上下文中使用。默认情况下,保留字是没有大小写之分的。比如,MOV 与 mov、Mov 是相同的。

    保留字有不同的类型:

    • 指令助记符,如 MOV、ADD 和 MUL。
    • 寄存器名称。
    • 伪指令,告诉汇编器如何汇编程序。(不是机器指令)
    • 属性,提供变量和操作数的大小与使用信息。例如 BYTE 和 WORD。
    • 运算符,在常量表达式中使用。
    • 预定义符号,比如 @data,它在汇编时返回常量的整数值。

    下表是常用的保留字列表。

    $ PARITY? DWORD STDCALL
    ? PASCAL FAR SWORD
    @B QWORD FAR16 SYSCALL
    @F REAL4 FORTRAN TBYTE
    ADDR REAL8 FWORD VARARG
    BASIC REAL10 NEAR WORD
    BYTE SBYTE NEAR16 ZERO?
    C SDORD OVERFLOW?  
    CARRY? SIGN?    

    伪指令

    DW 定义字(2字节).

    PROC 定义过程.

    ENDP 过程结束.

    SEGMENT 定义段.

    ASSUME 建立段寄存器寻址.

    ENDS 段结束.

    END 程序结束.

    伪指令 (directive) 是嵌入源代码中的命令,由汇编器识别和执行。伪指令不在运行时执行,但是它们可以定义变量、宏和子程序;为内存段分配名称,执行许多其他与汇编器相关的日常任务。

    默认情况下,伪指令不区分大小写。例如,.data,.DATA 和 .Data 是相同的。

    下面的例子有助于说明伪指令和指令的区别。DWORD 伪指令告诉汇编器在程序中为一个双字变量保留空间。另一方面,MOV 指令在运行时执行,将 myVar 的内容复制到 EAX 寄存器中:

    myVar DWORD 26
    mov eax,myVar

    尽管 Intel 处理器所有的汇编器使用相同的指令集,但是通常它们有着不同的伪指令。比如,Microsoft 汇编器的 REPT 伪指令对其他一些汇编器就是无法识别的。

    定义段

    汇编器伪指令的一个重要功能是定义程序区段,也称为段 (segment)。程序中的段具有不同的作用。如下面的例子,一个段可以用于定义变量,并用 .DATA 伪指令进行标识:

    .data

    .CODE 伪指令标识的程序区段包含了可执行的指令:

    .code

    .STACK 伪指令标识的程序区段定义了运行时堆栈,并设置了其大小:

    .stack 100h

    指令

    指令(instruction)是一种语句,它在程序汇编编译时变得可执行。汇编器将指令翻译为机器语言字节,并且在运行时由 CPU 加载和执行。

    一条指令有四个组成部分:

    • 标号(可选)
    • 指令助记符(必需)
    • 操作数(通常是必需的)
    • 注释(可选)

    不同部分的位置安排如下所示:

    [label: ] mnemonic [operands] [;comment]

    现在分别了解每个部分,先从标号字段开始。

    1) 标号

    标号(label)是一种标识符,是指令和数据的位置标记。标号位于指令的前端,表示指令的地址。同样,标号也位于变量的前端,表示变量的地址。标号有两种类型:数据标号和代码标号。

    数据标号标识变量的位置,它提供了一种方便的手段在代码中引用该变量。比如,下面定义了一个名为 count 的变量:

    count DWORD 100

    汇编器为每个标号分配一个数字地址。可以在一个标号后面定义多个数据项。在下面的例子中,array 定义了第一个数字(1024)的位置,其他数字在内存中的位置紧随其后:

    array DWORD 1024, 2048
    DWORD 4096, 8192

    程序代码区(指令所在区段)的标号必须用冒号(:)结束。代码标号用作跳转和循环指令的目标。例如,下面的 JMP 指令创建一个循环,将程序控制传递给标号 target 标识的位置:

    target:
    mov ax,bx
    ...
    jmp target

    代码标号可以与指令在同一行上,也可以自己独立一行:

    L1: mov ax, bx
    L2 :

    标号命名规则要求,只要每个标号在其封闭子程序页中是唯一的,那么就可以多次使用相同的标号。

    2) 指令助记符

    指令助记符(instruction mnemonic)是标记一条指令的短单词。在英语中,助记符是帮助记忆的方法。相似地,汇编语言指令助记符,如 mov, add 和 sub,给出了指令执行操作类型的线索。下面是一些指令助记符的例子:

    助记符 说明 助记符 说明
    MOV 传送(分配)数值 MUL 两个数值相乘
    ADD 两个数值相加 JMP 跳转到一个新位置
    SUB 从一个数值中减去另一个数值 CALL 调用一个子程序

    3) 操作数

    操作数是指令输入输出的数值。汇编语言指令操作数的个数范围是 0〜3 个,每个操作数可以是寄存器、内存操作数、整数表达式和输入输岀端口。
    生成内存操作数有不同的方法,比如,使用变量名、带方括号的寄存器等。变量名暗示了变量地址,并指示计算机使用给定地址的内存内容。下表列出了一些操作数示例:

    示例 操作数类型 示例  操作数类型
    96  整数常量 eax 寄存器
    2+4 整数表达式 count 内存

    现在来考虑一些包含不同个数操作数的汇编语言指令示例。比如,STC 指令没有操作数:

    stc ;进位标志位置 1

    INC 指令有一个操作数:

    inc eax ;EAX 加 1

    MOV 指令有两个操作数:

    mov count, ebx ;将 EBX 传送给变量 count

    操作数有固有顺序。当指令有多个操作数时,通常第一个操作数被称为目的操作数,第二个操作数被称为源操作数(source operand)。

    一般情况下,目的操作数的内容由指令修改。比如,在 mov 指令中,数据就是从源操作数复制到目的操作数。

    IMUL 指令有三个操作数,第一个是目的操作数,第二个和第三个是进行乘法的源操作数:

    imul eax,ebx,5

    在上例中,EBX 与 5 相乘,结果存放在 EAX 寄存器中。

    4) 注释

    注释是程序编写者与阅读者交流程序设计信息的重要途径。程序清单的开始部分通常包含如下信息:

    • 程序目标的说明
    • 程序创建者或修改者的名单
    • 程序创建和修改的日期
    • 程序实现技术的说明

    注释有两种指定方法:

    • 单行注释,用分号(;)开始。汇编器将忽略在同一行上分号之后的所有字符。
    • 块注释,用 COMMENT 伪指令和一个用户定义的符号开始。汇编器将忽略其后所有的文本行,直到相同的用户定义符号出现为止。

    示例如下:

    COMMENT !
    This line is a comment.
    This line is also a comment.
    !

    其他符号也可以使用,只要该符号不出现在注释行中:

    COMMENT &
    This line is a comment.
    This line is also a comment.
    &

    当然,程序员应该在整个程序中提供注释,尤其是代码意图不太明显的地方。

    5) NOP(空操作)指令

    最安全(也是最无用)的指令是 NOP(空操作)。它在程序空间中占有一个字节,但是不做任何操作。它有时被编译器和汇编器用于将代码对齐到有效的地址边界

    在下面的例子中,第一条指令 MOV 生成了 3 字节的机器代码。NOP 指令就把第三条指令的地址对齐到双字边界(4 的偶数倍)

    00000000 66 8B C3 mov ax,bx
    00000003 90 nop ;对齐下条指令
    00000004 8B D1 mov edx,ecx

    x86 处理器被设计为从双字的偶数倍地址处加载代码和数据,这使得加载速度更快。

    展开全文
  • x86汇编指令集大全(带注释)

    万次阅读 多人点赞 2018-03-07 10:37:56
    汇编指令集太多,如果不用就会忘记,所以将i处理器官方的指令集大全写到博客上,有需要的人可以参考一下!X86和X87汇编指令大全(有注释) ---------- 一、数据传输指令 -----------------------------------------...

    汇编指令集太多,如果不用就会忘记,所以将i处理器官方的指令集大全写到博客上,有需要的人可以参考一下!

    X86和X87汇编指令大全(有注释)  
    ---------- 一、数据传输指令 ----------------------------------------------------  
    它们在存贮器和寄存器、寄存器和输入输出端口之间传送数据.  
    1. 通用数据传送指令.  
        MOV     传送字或字节.  
        MOVSX   先符号扩展,再传送.  
        MOVZX   先零扩展,再传送.  
        PUSH    把字压入堆栈.  
        POP     把字弹出堆栈.  
        PUSHA   把AX,CX,DX,BX,SP,BP,SI,DI依次压入堆栈.  
        POPA    把DI,SI,BP,SP,BX,DX,CX,AX依次弹出堆栈.  
        PUSHAD  把EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI依次压入堆栈.  
        POPAD   把EDI,ESI,EBP,ESP,EBX,EDX,ECX,EAX依次弹出堆栈.  
        BSWAP   交换32位寄存器里字节的顺序  
        XCHG    交换字或字节.(至少有一个操作数为寄存器,段寄存器不可作为操作数)  
        CMPXCHG 比较并交换操作数.(第二个操作数必须为累加器AL/AX/EAX)  
        XADD    先交换再累加.(结果在第一个操作数里)  
        XLAT    字节查表转换.----BX指向一张256字节的表的起点,AL为表的索引值(0-255,即0-FFH);返回AL为查表结果.([BX+AL]->AL)  
    2. 输入输出端口传送指令.  
        IN      I/O端口输入. ( 语法: IN   累加器,    {端口号│DX} )  
        OUT     I/O端口输出. ( 语法: OUT {端口号│DX},累加器 )输入输出端口由立即方式指定时,    其范围是 0-255; 由寄存器 DX 指定时,其范围是    0-65535.  
    3. 目的地址传送指令.  
        LEA     装入有效地址.例: LEA DX,string ;把偏移地址存到DX.  
        LDS     传送目标指针,把指针内容装入DS.例: LDS SI,string   ;把段地址:偏移地址存到DS:SI.  
        LES     传送目标指针,把指针内容装入ES.例: LES DI,string   ;把段地址:偏移地址存到ES:DI.  
        LFS     传送目标指针,把指针内容装入FS.例: LFS DI,string   ;把段地址:偏移地址存到FS:DI.  
        LGS     传送目标指针,把指针内容装入GS.例: LGS DI,string   ;把段地址:偏移地址存到GS:DI.  
        LSS     传送目标指针,把指针内容装入SS.例: LSS DI,string   ;把段地址:偏移地址存到SS:DI.  
    4. 标志传送指令.  
        LAHF    标志寄存器传送,把标志装入AH.  
        SAHF    标志寄存器传送,把AH内容装入标志寄存器.  
        PUSHF   标志入栈.  
        POPF    标志出栈.  
        PUSHD   32位标志入栈.  
        POPD    32位标志出栈.  
    ---------- 二、算术运算指令 ----------------------------------------------------  
        ADD     加法.  
        ADC     带进位加法.  
        INC     加 1.  
        AAA     加法的ASCII码调整.  
        DAA     加法的十进制调整.  
        SUB     减法.  
        SBB     带借位减法.  
        DEC     减 1.  
        NEG     求反(以    0 减之).  
        CMP     比较.(两操作数作减法,仅修改标志位,不回送结果).  
        AAS     减法的ASCII码调整.  
        DAS     减法的十进制调整.  
        MUL     无符号乘法.结果回送AH和AL(字节运算),或DX和AX(字运算),  
        IMUL    整数乘法.结果回送AH和AL(字节运算),或DX和AX(字运算),  
        AAM     乘法的ASCII码调整.  
        DIV     无符号除法.结果回送:商回送AL,余数回送AH, (字节运算);或 商回送AX,余数回送DX, (字运算).  
        IDIV    整数除法.结果回送:商回送AL,余数回送AH, (字节运算);或 商回送AX,余数回送DX, (字运算).  
        AAD     除法的ASCII码调整.  
        CBW     字节转换为字. (把AL中字节的符号扩展到AH中去)  
        CWD     字转换为双字. (把AX中的字的符号扩展到DX中去)  
        CWDE    字转换为双字. (把AX中的字符号扩展到EAX中去)  
        CDQ     双字扩展. (把EAX中的字的符号扩展到EDX中去)  
    ---------- 三、逻辑运算指令 ----------------------------------------------------  
        AND     与运算.  
        OR      或运算.  
        XOR     异或运算.  
        NOT     取反.  
        TEST    测试.(两操作数作与运算,仅修改标志位,不回送结果).  
        SHL     逻辑左移.  
        SAL     算术左移.(=SHL)  
        SHR     逻辑右移.  
        SAR     算术右移.(=SHR)  
        ROL     循环左移.  
        ROR     循环右移.  
        RCL     通过进位的循环左移.  
        RCR     通过进位的循环右移.  
                  以上八种移位指令,其移位次数可达255次.  
                  移位一次时, 可直接用操作码. 如 SHL AX,1.  
                  移位>1次时, 则由寄存器CL给出移位次数.  
                  如 MOV CL,04   SHL AX,CL  
    ---------- 四、串指令 ----------------------------------------------------------  
                  DS:SI 源串段寄存器 :源串变址.  
                  ES:DI 目标串段寄存器:目标串变址.  
                  CX 重复次数计数器.  
                  AL/AX 扫描值.  
                  D标志   0表示重复操作中SI和DI应自动增量; 1表示应自动减量.  
                  Z标志   用来控制扫描或比较操作的结束.  
        MOVS    串传送.( MOVSB 传送字符. MOVSW 传送字. MOVSD 传送双字. )  
        CMPS    串比较.( CMPSB 比较字符. CMPSW 比较字. )  
        SCAS    串扫描.把AL或AX的内容与目标串作比较,比较结果反映在标志位.  
        LODS    装入串.把源串中的元素(字或字节)逐一装入AL或AX中.( LODSB 传送字符. LODSW 传送字.    LODSD 传送双字. )  
        STOS    保存串.是LODS的逆过程.  
        REP         当CX/ECX<>0时重复.  
        REPE/REPZ   当ZF=1或比较结果相等,且CX/ECX<>0时重复.  
        REPNE/REPNZ 当ZF=0或比较结果不相等,且CX/ECX<>0时重复.  
        REPC        当CF=1且CX/ECX<>0时重复.  
        REPNC       当CF=0且CX/ECX<>0时重复.  
    ---------- 五、程序转移指令 ----------------------------------------------------  
    1. 无条件转移指令 (长转移)  
        JMP         无条件转移指令  
        CALL        过程调用  
        RET/RETF    过程返回.  
    2. 条件转移指令   (短转移,-128到+127的距离内)( 当且仅当(SF XOR OF)=1时,OP1<OP2 )  
        JA/JNBE     不小于或不等于时转移.  
        JAE/JNB     大于或等于转移.  
        JB/JNAE     小于转移.  
        JBE/JNA     小于或等于转移.  
            以上四条,测试无符号整数运算的结果(标志C和Z).  
        JG/JNLE     大于转移.  
        JGE/JNL     大于或等于转移.  
        JL/JNGE     小于转移.  
        JLE/JNG     小于或等于转移.  
            以上四条,测试带符号整数运算的结果(标志S,O和Z).  
        JE/JZ       等于转移.  
        JNE/JNZ     不等于时转移.  
        JC          有进位时转移.  
        JNC         无进位时转移.  
        JNO         不溢出时转移.  
        JNP/JPO     奇偶性为奇数时转移.  
        JNS         符号位为 "0" 时转移.  
        JO          溢出转移.  
        JP/JPE      奇偶性为偶数时转移.  
        JS          符号位为 "1" 时转移.  
    3. 循环控制指令(短转移)  
        LOOP            CX不为零时循环.  
        LOOPE/LOOPZ     CX不为零且标志Z=1时循环.  
        LOOPNE/LOOPNZ   CX不为零且标志Z=0时循环.  
        JCXZ            CX为零时转移.  
        JECXZ           ECX为零时转移.  
    4. 中断指令  
        INT         中断指令  
        INTO        溢出中断  
        IRET        中断返回  
    5. 处理器控制指令  
        HLT         处理器暂停,  直到出现中断或复位信号才继续.  
        WAIT        当芯片引线TEST为高电平时使CPU进入等待状态.  
        ESC         转换到外处理器.  
        LOCK        封锁总线.  
        NOP         空操作.  
        STC         置进位标志位.  
        CLC         清进位标志位.  
        CMC         进位标志取反.  
        STD         置方向标志位.  
        CLD         清方向标志位.  
        STI         置中断允许位.  
        CLI         清中断允许位.  
    ---------- 六、伪指令 ----------------------------------------------------------  
        DW          定义字(2字节).  
        PROC        定义过程.  
        ENDP        过程结束.  
        SEGMENT     定义段.  
        ASSUME      建立段寄存器寻址.  
        ENDS        段结束.  
        END         程序结束.  
    ---------- 七、处理机控制指令:标志处理指令 ------------------------------------  
        CLC     进位位置0指令  
        CMC     进位位求反指令  
        STC     进位位置为1指令  
        CLD     方向标志置1指令  
        STD     方向标志位置1指令  
        CLI     中断标志置0指令  
        STI     中断标志置1指令  
        NOP     无操作  
        HLT     停机  
        WAIT    等待  
        ESC     换码  
        LOCK    封锁  
    ========== 浮点运算指令集 ======================================================  
    ---------- 一、控制指令(带9B的控制指令前缀F变为FN时浮点不检查,机器码去掉9B)----  
    FINIT                 初始化浮点部件                  机器码  9B DB E3  
    FCLEX                 清除异常                         机器码  9B DB E2  
    FDISI                 浮点检查禁止中断                 机器码  9B DB E1  
    FENI                  浮点检查禁止中断二            机器码  9B DB E0  
    WAIT                  同步CPU和FPU                    机器码  9B  
    FWAIT                 同步CPU和FPU                    机器码  D9 D0  
    FNOP                  无操作                          机器码  DA E9  
    FXCH                  交换ST(0)和ST(1)                机器码  D9 C9  
    FXCH ST(i)            交换ST(0)和ST(i)                机器码  D9 C1iii  
    FSTSW ax              状态字到ax                       机器码  9B DF E0  
    FSTSW   word ptr mem  状态字到mem                      机器码  9B DD mm111mmm  
    FLDCW   word ptr mem  mem到状态字                      机器码  D9 mm101mmm  
    FSTCW   word ptr mem  控制字到mem                      机器码  9B D9 mm111mmm  
      
    FLDENV  word ptr mem  mem到全环境                      机器码  D9 mm100mmm  
    FSTENV  word ptr mem  全环境到mem                      机器码  9B D9 mm110mmm  
    FRSTOR  word ptr mem  mem到FPU状态                    机器码  DD mm100mmm  
    FSAVE   word ptr mem  FPU状态到mem                    机器码  9B DD mm110mmm  
      
    FFREE ST(i)           标志ST(i)未使用                   机器码  DD C0iii  
    FDECSTP               减少栈指针1->0 2->1             机器码  D9 F6  
    FINCSTP               增加栈指针0->1 1->2             机器码  D9 F7  
    FSETPM                浮点设置保护                       机器码  DB E4  
    ---------- 二、数据传送指令 ----------------------------------------------------  
    FLDZ                  将0.0装入ST(0)                  机器码  D9 EE  
    FLD1                  将1.0装入ST(0)                  机器码  D9 E8  
    FLDPI                 将π装入ST(0)                    机器码  D9 EB  
    FLDL2T                将ln10/ln2装入ST(0)             机器码  D9 E9  
    FLDL2E                将1/ln2装入ST(0)                机器码  D9 EA  
    FLDLG2                将ln2/ln10装入ST(0)             机器码  D9 EC  
    FLDLN2                将ln2装入ST(0)                  机器码  D9 ED  
      
    FLD    real4 ptr mem  装入mem的单精度浮点数             机器码  D9 mm000mmm  
    FLD    real8 ptr mem  装入mem的双精度浮点数             机器码  DD mm000mmm  
    FLD   real10 ptr mem  装入mem的十字节浮点数             机器码  DB mm101mmm  
      
    FILD    word ptr mem  装入mem的二字节整数              机器码  DF mm000mmm  
    FILD   dword ptr mem  装入mem的四字节整数              机器码  DB mm000mmm  
    FILD   qword ptr mem  装入mem的八字节整数              机器码  DF mm101mmm  
      
    FBLD   tbyte ptr mem  装入mem的十字节BCD数            机器码  DF mm100mmm  
      
    FST    real4 ptr mem  保存单精度浮点数到mem             机器码  D9 mm010mmm  
    FST    real8 ptr mem  保存双精度浮点数到mem             机器码  DD mm010mmm  
      
    FIST    word ptr mem  保存二字节整数到mem              机器码  DF mm010mmm  
    FIST   dword ptr mem  保存四字节整数到mem              机器码  DB mm010mmm  
      
    FSTP   real4 ptr mem  保存单精度浮点数到mem并出栈      机器码  D9 mm011mmm  
    FSTP   real8 ptr mem  保存双精度浮点数到mem并出栈      机器码  DD mm011mmm  
    FSTP  real10 ptr mem  保存十字节浮点数到mem并出栈      机器码  DB mm111mmm  
      
    FISTP   word ptr mem  保存二字节整数到mem并出栈           机器码  DF mm011mmm  
    FISTP  dword ptr mem  保存四字节整数到mem并出栈           机器码  DB mm011mmm  
    FISTP  qword ptr mem  保存八字节整数到mem并出栈           机器码  DF mm111mmm  
      
    FBSTP  tbyte ptr mem  保存十字节BCD数到mem并出栈     机器码  DF mm110mmm  
      
    FCMOVB                ST(0),ST(i) <时传送              机器码  DA C0iii  
    FCMOVBE               ST(0),ST(i) <=时传送             机器码  DA D0iii  
    FCMOVE                ST(0),ST(i) =时传送             机器码  DA C1iii  
    FCMOVNB               ST(0),ST(i) >=时传送             机器码  DB C0iii  
    FCMOVNBE              ST(0),ST(i) >时传送              机器码  DB D0iii  
    FCMOVNE               ST(0),ST(i) !=时传送            机器码  DB C1iii  
    FCMOVNU               ST(0),ST(i) 有序时传送        机器码  DB D1iii  
    FCMOVU                ST(0),ST(i) 无序时传送        机器码  DA D1iii  
    ---------- 三、比较指令   --------------------------------------------------------  
    FCOM                  ST(0)-ST(1)                      机器码  D8 D1  
    FCOMI                 ST(0),ST(i)  ST(0)-ST(1)         机器码  DB F0iii  
    FCOMIP                ST(0),ST(i)  ST(0)-ST(1)并出栈   机器码  DF F0iii  
    FCOM   real4 ptr mem  ST(0)-实数mem                      机器码  D8 mm010mmm  
    FCOM   real8 ptr mem  ST(0)-实数mem                      机器码  DC mm010mmm  
      
    FICOM   word ptr mem  ST(0)-整数mem                      机器码  DE mm010mmm  
    FICOM  dword ptr mem  ST(0)-整数mem                      机器码  DA mm010mmm  
    FICOMP  word ptr mem  ST(0)-整数mem并出栈               机器码  DE mm011mmm  
    FICOMP dword ptr mem  ST(0)-整数mem并出栈               机器码  DA mm011mmm  
      
    FTST                  ST(0)-0                          机器码  D9 E4  
    FUCOM  ST(i)          ST(0)-ST(i)                      机器码  DD E0iii  
    FUCOMP ST(i)          ST(0)-ST(i)并出栈                   机器码  DD E1iii  
    FUCOMPP               ST(0)-ST(1)并二次出栈             机器码  DA E9  
    FXAM                  ST(0)规格类型                    机器码  D9 E5  
    ---------- 四、运算指令   --------------------------------------------------------  
    FADD                  把目的操作数 (直接接在指令后的变量或堆栈缓存器) 与来源操作数 (接在目的操作数后的变量或堆栈缓存器)  相加,并将结果存入目的操作数  
    FADDP  ST(i),ST       这个指令是使目的操作数加上 ST  缓存器,并弹出 ST 缓存器,而目的操作数必须是堆栈缓存器的其中之一,最后不管目的操作数为何,经弹出一次后,目的操作数会变成上一个堆栈缓存器了  
    FIADD                 FIADD 是把 ST   加上来源操作数,然后再存入 ST 缓存器,来源操作数必须是字组整数或短整数形态的变数  
      
    FSUB                  减  
    FSUBP  
    FSUBR                 减数与被减数互换  
    FSUBRP  
    FISUB  
    FISUBR  
      
    FMUL                  乘  
    FMULP  
    FIMUL  
      
    FDIV                  除  
    FDIVP  
    FDIVR  
    FDIVRP  
    FIDIV  
    FIDIVR  
      
    FCHS                  改变 ST 的正负值  
      
    FABS                  把 ST  之值取出,取其绝对值后再存回去。  
      
    FSQRT                 将 ST  之值取出,开根号后再存回去。  
      
    FSCALE                这个指令是计算 ST*2^ST(1)之值,再把结果存入 ST 里而 ST(1)   之值不变。ST(1)  必须是在 -32768 到 32768 (-215 到 215 )之间的整数,如果超过这个范围计算结果无法确定,如果不是整数 ST(1)    会先向零舍入成整数再计算。所以为安全起见,最好是由字组整数载入到 ST(1) 里。  
      
    FRNDINT               这个指令是把 ST 的数值舍入成整数,FPU    提供四种舍入方式,由 FPU 的控制字组(control    word)中的 RC 两个位决定  
                              RC    舍入控制  
                              00    四舍五入  
                              01    向负无限大舍入  
                              10    向正无限大舍入  
                              11    向零舍去  
    ================================================================================  

     

     

     

    展开全文
  • 汇编】新_Windows和MacOS配置8086汇编语言环境

    千次阅读 多人点赞 2020-04-05 17:18:28
    尝试3.1 编写代码3.2 挂载目录挂载切换虚拟磁盘简单指令3.3 开始汇编确保环境汇编和链接3.4 使用DEBUG工具启动常用命令4. 示例代码截图 1. 获取工具 Windows和Mac都下载这个,仅Dos环境有区别,汇编时用到的文件是...

    写在前面:大家好K。首先为你点进这篇有趣的文章点赞👍!文章在撰写过程中难免有疏漏和错误,欢迎你在下方留言指出文章的不足之处;如果觉得这篇文章对你有用,也欢迎你点赞和留下你的评论。更多内容请点进👉我的博客K。👈阅览。

    1. 获取工具

    Windows和Mac都下载这个,仅Dos环境有区别,汇编时用到的文件是通用的

    链接: https://pan.baidu.com/s/1KWMNPnrbNGPytZ9FZNM8GA 密码: 0mp7

    2. 安装Dos环境

    下载完成后,Windows根据dosbox安装及dosbox下masm的使用.doc安装

    Mac直接点击Boxer.app即可运行Dos环境(后文将Boxer和dosbox统称为dosbox),不推荐用mac版的dosbox,版本过于久,且不能粘贴(不可忍)

    注意,其他文件后面需要用到(特别留意MASM文件夹,里面有MASM.EXE和LINK.EXE汇编时用),妥善保存

    3. 尝试

    3.1 编写代码

    用任意编辑器写完代码,将后缀名改为.asm

    把源代码文件放到MASM文件夹中,使得源代码文件与MASM.EXE、LINK.EXE两程序在同一层

    3.2 挂载目录

    挂载

    Dosbox是虚拟机环境,想要在其中访问本机的文件,需要将本机的文件夹挂载到dosbox中

    mounnt c d:\MASM5\MASM是将本机D盘中的\MASM5\MASM挂载到dosbox的C盘

    切换虚拟磁盘

    Dosbox双击打开默认是在Z盘中,执行完上面的挂载操作后,键入命令c:切换到doxbox的C盘中,此时操作C盘中的文件,(例)即是操作本机中d:\MASM5\MASM中的文件

    简单指令

    更多命令请查DOS命令

    切换磁盘:盘符:。例,c:切换到C盘

    挂载:mount 盘符 本机文件夹。例,mount c d:\MASM5\将本机中d:\MASM5\挂载到dosbox的C盘中

    卸载:unmount 盘符。例,先离开想要卸载的磁盘(切换到其他磁盘),再执行unmount c卸载挂载在C盘上的文件夹

    切换目录:cd 目标路径.是当前文件夹,..是上一文件夹。例,cd ./MASM切换到当前你文件夹中的MASM文件夹

    列出所有文件:dir。例,当前在C:\MASM5\中年,输入dir将列出当前文件夹中的所有文件和文件夹

    3.3 开始汇编

    确保环境

    确保编写的汇编源代码文件在MASM文件夹中,即与DEBUG.EXE、MASM.EXE、LINK.EXE在同一文件夹内。若没有,快把源文件拿过来放一起

    汇编和链接

    作为初学者,先不关系具体发生了什么

    两条命令

    masm 文件名;
    link 文件名;
    

    这就是要求把源代码文件和这些工具放在同一个文件夹内的原因,可以不用写全路径,直接输名字即可使用

    第一行,运行结果得到中间文件XXX.OBJ。注意1.不加扩展名,2.加分号(为了快速处理)。不加分号需要手动配置一些参数

    第二行,运行结果得到可执行文件XXX.EXE。注意1.不加扩展名,2.加分号(为了快速处理)。不加分号需要手动配置一些参数

    3.4 使用DEBUG工具

    使用DEBUG,可以查看程序运行时的内存和寄存器的数据

    启动

    命令:debug XXX.EXE,注意加上.exe扩展名

    常用命令

    点击这里学习更多debug指令

    查看内存:d,在后面加十六进制偏移地址值,可以查看相应地址的内存

    查看寄存器:r

    单步执行:t,输入一次执行一步,并显示寄存器值

    快速执行:g,不打断执行之后的代码

    退出:q,到达程序最后后,需手动退出。继续单步调试会执行后面的代码

    4. 示例

    代码

    code segment
        assume cs:code
    start:
        ; 给ax寄存器传值,十六进制数b
        mov ax, 0bh
    
        mov ax, 4c00h ; 4c00h表示程序退出,并返回00,传递退出信息
        int 21h
    code ends
    end start
    

    截图

    1. 挂载成功后,切换到c盘,并列出当前文件夹内容
      挂载成功后,切换到c盘,并列出当前文件夹内容

    2. 汇编,两步

    链接时有无栈段警告,可忽略

    汇编

    1. 使用DEBUG示例

    执行到第5行时,AX值被修改为BH,紧接着又被修改成4C00H

    使用DEBUG示例

    展开全文
  • 汇编push和pop指令

    万次阅读 多人点赞 2019-06-01 10:16:01
    push和pop是用来操作栈的2个指令。 push寄存器:将一个寄存器中的数据入栈 ... 下面用一段汇编代码学习一下栈的操作,用masm编辑的(环境用的<<汇编语言>> 王爽的那套环境)。 assume cs:codesg ...

         ❤️强烈推荐人工智能学习网站❤️


              push和pop是用来操作栈的2个指令。 

               push寄存器:将一个寄存器中的数据入栈

               pop寄存器:出栈用一个寄存器接收数据

        

               下面用一段汇编代码学习一下栈的操作,用masm编辑的(环境用的<<汇编语言>> 王爽的那套环境)。

    assume cs:codesg     ;cs寄存器指向该程序的首地址
    
    codesg segment
        mov ax,1000H     ;将1000H送入寄存器ax,相当于ax=1000H
        mov ss,ax
        mov sp,0010H
    
        mov ax,001AH    ;将ax,bx赋值
        mov bx,001BH
    
        push ax
        push bx         ;将ax,bx入栈
    
        sub ax,ax   ;sub为减法指令,相当于ax=ax-ax
        sub bx,bx
    
        pop ax          //将栈顶的数据送入ax,pop也有mov指令类似的功能
        pop bx
    
    codesg ends
    end

                该段代码将10000H~10000FH这段空间当栈,初始状态栈是空的。设置寄存器ax,bx的值,将ax,bx中的数据入栈,然后将ax,bx清零,从栈中恢复ax,bx原来的内容。

                ax,bx,sp,cs为寄存器,ss为段寄存器。任意时刻CPU从CS*16+IP(这里cs和ip表示该寄存器的值)单元开始执行指令,所以设置cs:codesg。任意时刻,ss*16+sp(这里ss和sp表示对应寄存器的值)对应的地址单元指向栈顶元素,所以程序里面设置ss=1000H,而不是ss=10000H。

               下面看一下单步调试的结果:

    r命令时查看当前寄存器的内容,t是单步执行命令。每一步的执行结果中,上面是对应寄存器的值,下面对应的机器指令是下一条将要执行的机器指令。每执行一条指令你都看到对应寄存器的变化。最后一条pop bx指令由于图片大小原因,我没有截出来,所以最后一行的结果只是执行pop ax,而没有执行pop bx的结果。

     

     

     

              参考资料:<<汇编语言>> 王爽

    展开全文
  • 利用DOSBox运行汇编超详细步骤!!

    万次阅读 多人点赞 2020-05-19 22:46:22
    最近学校要求用汇编写课设,笔试取消,无奈只有配置环境自己写课设了。起初是利用VS2017进行配置,但后面运行好像有些问题,就想到用DOSBox了。以下是详细步骤: 第一步:下载好相关文件,文件我放在下面链接里: ...
  • arm汇编和neon汇编

    千次阅读 2017-11-14 20:22:39
    arm汇编和neon汇编
  • GCC在C语言中内嵌汇编 asm __volatile__

    万次阅读 多人点赞 2012-11-26 22:20:05
    在内嵌汇编中,可以将C语言表达式指定为汇编指令的操作数,而且不用去管如何将C语言表达式的值读入哪个寄存器,以及如何将计算结果写回C 变量,你只要告诉程序中C语言表达式与汇编指令操作数之间的对应关系即可, ...
  • 网上的教程只能在win10中使用debug ...更多汇编及程序设计内容请访问omegaxyz.com 汇编文件 http://pan.baidu.com/s/1dE5COm9 首先,将文件下载安装DOSBox0.74注意不要安装在C盘 将下载的MASM文件(如图)复制到一个
  • 8086汇编语言讲座

    千人学习 2018-03-20 10:20:26
    关于8086汇编语言,是与计算机原理相结合的,通过汇编语言可以加深对计算机原理的掌握和理解。 另外汇编语言还是可以干成事的,比如破解,外挂等都会用到它。
  • 汇编语言

    千次阅读 2019-09-18 21:52:55
    汇编语言 汇编语言是一类语言,ARM,MIPS,X86。 汇编语言与CPU联系紧密。但是可移植性差。 Li $t1 , 1 # 把1放到t1寄存器里面 add $t0 , $t1 ,2 # 2加上ti里面的放到t0中 ...
  • 汇编语言入门教程

    千人学习 2019-12-26 10:57:49
    汇编语言入门级教程 游戏安全,游戏逆向必学的基础语言 
  • 汇编语言程序vs. 汇编程序

    千次阅读 2016-12-02 13:37:48
    汇编语言程序vs. 汇编程序@(组成原理)这是个常常被人拿来挖坑的地方。汇编语言程序就是你用汇编语言写的文本型的程序,我们说用一堆助记符来写的源代码。汇编程序是汇编阶段用来把汇编语言翻译成机器语言指令的程序...
  • 汇编和反汇编的区别

    千次阅读 2019-01-16 00:04:09
    汇编与反汇编的区别 我们先看一个图,一个c程序如何变成一个可执行程序 1.汇编 动词,指的是把汇编语言翻译成机器语言的过程。 名词,指的便是汇编语言 在linux查看.s文件(Ps:源程序为test.c)&nbsp; ...
  • 通过汇编程序理解汇编和链接过程

    千次阅读 2020-09-17 18:20:17
    通过编写汇编程序,然后分析它的汇编和链接过程,对理解汇编程序中的各种汇编器指令和各种标签很有帮助。 首先介绍以下汇编器指令和标签这两个概念,观察下面一段求最大值的汇编程序代码maxmum.s: #目的:寻找一组...
  • 汇编和反汇编的理解

    千次阅读 2018-10-22 21:15:04
    汇编语言是高级语言转换成机器码的桥梁,通过汇编语言的编译转换成机器码,计算机就可以执行程序。因为在计算机中,所有的程序都是按照机器码执行的,所以对汇编语言的理解,能够增加对底层执行的认识。 下面介绍的...
  • ARM:ARM汇编语言与基础汇编指令

    万次阅读 2017-02-19 21:51:39
    1、为什么要学习汇编语言? 1)嵌入式硬件上电的初始化代码是用汇编代码编写; 2)调试代码时,问题的解决有可能看汇编代码; 3)系统调优(提高产品整体运行效率); memcpy:C语言函数原型 :汇编代码 - 效率...
  • 关于底层知识的学习,汇编当然是绕不过,当你需要调优一小段代码时,你需要看的汇编语言。通过学习汇编语言,你能更清楚明白的了解整个计算机的计算过程,指令相关知识,对学习计算机帮助甚大。 目录: 第1章 ...
  • ARM汇编与ARM GNU汇编 区别

    千次阅读 2019-05-10 11:14:32
    一、想学汇编,at&t汇编与ARM汇编的区别? 问:想学汇编语言,因为现在用的是linux系统(ubuntu11.04),so 有一本《汇编语言程序设计》马朝晖译,可惜淘宝、当当、京东等都没货,淘宝上只有盗版的。 ARM的书倒是...
  • 嵌入式汇编(内联汇编

    千次阅读 2018-07-25 17:41:22
    嵌入式汇编基本格式: asm(&quot;汇编语句&quot; : 输出寄存器 : 输入寄存器 : 会被修改的寄存器); 输出寄存器:表示这段汇编执行完之后,哪些寄存器用于存放输出数据。 这些寄存器会分别对应一C语言...
  • MIPS汇编语言指令分类及寻址模式

    万次阅读 2016-10-04 14:53:36
    MIPS汇编语言指领分类及寻址模式一、普及一些相关概念 指令集:一个给定的计算机体系结构所包含的指令集合。 存储程序概念:多种类型的指令和数据均以数字形式存储于存储器的概念,存储程序型计算机即缘于此。1 二、...
  • 汇编学习软件推荐 - 汇编金手指

    千次阅读 2020-04-10 02:02:29
    汇编的学习只要理解底层操作即可,在调试期间很有用,开发还是使用高级语言,所以很多指令不用背,推荐一个查询的软件 这款软件可以直接查询需要的指令,有详细的介绍和使用方法 编写汇编软件:debug软件见之前的...
  • 汇编语言程序设计

    千人学习 2017-03-01 22:19:38
    汇编语言是一门低级程序设计语言,在数以千计的计算机语言中,有着不可替代的重要地位,广泛地用于开发操作系统内核、设备驱动程序等。随着近年来物联网、嵌入式系统的发展,汇编语言在行业中的地位也再次攀升,在...
  • 用gdb 查看,执行汇编代码

    万次阅读 2014-05-23 14:45:27
    用gdb 查看汇编代码, 采用disassemble 和 x 命令。 nexti, stepi 可以单步指令执行 如下例: ------------------------------------------------------------ 源代码: ----------------------------------------...
  • C语言内联汇编

    千次阅读 2018-09-26 22:06:43
    在阅读linux 源码的时候,我们会看到很多C语言内联汇编的代码。下面我们集中看看C语言内联汇编是怎么样的。 首先,我们得想想为什么会有在C语言里面内联汇编的需求。 主要有两个,一个是我们觉得在被频繁调用的函数...
  • 本文基于MDK 5.26软件,在stm32f103上进行汇编语言的实验测试;
  • win10配置汇编语言环境(王爽汇编语言环境)

    千次阅读 多人点赞 2019-03-30 16:47:20
    win10配置汇编语言环境(王爽汇编语言环境) 前言 有不少童鞋在学习“汇编语言”这门课程时,不太满足于课本上的理论知识,想要亲自上机实践一下,从而更能够更深刻的理解汇编语言的基本原理。然而,大多数同学...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 151 950
精华内容 60 780
关键字:

汇编