Fork me on Gitee

汇编二(入门例子)

 

1: 字符输出

 LDA AX,BUffer: 将buffer地址的连带偏移地址加入到AX寄存器中 , 8086 8088为16进制的寄存器,20位物理地址

MOV AX,BUffer; 同理,但是将buffer的16位地址装入AX寄存器中

DATAS SEGMENT
     STRS  DB  'Hello World!',13,10,'$'
     ;定义了一个字符串,标号是STRING,其值是字符串首字符的地址。
     ;DB表示的是字符串中每个字符的都是一个字节,每往后加1的时候,地址偏移量加1.
     ;13 CR 回车
     ;10 LF 换行
     ;$作为字符串的结束符 不结束将会输出乱码
DATAS ENDS

STACKS SEGMENT stack

STACKS ENDS

ASSUME CS:CODE,DS:DATAS,SS:STACKS
CODE SEGMENT
main:
    MOV AX,DATAS ; 初始化代码
    MOV DS,AX; 初始化代码
    LEA  DX,STRS; 将偏移地址STRS装入数据寄存器
    MOV AH,9 ;9 为输出代码
    INT 21H ; 执行中断
    MOV AH,4CH
    INT 21H;
CODE ENDS

end main

 2:顺序控制

顺序控制是构成程序的核心条件之一,这里尤为主要的说明一下:

Z=((3X+Y-5)/2其中X=15HY=10H

 

DATAS SEGMENT
    ;定义Z=((3X+Y-5)/2其中X=15H Y=10H
    X DW 15H
    Y DW 10H
    Z DW ?
DATAS ENDS
ASSUME CS:CODE,DS:DATAS
CODE SEGMENT
main:
    MOV AX,DATAS ; 初始化代码
    MOV DS,AX; 初始化代码
    MOV AX,X
    SHL AX,1
    ADD AX,X
    ADD AX,Y
    SUB AX,5
    SAR AX,1
    MOV Z,AX
    LEA DX,Z
    MOV AH,02H ; 显示输出
    INT 21H
    MOV AH,4CH
    INT 21H;
CODE ENDS

end main

 

3: 基本流程控制

需要了解psw状态寄存器的各项代表的意思,这里只需要关注 ZF 零位标志位

 

 

 这里 X为2;

 

DATAS SEGMENT
    ;定义X=2
    X DB 2
    Y DB ?
DATAS ENDS
ASSUME CS:CODE,DS:DATAS
CODE SEGMENT
main:
    MOV AX,DATAS ; 初始化代码
    MOV DS,AX; 初始化代码
    CMP X,0
    JGE lable1 ; >=0
    MOV Y,-1
    JMP next
    lable1:
    JZ lable2; =0
    MOV Y,1;
    JMP next
    lable2:
    MOV Y,0 
    next:
    MOV AX,0
    MOV AH,4CH
    INT 21H;
CODE ENDS

end main

 

 

  

 
 DATAS SEGMENT
     X DW 2; XΪ2 
 DATAS ENDS
 CODES SEGMENT
 ASSUME DS:DATAS,CS:CODES
 START:
     MOV AX,DATAS
    MOV DS,AX
    XOR AX,AX
    MOV AX,X
    CMP AX,0
    JL NEXT
    MOV AX,1
    JMP NEXT2
    NEXT:
    MOV AX,-1
    NEXT2:
    MOV AH,4CH;
    INT 21H 
 CODES ENDS
 END START

 

结果:

 

 

4:循环程序

  • loop:功能:首先将CX内容减1,若(CX)0,则转至目标地址处执循环,否则顺序执行。
  • loopz/loopE 功能:首先将CX内容减1,若(CX)0且ZF=1,则转至目标地址处执循环,否则顺序执行。例如:

计算1+2+3+..+100的和:

DATAS SEGMENT
DATAS ENDS
ASSUME CS:CODE,DS:DATAS
CODE SEGMENT
main:
    MOV AX,DATAS ; 初始化代码
    MOV DS,AX; 初始化代码
    MOV CX,100
    MOV AX,0;
    next:
    MOV AX,CX
    LOOP next
    MOV BX,AX
    MOV DX,BX
    MOV AH,02H
    INT 21H
    MOV AH,4CH
    INT 21H;
CODE ENDS

end main

 5: A+B问题

  •   MOV AH,01 输入
  •   MOV  AH,02 输出数字
  •   MOV AH,09 输出字符串
  •   SUB AL,30H  转为数字
DATAS SEGMENT
    ;此处输入数据段代码
    TIP1 DB 'PLEASE INPUT A:',13,10,'$'
    TIP2 DB 13,10,'PLEASE INPUT B:',13,10,'$'
    TIP3 DB 13,10,'A + B = $'
DATAS ENDS

STACKS SEGMENT
    ;此处输入堆栈段代码
STACKS ENDS

CODES SEGMENT
    ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
    MOV AX,DATAS
    MOV DS,AX
    ;TIP ONE
    LEA DX,TIP1
    MOV AH,09
    INT 21H
    ;GET A
    MOV AH,01
    INT 21H
    SUB AL,30H
    MOV CL,AL
    ;TIP TWO
    LEA DX,TIP2
    MOV AH,09H
    INT 21H
    ;GET B
    MOV AH,01
    INT 21H
    SUB AL,30H
    ADD CL,AL
    ADD CL,30H
    ;TIP 3
    LEA DX,TIP3
    MOV AH,09
    INT 21H
    
    ;RESULT
    MOV DL,CL
    MOV AH,02
    INT 21H
    ;TAO LU
    MOV AH,4CH
    INT 21H
CODES ENDS
    END START

 6: 数组的操作与处理

数组在汇编的声明使用伪指令DUP 进行声明

如 X DB 100 DUP(0) ; 声明了 100个元素全部为0的字节数组,

数组在机器中使用寄存器间接寻址, 数组的首地址存放在x的地址中, s[i] 这种方式实际上就是首地址加上偏移地址,进行访问

6.1: 编写一个程序,首先定义一个数据段,在数据段中定义一个字类型的数组,数组有1000个元素,并将初值设为0;再编写一个代码段,在代码段中完成将数组的每个元素值设置为1234H

DATAS SEGMENT
    X DW 1000 DUP(0)
DATAS ENDS

CODES SEGMENT
    ASSUME CS:CODES,DS:DATAS
START:
    MOV AX,DATAS
    MOV DS,AX
    MOV CX,5
    MOV SI,0
    next:
    MOV x[SI],1234H
    INC SI; 字数组 两个字节
    INC SI
    LOOP next
    MOV AH,4CH
    INT 21H
CODES ENDS
    END START

6.2 数组求和 并输出

 1,2,3,4,5,6,7,8,9,10

DATAS SEGMENT
    ARRAY  DB 1,2,3,4,5,6,7,8,9,10
    len EQU $-ARRAY; 替换指令
DATAS ENDS

CODES SEGMENT
    ASSUME CS:CODES,DS:DATAS
START:
    MOV AX,DATAS
    MOV DS,AX
       XOR AX,AX
       MOV SI,0
       MOV CX,0
       next: ADD AL,ARRAY[SI] ;读取数组下标
        INC SI
        INC CX
        CMP CX,len
       JL next ; <len 就继续执行循环
    MOV DL,AL
    MOV AH,4CH
    INT 21H
CODES ENDS
    END START

 7: 堆栈操作

  7.1子程序的定义与调用:

  • 如果你的子程序和主程序在同一个代码段,则使用near,调用发生后,主程序堆栈中只压入ip值;
  • 如果你的子程序和主程序不在一个代码段,则使用far,调用发生后,主程序堆栈中将压入cs、ip值;

 

 subpro PROC FAR
    //coding
 subpro ENDP
 
 subpro PROC NEAR
    //coding
 subpro ENDP

 

 

 

7.2 堆栈SS

 

  • sp:表示栈顶指针,指向栈顶地址.与SS相配合使用.ss为栈段.
  • bp:是基址指针,段地址默认在SS中.可以定位物理地址,比如:"mov ax,[bp+si+6]/mov ax,[bp+di+6].
  • push sp=sp-2
  • pop sp=sp+2

7.3 子程序求两个数最大最小值

DATAS SEGMENT
     X DW 0001H
     Y DW 00002H
     Z DW ? ; 存储结果
DATAS ENDS

STACKS SEGMENT 
   DB 100H DUP(?)
STACKS ENDS

CODES SEGMENT
    ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
    MOV AX,DATAS
    MOV DS,AX
    PUSH X;
    PUSH Y;
    CALL MAXF;调用子过程
    MOV SP,4 ;恢复栈顶指针
    MOV Z,AX
    MOV AH,4CH
    INT 21H
    ; 子过程
    MAXF PROC NEAR
    PUSH BP
    MOV BP,SP
    MOV AX,[BP+4];
    CMP AX,[BP+6];
    JG next
    MOV AX,[BP+6]
    next:POP BP
    RET 0
    MAXF ENDP
CODES ENDS
    END START

 

posted @ 2019-11-03 14:49  ---dgw博客  阅读(683)  评论(0编辑  收藏  举报