一、介绍
上一节介绍了8086cpu里的寄存器和常见的指令(MOV、ADD、SUB、INC、DEC、MUL、DIV),本章节主要介绍JUMP、CMP&JE、LOOP、PUSH&POP、PROC&CALL、输入和输出。如有错误,敬请斧正,万分感谢!
二、进阶指令
1.JUMP 无条件跳转
执行顺序:1——>3 (2被跳过没有执行)
.....;1
JUMP LabelName ;跳转到LabelName处
.....;2
LabelName:
.....;3
2.CMP&JE (条件跳转)
如果 AX = 10,执行顺序:1——>3
如果AX != 10,执行顺序:1——>2——>3
... ...;1
CMP AX,10 ;比较两个数的大小
JE LabelName ;为真跳转,否则不跳(JE是判断是否等于)
... ...;2
LabelName:
... ...;3
JE也可以换成其他判断大小的指令,例如:
JE | = |
JG / JNLE | > |
JGE / JNL | >= |
JL / JNGE | < |
JLE /JNG | <= |
JNE | != |
3.LOOP (循环)
执行顺序:只有 1 执行了X次后,才可以执行后面的2
MOV CX, X ;循环次数X(>0)储存在CX中
LabelName:
... ... ;1 循环的操作内容
LOOP LabelName
... ... ;2
注意事项:
- 循环次数一定要大于0,并且仅能放入CX
- 循环过程中CX都在 -1,所以循环体中不能再随意改变CX的值
- 只有LOOP不能实现多重循环,但再加上跳转指令则可以实现
4.PUSH&POP 入栈&出栈
PUSH reg8/reg16
POP reg8/reg16
注意事项:栈的特点是后进先出;后进先出
POSH/POP的操作对象只能是寄存器,PUSH和POP要符合规范,例如
错误示例:没有PUSH过,却要POP。
5.PROC&CALL 子函数调用
执行顺序:1——>3——>2
... ... ;1
CALL FunctionName ;调用FunctionName
... .... ;2
PROC FunctionName :
... .... ;3 子程序执行内容
RET
FunctionName ENDP
(如果题目没有要求,那么函数调用不是必须的。上述的其他指令熟练掌握即可应付考试)
关于子程序的参数传递:
1.用寄存器传递——适合参数较少情况
例:把大写字母改为小写字母
;子程序名:UPTOLW
;功能:大写转换小写
;入口参数:AL=待转字符
;出口参数:DL中放转换完字符
MOV AL, ‘R’ ;传参
CALL UPTOLW
MOV DL, AL
UPTOLW PROC
PUSHF
CMP AL, ‘A’
JB UP1
CMP AL, ‘Z’
JA UP1
ADD AL, ‘a’-‘A’
UP1: POPF
RET
UPTOLW ENDP
2.用地址表传递——适合参数较多情况
;数据段
ARY DW -86,420,7, … ,40
COUNT DW 100
SUM DW ?
TAB DW 3 DUP(?)
;代码段
MOV TAB, OFFSET ARY
MOV TAB+2, OFFSET COUNT
MOV TAB+4, OFFSET SUM
LEA BX, TAB ;传参
CALL PADD
MOV DX, SUM
... ...
PADD PROC
MOV SI, [BX]
MOV DI, [BX+2]
MOV CX, [DI]
MOV DI, [BX+4]
XOR AX, AX
L: ADD AX, [SI]
ADD SI, 2
LOOP L
MOV [DI], AX
RET
PADD ENDP
3.用堆栈传递——适合参数多情况
如果使用堆栈传递入口参数, 在主程序调用之前,需要把传递的参数依次压入堆栈。
进入子程序后,从堆栈中取出入口参数。 如果传送的是出口参数,
在子程序返回前,把需要返回的参数存入堆栈
返回主程序后再从堆栈中取出参数。
6.输入输出
输入/输出语句必须用到固定的寄存器,不可变。
1)输入单个字符
当程序执行到下面这个语句段的时候,用户需要从键盘输出一个字符。该字符将以其所对应的ACSII值被存放在AL处。
MOV AH,1
INT 21H
2)输入字符串
当程序执行到下面这个语句段的时候,用户需要从键盘输出一串字符,以回车结束。这些字符将以其所对应的ACSII值被存放在数据段的STRING处。
;数据段
MAXLENGTH DB 20;一个字节,用它存最大的长度
ACTUALLENGTH 20 ? ;一个字节,用它存实际的长度,在指令执行后会被填写
STRING DB 20 DUP(?) ;用来存字符串
;代码段
MOV DX,OFFSET MAXLENGTH
MOV AH,10
INT 21H
3)输出单个字符
当程序执行到下面这个语句段的时候,将在屏幕上显示一个字符
MOV DL,'A' ;‘A’ 也可写出A的ACSII值 65
MOV AH,2
INT 21H
4)输出字符串
当程序执行到下面这个语句段的时候,将在屏幕上显示一串字符,以‘$’作为字符串结束输出的符号。如果输出的字符串最后没有‘$’,将出现乱码。
MOV DX,OFFSET STRING ;将要输出的字符串的起始地址存放在DX
MOV AH,9
INT 21H
注意:
1.如果想要输出“ABC”,则STRING=65,66,67,36或者 STRING=‘A’,‘B’,‘C’,'$'或者字符与数字混合的形式,而STRING=A,B,C是错误的;
2.从键盘输入的数字不能直接拿来计算,因为参加运算的是其ACSII值而不是其本身。
例如:输入“123”,实际得到的是49,50,51。可以将这些数先分别减去48(0的ACSII值),再加权求和(1*100+2*10+3*1)最终得到输入的数据。
同理输出数字时,可以除以10得到每个数位上的数,再转换成ACSII,别忘了加上‘$’。
3.输出换行符为:0DH,0AH,24H (24H为'$'的十六进制表示,另外此汇编语言要求若数字最高位为字母,则需要在前+‘0’)
三、结语
本文旨在帮助有需要的同学快速学会编写8086汇编语言。如有表述不清的地方,多余谅解。