• 【原创】汇编语言的基本知识(二)


    五,loop指令实现循环

    1,[bx]和内存单元的描述

    (1)完整地描述一个内存单元需要2种信息:1,内存单元的地址;2,内存单元的长度

    用[0]表示内存单元的时候,0表示单元的偏移地址,段地址默认在ds中;

    [bx]同样也表示一个内存单元,它的偏移地址在bx中,段地址默认在ds中;

    2,一般用"()"来表示一个寄存器或一个内存单元中的内容

    ,3,loop指令的坐拥:1,(cx) = (cx) -1 ;2判断cx中的值,不为0则转至标号出执行程序,为0则向下执行

    #计算2的12次方
    
    assumne cs:code
    code segment
        mov ax,2
        mov cx,11
    s: add ax,ax
        loop s
        mov ax,4c00h
        int 21h
    code ends
    end

    4,在汇编源程序中,数据不能以字母开头,要在前面加0,比如A000H在汇编程序中改写为"0A000H"

    5,段前缀:在访问内存的指令中,使用:显示地指明内存单元的段地址,在汇编语言中称为段前缀

    mov ax,ds:[bx]
    mov ax,cs:[bx]
    ...
    ds: cs:等都是段前缀

    6,段前缀的使用,例:将内存ffff:0~ffff:b单元中的数据复制到0:200~0:20b单元中。

    assume cs:code
        code segment 
            mov bx,0
            mov cx,12
        s: mov ax,0ffffh
            mov ds,ax
            mov dl,[bx]
        
            mov ax,0020h
            mov ds,ax
            mov [bx],dl
            
            inc bx
            loop s
        
            mov ax,4c00h
            int 21h
    
    code ends
    end

    7,将数据,代码,栈放入不同的段

    assume cs:code ,ds:data,ss:stack
    data segment
        dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987
    data ends
    stack segment
        dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
    stack ends
    code segment
    start:mov ax,stack
        mov ss,ax
        mov sp,20h
        mov ax,data
        mov ds,ax
        mov bx,0
        mov cx,8
    s: push [bx]
        add bx,2
        loop s0
        mov ax,4c00h
        int 21h
    code ends
    end start

    六,更灵活的定位内存地址

    1,逻辑指令 and和or

    #按位进行与运算
    mov al,01100011B
    and  al,00111011B
    结果为:al=00100011B
    
    #按位进行或运算
    mov al,01100011B
    or    al,00111011B
    结果为:al=01111011B

    2,以字符形式给出数据:ASCLL码

    mov al,'a' 相当于执行 mov al,61H, 'a'的asciil码的16进制为61

    3,用[bx+idata]的方式进行数组的处理,inc指令

    举例:将datasg中定义的第一个字符串转化为大写,第二个字符串转化为小写

    assume cs:codesg ds:datasg
    
    datasg segment
        db 'BiSiC'
        db 'MinIX'
    datasg ends
    codesg segment
        start:mov ax,datasg
        mov ds,ax
        mov bx,0
        mov cx,5    
    s: mov al,[bx]
        and al,11011111b
        mov [bx],al
        mov al,[5+bx]
        or al,00100000b
        mov [5+bx],al
       inc bx
        loop s
    
    codesg ends
    
    end start

    4,不同的寻址方式的灵活应用

    [idata] 1个常量,直接定位一个内存单元

    [bx] 1个变量,间接定位一个内存单元

    [bx+idata] 1个变量+1个常量

    [bx+si] 2个变量

    [bx+si+idata] 2个变量+1个常量

     5,程序中经常需要进行数据的暂存,需要一个通用的方案解决寄存器数量有限的问题

    (1)当寄存器不够用的时候,就需要用内存单元保存数据了;

    (2)一般来说,在需要暂存数据的时候,我们都应该使用栈。

    七,数据处理的2个基本问题

    1,用reg表示1个寄存器,sreg表示一个段寄存器

    reg包括:ax bx cx dx al bl cl dl ah bh ch dh sp bp si di

    sreg包括:ds cs es ss

    这4个寄存器可以单个出现:bx si di bp

    2,数据位置的表达
    (1)立即数:对于直接包含在机器指令中的数据(执行前在cpu的指令缓冲器中)

    mov ax,1
    add bx,2000h
    or bx,00010000b
    mov al, 'a'

    (2)寄存器:指令要处理的数据再寄存器中,需要给出相应的寄存器名

    mov ax,bx
    mov ds,ax
    push bx
    mov ds:[0],bx
    push ds
    mov ss,ax
    mov sp,ax

    (3)段地址(SA)和偏移地址(EA):要处理的数据再内存中,用[X]的格式给出EA

    #段地址默认在ds中
    mov ax,[0]
    mov ax,[di]
    mov ax,[bx+8]
    mov ax,[bx+si]
    mov ax,[bx+si+8]
    
    #段地址默认在ss中
    mov ax,[bp]
    mov ax,[bp+8]
    mov ax,[bp+si]
    mov ax,[bp+si+8]
    
    #显示给出段地址的寄存器
    mov ax,ds:[bp]
    mov ax,es:[bx]
    mov ax,ss:[bx+si]
    mov ax,cs:[bx+si+8]

    3,指令要处理的数据有多长

     cpu指令可以处理两种尺寸的数据:byte(字节)和word(子)。所以在机器指令中要指明是字操作还是字节操作

    (1)通过寄存器名指明要处理的尺寸

    (2)没有寄存器名存在的情况下,用操作符X ptr指明内存单元的长度

    mov word ptr ds:[0],1
    mov byte ptr ds:[0],1

    (3)其他方法:push [1000H]就不用指明,因为push指令只进行word字操作

    4,div指令:除法指令

    1,除数:
    有8位和16位2种,在一个reg或内存单元中
    
    2,被除数:
    默认放在AX或DX和AX中
    
    3,结果:
    如果除数为8位,则AL存储商,AH存储余数,
    如果除数为16位,则AX存储商,DX存储余数

    5,伪指令dd

    dd定义字节型,dw定义字型

    dd定义双字型

    6,dup是一个操作数,在汇编语言中同db dw dd等一样,也是由编译器识别处理的符号。与db dw dd配合使用,用来进行数据的重复,比如

    db 3 dup (0)  ;定义了3个字节,它们的值都是0
    #相当于
    db 0,0,0
    
    db 3 dup (0,1,2)
    #相当于
    db 0,1,2,0,1,2,0,1,2

    db 3 dup ('abc','ABC')
    #相当于
    db 'abcABCabcABCabcABC'

    db 重复次数 dup (重复的数据)

    dw 重复次数 dup (重复的数据)

    dd 重复次数 dup (重复的数据)

    八,转移指令的原理

    1,可以修改IP,或同时修改CS和IP的指令统称为转移指令。一般有一下几类:

    无条件转移指令(jmp)
    条件转移指令
    循环指令(loop)
    过程
    终端

    2,操作符offset在汇编语言中是由编译器处理的符号,它的功能是取得标号的位移地址。

    3,jmp为无条件转移指令,可以只修改IP,也可以同时修改CS和IP,jmp指令要给出2种信息

    (1)转移的目的地址

    (2)转移的距离(段间转移、段内段转移,段内近转移)

    4,段内段转移:jmp short 标号

    assume cs:codesg
    
    codesg segment
        start:mov ax,0
            jmp short s
            add ax,1
        s: inc ax
    codesg ends
    end start

    在"jmp short 标号"指令所对应的机器码中,并不包含转移的目的地址,而包含的是转移的位移

    实际上,jmp short 标号的功能为:(IP)=(IP)+8位位移

    (1)8位位移=标号处的地址-jmp指令后的第一个字节的地址

    (2)short指明此处的位移为8位位移

    (3)8位位移的范围为-128~127,用补码表示

    (4)8位位移有比哪一程序在编译时算出(此处可以深究下)

    5,段内近转移:jmp near ptr 标号;其功能为:(IP)=(IP)+16位位移

    6,段间转移(远转移):jmp far ptr 标号,功能为

    (CS)=标号所在段的段地址;(IP)=标号所在段的偏移地址

    7,转移地址在寄存器中:jmp 16位ref 。功能为:(IP)=(16位reg)

    8,转移地址在内存中:

    (1)jmp word ptr 内存单元地址,属于段内转移

      (IP)=(内存单元地址)

    (2)jmp dword ptr 内存单元地址,属于段间转移

      (CS)=(内存单元地址+2)

      (IP)=(内存单元地址)

    9,jcxz指令:有条件转移指令,所有有条件指令都是短转移,在对应的机器码中包含转移的位移,而不是目的地址

    格式:jcxz 标号(如果(CX)=0,转移到标号处执行)

    操作:当(CX)=0时,(IP)=(IP)+8位位移

    相当于:if((CX)==0) jmp short 标号

    10,loop指令,所有循环指令都是短转移,在对应的机器码中包含转移的位移,而不是目的地址

    格式:loop 标号

    操作:

    (1)(CX)=(CX)-1 

    (2)如果(CX)不等于0,(IP)=(IP)+8位位移  

    相当于:

    (CX)--;

    if((CX)<>0) jmp short 标号

    11,根据位移进行转移的意义:方便程序段在内存中的浮动装配

    12,call和ret指令都是转移指令,通常一起使用实现子程序的设计

    (1)ret指令用栈中的数据,修改IP的内容,从而实现近转移,

      相当于执行  pop IP

    (IP)=((SS)*16+(SP))
    (SP)=(SP)+2

    (2)retf指令用栈中的数据,修改CS和IP的内容,从二实现远转移 

      相当于执行 pop IP    pop CS

    (IP)=((SS)*16+(SP))
    (SP)=(SP)+2
    (CS)=((SS)*16+(SP))
    (SP)=(SP)+2

    (3)call指令:根据位移进行转移时

    格式:call 标号

    (SP)=(SP)-2
    ((SS)*16+(SP))=(IP)
    (IP)=(IP)+16位位移

    相当于进行

    push IP

    jmp near ptr 标号

     13,call far ptr 标号 :目的地址在指令中,实现的是段间转移,

    (SP)=(SP)-2
    ((SS)*16+(SP)) = (CS)
    (SP)=(SP)-2
    ((SS)*16+(SP)) = (IP)
    
    (CS)=标号所在段的段地址
    (IP)=标号所在段的偏移地址

    相当于进行

    push CS

    push IP

    jmp far ptr 标号

    14,call 16位reg:转移地址在寄存器中

    (SP)=(SP)-2
    ((SS)*16+(SP)) = (IP)
    (IP)=(16位reg)

    相当于 push IP

    jmp 16位reg

    15,call word ptr 内存单元地址:转移地址在内存中

    相当于 

    push IP

    jmp word ptr 内存单元地址

    16,call dword ptr 内存单元地址:转移地址在内存中

    相当于

    push CS

    push IP

    jmp dword ptr 内存单元地址

    17,call和ret的配合使用

    assume cs:code
    
    code segment
    main: ...
            ...
        call sub1
            ...
             ...
        mov ax,4c00h
        int 21h
    
    sub1: ...
            ...
        call sub2
            ...
            ...
        ret
    
    sub2: ...
            ...
            ...
        ret
    code ends
    end main

    (1)从上面可以看出,call和ret指令共同支持了汇编语言编程中的模块化设计。

    (2)参数和结果的传递:参数存在什么地方,计算结果存放在什么地方;答案是寄存器

    (3)对于存放参数的寄存器和存放结果的寄存器,调用者和子程序的读写操作恰恰相反

    调用者将参数送入参数寄存器,从结果寄存器中取得返回值

    子程序从参数寄存器中取得参数,将返回值送入结果寄存器

    assume cs:code
    
    data segment
        dw 1,2,3,4,5,6,7,8
        dd  0,0,0,0,0,0,0,0
    data ends
    
    code segment
    
        start:mov ax,data
                mov ds,ax
                mov si,0
                mov di,16
    
                mov cx,8
        s:     mov bx,[si]
                call cube
                mov [di],ax
                mov [di].2,dx
                add si,2
                add di,4
                loop s
    
                mov ax,4c00h
                int 21h
        cube: mov ax,bx
                mul bx
                mul bx
                ret
    
    code ends
    end start

    18,mul指令:乘法

    (1)2个相乘的数,要么都是8位要么都是16位,

    如果是8位,一个默认在AL中,另一个在8位reg或内存字节单元中

    如果是16位,一个默认在AX中,另一个在16位reg或内存字单元中

    (2)结果:如果是8位乘法,结果在AX中;如果是16位乘法,结果高位默认在DX中存放,低位在AX中存放。

    格式:mul reg或者mul 内存单元

    举例:

    mov al,100
    mov bl,10
    mul bl
  • 相关阅读:
    JDK 14的新特性:更加好用的NullPointerExceptions
    技术回顾系列:最新最热门的技术大事-第一周
    JDK 14的新特性:instanceof模式匹配
    JDK 15 JAVA 15的新特性展望
    怎么break java8 stream的foreach
    java 8 stream中的Spliterator简介
    怎么在java中创建一个自定义的collector
    java 8 stream reduce详解和误区
    java stream中Collectors的用法
    java关于throw Exception的一个小秘密
  • 原文地址:https://www.cnblogs.com/tkzc2013/p/14339862.html
Copyright © 2020-2023  润新知