汇编二(入门例子)
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