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

    万次阅读 多人点赞 2016-07-28 16:09:21
    标 题:汇编实验10—— 编写子程序 作 者: XHS_12302 时 间: 链 接: 实验10编写子程序 在这次实验中,我们将要编写3个子程序,通过它们来认识几个常见的问题和掌握解决这些问题的方法。同前面的所有实验一样,...

    标 题: 汇编实验10—— 编写子程序
    作 者: XHS_12302
    时 间: 2016_7_28 16:56

     

     

     

     

     

    实验10编写子程序


      在这次实验中,我们将要编写3个子程序,通过它们来认识几个常见的问题和掌握解决这些问题的方法。同前面的所有实验一样,这个实验是必须要独立完成的,在后面的课程中,将要用到这个实验中编写的3个子程序。
    1.  显示字符串
    问题
    显示字符串是现实工作中经常要用到的功能,应该编写一个通用的子程序来实现这个功能。我们应该提供灵活的调用接口,使调用者可以决定显示的位置(行、列)、内容和颜色。

    提示
    (1)  子程序的入口参数是屏幕上的行号和列号,注意在子程序内部要将它们转化为显存中的地址,首先要分析一下屏幕上的行列位置和显存地址的对应关系:
    (2)  注意保存子程序中用到的相关寄存器:
    (3)  这个子程序的内部处理和显存的结构密切相关,但是向外提供了与显存结构无关的接口。通过调用这个子程序,进行字符串的显示时可以不必了解显存的结构,为编程提供了方便。在实验中,注意体会这种设计思想。

    子程序描述
    名称:show_str
    功能:在指定的位置,用指定的颜色,显示一个用0结束的字符串。
    参数:(dh)=行号(取值范围0~24),(dl)=列号(取值范围0~79),
        (cl)=颜色,ds:si指向字符串的首地址
    返回:无
    就用举例:在屏幕的8行3列,用绿色显示data段中的字符串。

     

     

     

     

    代码:

     

    assume cs:code
       data segment
       db 'Welcome to masm!',0
       data ends
    
     code segment
       start:  mov dh,8
               mov dl,3
               mov cl,2
               mov ax,data
               mov ds,ax
               mov si,0
               call show_str
               mov ax,4c00h
               int 21h
       show_str: push dx
                 push cx
                 push ds
                 push si
    
         mov ax,0b800h
         mov es,ax
         
         mov al,160
         mul dh
         mov bx,ax
         mov al,2
         mul dl
         add bx,ax
        mov al,cl
        
             s: mov cl,[si] 
                  jcxz ok
                  mov dx,[si]
                  mov es:[bx],dx
                  mov es:[bx+1],al
                  inc si
                  add bx,2
                  loop s
    
     ok:             
      pop si
      pop ds
      pop cx
      pop dx
    ret
    code ends
    end start 

     

     

    实验截图

     

     

     

    2.  解决除法溢出的问题
    问题
    前面讲过,div指令可以做除法。当进行8位除法的时候,用al存储结果的商,ah存储结果的余数:进行16位除法的时候,用ax存储结果的商,dx存储结果的余数。可是,现在有一个问题,如果结果的商大于ah或ax所能存储的最大值,那么将如何?
    比如,下面的程序段:
     mov bh,1
     mov ax,1000
     div bh
    进行的是8位除法,结果的商为1000,而1000在ah中放不下,
    又比如,下面的程序段:
    mov ax,1000h
    mov dx,1
    mov bx,1
    div bx
    进行的是16位除法,结果的商为11000H,而11000H在ax中存放不下。
    我们在用div指令做除法的时候,很可能发生上面的情况:结果的商过大,超出了寄存器所能存储的范围。当CPU执行div等除法指令的时候。如果发生这样的情况,将引发CPU的一个内部错误。这个错误被称为:除法溢出。我们可以通过特殊的程序来处理这个错误, 这里我们不讨论这个错误的处理,这是后面的课程中要涉及的内容。

    好了,我们已经清楚了问题的所在:用div指令做除法的时候可能产生除法溢出。由于有这样的问题,在进行除法运算的时候要注意除数和被除数的值,比如1000000/10就不能用div指令来计算。那么怎么办呢?我们用下面的子程序divdw解决。


    子程序描述
    名称:divdw
    功能:进行不会产生溢出的除法运算,被除数为dword型,除数为word型,结果为dword型。
    参数:(ax)=dword型数据的低16位
        (dx)=dword型数据的高16位
        (cx)=除数
    返回:(dx)=结果的高16位,(ax)=结果的低16位
        (cx)=余数
    应用举例:计算1000000/10(F4240H/0AH)

      mov ax,4240h
      mov v dx,000fh
      mov cx,0ah
      call divdw


    提示
    给出一个公式:
    X:被除数,范围:[0,FFFF FFFF]
    N:除数,范围:[0,FFFF]
    H:X高16位,范围:[0,FFFF]
    L:X低16位,范围:[0,FFFF]
    int():描述性运算符,取商,比如:rem(38/10)=8
    rem():描述性运算符,取答数,比如:rem(38/10)=8
    公式:X/N=int(H/N)*65536+[rem(H/N)*65536+L]/N
    这个公式将可能产生溢出的除法运算:X/N,转变为多个不会产生溢出的除法运算。
    公式中,等号右边的所有除法运算都可以用div指令来做,肯定不会导致除法溢出。

    代码:

     

    assume cs:code
        code segment
        start:mov ax,4240h
              mov dx,000fh
              mov cx,0Ah
              call divdw
              mov ax,4c00H
              int 21h
    divdw:
          push ax
          mov ax,dx
          mov dx,0
          div cx
          mov bx,ax
          pop ax
          div cx
          mov cx,dx
          mov dx,bx
          ret    
        code ends
    end start

     

     

     

    程序截图:

     

    3.数值显示
    问题
    编程,将data段中的数据以十进制的形式显示出来。
    data segment
    dw 123,12666,1,8,3,38
    data ends
      这些数据在内存中都是二进制信息,标记了数值的大小。要把它们显示到屏幕上,成为我们能够读懂的信息,需要进行信息的转化。比如,数值12666,在机器中存储为二进制信息:0011000101111010B(317AH),计算机可以理解它。而我们要在显示器上读到可以理解的数值12666,我们看到的应该是一串字符:“12666”。由于 显卡遵循的是ASCII编码,为了让我们能在显示器上看到这串字符,它在机器中应以ASCII码的形式存储为:31H、32H、36H、36H、36H(字符“0”~“9”对应的ASCII码为30H~39H)。
      通过上面的分析可以看到,在概念世界中,有一个抽象的数据12666,它表示了一个数值的大小。在现实世界中它可以有多种表示形式,可以在电子机器中以高低电平(二进制)的形式存储,也可以在纸上、黑板上、屏幕上以人类的语言“12666”来书写。现在,我们面临的问题就是,要将同一抽象的数据,从一种表示形式转化为另一种表示形式。
      可见,要将数据用十进制形式显示到屏幕上,要进行两步工作:
    (1)  将用二进制信息存储的数据转变为十进制形式的字符串:
    (2)  显示十进制形式的字符串。
    第二步我们在本次实验的第一个子程序中已经实现,在这里只要调用一下show_str即可。我们来讨论第一步,因为将二进制信息转变为十进制形式的字符串也是经常要用到的功能,我们应该为它编写一个通用的子程序。


    子程序描述
    名称:dtoc
    功能:将word型数据转变为表示十进制数的字符串,字符串以0为结尾符。
    参数:(ax)=word型数据
        ds:si指向字符串的首地址
    返回:无
    应用举例:编程,将数据12666以十进制的形式在屏幕的8行3列,用绿色显示出来。
    在显示时我们调用本次实验中的第一个子程序show-str。



    提示
      下面我们对这个问题进行一下简单地分析。
    (1)  要得到字符串“12666”,就是要得到一列表示该字符的ASCII码:31H、32H、36H、36H、36H。
    十进制数码字符对应的ASCII码=十进制数码值+30H
    要得到表示十进制数的字符串,先求十进制数每位的值。
    例:对于12666,先求得每位的值:1、2、6、6、6。再将这些数分别加上30H,便得到了表示12666的ASCII码串:31H、32H、36H、36H、36H。
    (2)  那么,怎样得到每位的值呢?采用如图10.2所示的方法。

    图10.2除10取余法示意


      可见,用10除12666,共除5次,记下每次的余数,就得到了每位的值。
    (3)  综合以上分析,可得出处理过程如下:
    用12666除以10,循环5次,记下每次的余数;将每次的余数分别加30H,便得到了表示十进制数的ASCII码串,如图10.3所示。



    图10.3得到十进制每位数字字符的方法示意

     


    (4)  对(3)的质疑:
    在已知数据是12666的情况下,知道进行5次循环。可在实际问题中,数据的值是多少
    程序员并不知道,也就是说,程序员不能事先确定循环次数。
      那么,如何确定数据各位的值已经全部求出了呢?我们可以看出,只要是除到商为0,各位的值就已经全部求出。可以使用jcxz指令来实现相关的功能。

     

     

     

     

     

    代码:

     

    assume cs:code
      data segment
      db 16 dup(0)
      data ends
    
     
      code segment
        start:mov ax,12666
              mov bx,data
              mov ds,bx
              mov si,0
              call dtoc
              mov dh,8
              mov dl,3
              mov cl,2
              call show_str
              mov ax,4c00h
              int 21h
    dtoc:
           mov cx,ax    ;17
           jcxz bk
           push ax
           mov al,ah
           mov ah,0
           mov bl,10
           div bl
           mov cl,al
           mov ch,ah
           pop ax
           mov ah,ch
           div bl
           mov dl,ah
           mov dh,0
           push dx
           mov ah,cl
           jmp short dtoc   ;29
         bk:pop ax 
            add ax,30h
            mov [si],al
            
            pop ax 
            add ax,30h
            mov [si+1],al
           
            pop ax 
            add ax,30h
            mov [si+2],al
            
            pop ax 
            add ax,30h
            mov [si+3],al    ;44
            
            pop ax 
            add ax,30h
            mov [si+4],al
            mov byte ptr [si+5],0
            ret
           
         
    show_str:
         mov si,0
         mov ax,0b800h
         mov es,ax
         
         mov al,160
         mul dh
         mov bx,ax
         mov al,2
         mul dl
         add bx,ax
         mov al,cl
        
             s: mov cl,[si] 
                  jcxz ok
                  mov dx,[si]
                  mov es:[bx],dx
                  mov es:[bx+1],al
                  inc si
                  add bx,2
                  loop s
    
     ok: ret    
      code ends
    end start


    程序运行截图

     

     

    至此    实验完成    

                               题中有不足之处  希望不吝赐教

                                             文中有的 文字是借鉴别人的    除了代码和截图

                                                 完成实验参考过别的资料,在第二个实验中受过小甲鱼视频(328/2)的启发

                                                                                                   视频资料上云盘找:链接: http://pan.baidu.com/s/1nvpQiLz 密码: et5r

                                                                                                                                                                                                                                     日期:2016_7_28

    展开全文
  • 什么是汇编语言

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

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

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

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

    发展历程

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

           上面所说的计算机指的是可以执行机器指令,进行运算的机器。这是早期计算机的概念。在我们常用的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 处理器被设计为从双字的偶数倍地址处加载代码和数据,这使得加载速度更快。

    展开全文
  • 汇编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的结果。

     

     

     

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

    展开全文
  • 汇编】新_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示例

    展开全文
  • 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文件(如图)复制到一个
  • 为了理解汇编语言的编辑、汇编、连接、运行的全过程,我们不使用IDE,而是分步骤来进行: 需要工具: 1. 文本编辑器(如果有Notepad++或者UltraEdit就更好了) 2. 汇编器(如MASM.exe) 3. 连接器(对应的link....
  • arm汇编和neon汇编

    千次阅读 2017-11-14 20:22:39
    arm汇编和neon汇编
  • 8086汇编语言讲座

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

    万次阅读 2017-02-19 21:51:39
    1、为什么要学习汇编语言? 1)嵌入式硬件上电的初始化代码是用汇编代码编写; 2)调试代码时,问题的解决有可能看汇编代码; 3)系统调优(提高产品整体运行效率); memcpy:C语言函数原型 :汇编代码 - 效率...
  • 汇编语言

    千次阅读 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. 汇编程序@(组成原理)这是个常常被人拿来挖坑的地方。汇编语言程序就是你用汇编语言写的文本型的程序,我们说用一堆助记符来写的源代码。汇编程序是汇编阶段用来把汇编语言翻译成机器语言指令的程序...
  • 关于底层知识的学习,汇编当然是绕不过,当你需要调优一小段代码时,你需要看的汇编语言。通过学习汇编语言,你能更清楚明白的了解整个计算机的计算过程,指令相关知识,对学习计算机帮助甚大。 目录: 第1章 ...
  • 用gdb 查看,执行汇编代码

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

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

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

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

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

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

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

    万次阅读 2020-09-03 20:53:57
    前言: 问:什么是plan9? 答:plan9是一个很强的操作系统,但我们只需要...答:确实可以跳过plan9汇编(比如直接拿机器码反编译出intel汇编来看),但是会让阅读变得非常困难。并且在golang的基础方法中,使用了大.
  • C语言调用汇编汇编调用C语言

    万次阅读 2017-05-18 12:27:23
    1.C语言调用汇编 程序的入口是main,在main里调用汇编的函数。 在C语言中,要extern 一个函数声明即可,然后这个函数在汇编里面实现。 在汇编里面,用EXPORT 把C语言定义的函数名引进来,再开始编写函数...
  • ATT汇编

    千次阅读 多人点赞 2015-07-22 00:21:24
    很多人接触比较多的是 windows 下的 Intel 汇编,然而 unix/linux 下 or 使用 gcc 的话,用的是 ATT 汇编。(unix 最初是 AT&T 实验室中的 Ken Thompson 发明的。) Intel 汇编和 ATT 汇编使用的指令基本一样,...

空空如也

1 2 3 4 5 ... 20
收藏数 115,656
精华内容 46,262
关键字:

汇编