微机系统-汇编语言入门
汇编语言及其程序设计
-1:汇编语言的语句格式
[名字] 操作符 操作数; [注释]
名字:
1. 是一种标识符。
2. 组成:A~Z,a~z; 0~9; 专用符号 ?.@ _$
3. 限制:
1)第一个字符不能是数字;
2)“.”必须是第一个字符;
3)前31个字符有效;
4)不能为关键字。
4. 类型:标号-指令符号地址变量-数据符号地址
操作符:
CPU指令、伪指令、宏指令
操作数:
指定参与操作的数据,或数据所在单元地址
注释:
说明程序、指令的功能,增加程序的可读性
-2:指令格式:
一个指令由5部分组成:前缀、操作码、寻址方式、偏移量、立即数。(加粗属于操作数)
(a)是前缀 (b)是操作码和操作数
-3:寻址方式:
一个指令一定涉及两个方面:谁?做什么?
这里的谁就涉及到了寻址方式了
有两类寻址:(1)对操作数寻址 (2)对转移地址、调用地址寻址
Pentium系统中使用字节(8位)、字(16位) 、双字(32位)和4倍字(64位) 。采用低端存储方式
一共有11中寻址方式:
总览
-1:立即寻址
操作数是指令的一部分。完整地取出该条指令之后也就获得了操作数。这种操作数称为立即数。
比如:
MOV AL,0101010lB
MOV BX,1234H
MOV EAX,12315678H
-2:寄存器寻址:
操作数在CPU的某个寄存器中,指令指定寄存器号。
MOV DS,AX
MOV EAX,ECX
MOV DL,BH
-3:存储器寻址:
操作数在存储器中。 (我们主要要去获取EA)
这里的EA=基址+(变址*比例因子)+位移量
基址:基址寄存器中的内容。基址寄存器通常用于编译程序指向局部变量区、数据段中数组或字符串的首地址。
变址:变址寄存器中的内容。变址寄存器用于访问数组或字符串的元素。
比例因子:32位机的寻址方式。寻址中,用变址寄存器的内容乘以比例因子得到变址值。该方式对访问数组特别有用。
位移量:指令中的一个数,但不是立即数,而是一个地址。
以8086为例:
存储器寻址方式:
-4:转移地址的寻址方式:
转移地址:转移指令中的操作数是转移的目的地址,称为转移地址
转移地址寻址:用于确定转移指令、CALL指令的转向地址。
段内相对寻址:
位移量+IP=EA ->IP/EIP
短跳转 JMP SHORT AA9 //8位
近跳转 JMP NEAR PTR AA8 //16位
段内间接(寄存器)寻址:
寄存器内容 =EA ->IP/EIP ,比如 :JMP BX
段内直接寻址:
目标段地址:偏移量=CS:IP/EIP 比如 JMP FAR PTR AA6
段间间接寻址
连续的存储单元内容=CS:IP/EIP 比如: JMP DWORD PTR [SI]
-5:指令系统
指令系统:指令的集合,软硬件交界面
指令系统需要我们掌握的要点:侧重指令系统的功能和方法
一共分为了10类指令:
数据传送指令、算术运算指令、 BCD 码调整指令、逻辑运算指令、 移位循环指令、控制转移指令、条件设置指令、串操作指令、处理器控制指令、保护模式系统控制指令
--1:数据传送指令 : 源 → 目。
指令执行后,源操作数不变,不影响状态标志。
(1)MOV指令
格式: MOV DST,SRC SRC->DST
要求DST和SRC的长度相等,CS可出不可入(可以用,但是不能写)
举例:
MOV WORD PTR [BX],10H 立即数传入[BX]
(2)PUSH
格式: PUSH SRC ;
把SRC压入栈中
举例 16为数据:
16 位指令操作:
(SP) ← (SP) - 2 //堆栈指针 SP 先减 2 。因为在 16 位系统中,堆栈按字(2 字节)操作,压入一个字数据,堆栈指针要指向新的栈顶位置,所以 SP 减 2 来预留存储单元。
((SP)+1, (SP)) ← (SRC) //将源操作数 SRC 的值存入 SP 所指向的栈顶位置(低字节存 SP 指向处,高字节存 SP + 1 处 )。
(3)POP
格式 : POP DEST
举例 16位操作:
DST <-((SP)+1, (SP))
SP <- SP+2
(4)标志寄存器 进出栈 (因为指明的操作的寄存器所以格式格外的简单)
PUSHF ;标志寄存器低16位压入堆栈
POPF ;从栈顶弹出2个字节送标志寄存器低16位
(5)LEA
格式: LEA ERG,SRC
REG 代表通用寄存器,SRC 代表源操作数(16 位或 32 位存储器有效地址 )。该指令功能是把源操作数 SRC 的有效地址送入指定寄存器 REG 。例如 LEA BX, [SI + 10H] ,就是将内存地址 [SI + 10H] 的有效地址送入 BX 寄存器 。
举例:
AX是16位的,所以就只会取出来16位
如果是MOV AX,MEM ,那么就会取出来 3412H
如果是LEA AX,MEM , 那么就会取出来其地址 3100H
(6)IN
-1:直接寻址(n:0~255)
IN AL ,n (AL为8位,将端口 n的内容送入到AL)
-2:间接寻址(DX为16位,可以送全部的端口地址:0~65535)
IN AL,DX (AL为8位,将 (DX)内存着的地址中的数据放入AL)
(7)OUT
OUT AL ,n (AL为8位,将AL的内容送入到端口)
-2:间接寻址(DX为16位,可以送全部的端口地址:0~65535)
OUT AL,DX (AL为8位,将 AL内容放入到DX存着的端口地址对应的端口中)
--2:算术运算指令
(1)加减法
ADD: DST,SRC //DST=DST+SRC
类型:
影响CF、PF、AF、ZF、SF、OF。可进行8、16、32位操作
ADC 带进位加法(add with carry)
格式:ADC DST, SRC ;(DST)← (SRC)+(DST)+CF
SUB 减法(subtract)
格式:SUB DST, SRC ;(DST)← (DST) - (SRC)
SBB 带借位减法(subtract with borrow)
格式:SBB DST, SRC ;(DST)← (DST) - (SRC) – CF
(2)自增,自减
INC
格式:INC OPR ;(OPR) ← (OPR)+1
DEC 减1(decrement)
格式:DEC OPR ;(OPR)← (OPR)-1
条指令共性说明:
目的操作数:通用寄存器、存储器单元,可以是8位、16位或32位。
执行INC、DEC指令后,影响AF、OF、PF、SF、ZF,但对CF没有影响
(3)CMP
格式:CMP OPR1, OPR2 ;(OPR1) - (OPR2)
(4)MUL 无符号数乘法(unsigned multiple)
格式:MUL SRC
功能:
字节乘 (AX) ← (AL) × (SRC)
字乘 (DX:AX) ← (AX) × (SRC)
(5)DIV 无符号数除法(unsigned divide)
格式:DIV SRC
功能
字节除 (AL) ←(AX)/(SRC)的商,(AH) ←(AX)/(SRC)的余数
字除 (AX) ←(DX:AX)/(SRC)的商,(DX) ←(DX:AX)/(SRC)的余数
--3:BCD码调整指令
(1)DAA 压缩BCD码加法调整
格式:DAA
功能:
1如果AL的低4位大于9或AF=1,则(AL)+6 → (AL) 和 1→AF。
2如果AL的高4位大于9或CF=1,则(AL)+60H → (AL) 和 1→CF。
注意:
只对AL调整。
OF无定义,其他5个状态受影响
举例:
MOV AL,54H ;//54H代表十进制数54
MOV BL,37H ;//37H代表十进制数37
ADD AL,BL ; //AL中的和为十六进制数8BH
DAA ; //AL=91H,AF=1,CF=0
(2)DAS 压缩BCD码减法调整(decimal adjust for subtraction)
格式:DAS
功能:调整压缩BCD码减法结果
(3) AAA 非压缩BCD码加法调整(ASCII adjust for addition)
格式:AAA
功能:调整非压缩BCD码加法结果
(4)AAS 非压缩BCD码减法调整(ASCII adjust for subtraction )
格式:AAS
功能:调整非压缩BCD码减法结果
--4:逻辑运算符:
(1)与,或,异或,比较
-1:AND 按位逻辑与运算
格式:AND DST,SRC ;(DST) ←(DST)∧(SRC)
-2:OR 按位逻辑或运算
格式:OR DST,SRC ;(DST) ←(DST)∨(SRC)
-3:XOR 按位逻辑异或运算(exclusive or)
格式:XOR DST,SRC ; (DST) ←(DST)⊕(SRC)
-4:TEST 按位逻辑比较运算
格式:TEST OPRl,OPR2 ;(OPRl)∧(OPR2)
4条指令类型:同ADD。
4条指令说明: CF、OF置0,影响SF、ZF、PF,AF无定义
(2)取反
NOT:
格式:NOT OPR ;(OPR) ← OPR
类型:通用寄存器、存储器单元,8位、16位、32位。
说明:不影响标志位。
--5:移位循环指令
1. 移位指令
SHL 逻辑左移(shift logical left)
格式: SHL OPR,CNT
SHR 逻辑右移(shift logical right)
格式:SHR OPR,CNT
SAL 算术左移(shift arithmetic left)
格式:SAL OPR,CNT
SAR 算术右移(shift arithmetic right)
格式:SAR OPR,CNT
移位指令说明:
OPR:通用寄存器、存储器单元。 8位、16位、32位。
CNT:8位立即数(1-31,8086中只能为1)、CL。
CF依操作设置。OF当CNT=1时有效。
2. 循环指令
ROL 循环左移(rotate left )
格式:ROL OPR, CNT
ROR 循环右移(rotate right)
格式:ROR OPR, CNT
RCL 带进位循环左移(rotate left through carry)
格式:RCL OPR, CNT
RCR 带进位循环右移(rotate right through carry )
格式:RCR OPR, CNT
--6:控制转移指令
1. 无条件段内相对短转移(jump)
格式:JMP SHORT OPR
功能: (IP) ←(IP)+8位位移量
说明:SHORT是短转移属性描述符,8位位移量是一个带符号数,范围是-128到+127字节。
2. 无条件段内相对近转移
格式:JMP NEAR PTR OPR
功能: (1P) ←(1P)+16位位移量
说明:NEAR是近转移属性描述符,16位位移量是一个带符号数
3. 无条件段内间接转移
格式:JMP OPR ; OPR可以是寄存器、存储器
功能: (IP)←(EA)
4. 无条件段间直接转移
格式:JMP FAR PTR OPR ; OPR为指令的标号(即指令地址)
功能:
(IP) ←OPR的段内偏移地址
(CS)←OPR所在段的段地址
5. 无条件段间间接转移
格式:JMP DWORD PTR OPR ; OPR为存储器单元
功能:
(IP) ←[EA]
(CS) ←[EA+2
6.条件相对转移 (8位偏移量OPR)
(1)单条件相对转移
① JZ/JE OPR ;ZF=1 转移(结果为零或相等转移)
② JNZ/JNE OPR ;ZF=0 转移(结果不为零或不相等转移)
③ JS OPR ;SF=1 转移(结果为负转移)
④ JNS OPR ;SF=0 转移(结果为正转移)
⑤ JO OPR ;OF=1 转移(结果溢出转移)
⑥ JNO OPR ;OF=0 转移(结果不溢出转移)
⑦ JP/JPE OPR ;PF=1 转移(结果为偶转移)
⑧ JNP/JPO OPR ;PF=0 转移(结果为奇转移)
⑨ JC OPR ;CF=1 转移(有借位或有进位转移)
⑩ JNC OPR ;CF=0 转移(无借位或无进位转移)
(2)无符号数比较条件相对转移(A-B) (A:above高于 B:below低于)
① JB/JNAE/JC OPR ;CF=1 (A<B转移)
② JAE/JNB/JNC OPR ;CF=0 (A≥B转移)
③ JBE/JNA OPR ;(CF∨ZF)=1 (A≤B转移)
④ JA/JNBE OPR ;(CF∨ZF)=0 (A>B转移)
(JA表示A大于B,跳转)
(3)有符号数比较条件相对转移(A-B) (G:greater大于 L:less小于)
① JL/JNGE OPR ;(SF⊕OF)=1 (A<B转移)
② JGE/JNL OPR ;(SF⊕OF)=0 (A≥B转移)
③ JLE/JNG OPR ;((SF⊕OF) ∨ZF)=1 (A≤B转移)
④ JG/JNLE OPR ;((SF⊕OF) ∨ZF)=0 (A>B转移)
--7:LOOP循环控制相对转移
格式:LOOP OPR
功能:(CX/ECX)←(CX/ECX)-1;(CX/ECX)≠0时转移
说明:上述循环控制相对转移指令中的转移地址为(IP/EIP)←(IP/EIP)+ 8位带符号数;8位位移量是由目标地址OPR确定的。
--8:子程序调用与返回
(1)段内相对调用
格式:
CALL DST ; DST为直接入口地址,指令中给出
CALL NEAR PTR DST
如果是16位的操作数:
SP← (SP)-2 ,[SP]←(IP) //当前地址放入栈
IP←(IP)+16位有符号数作为位移量 //修改IP,指向子程序入口
(2)段内间接调用
格式:CALL DST ;DST为reg or mem
功能: 假如操作数16位:
SP← (SP)-2,[SP]←(IP)
(IP) ←(EA)
类型:寄存器、存储器单元。
(3)段间直接调用
格式:CALL DST ; DST为直接入口地址,指令中给出
功能:
操作数16位:
SP← (SP)-2 , [SP] ← (CS)
SP← (SP)-2 , [SP] ← (IP) //保存当前的位置
IP ←DST的偏移地址 //指向新的程序入口
CS←DST所在段的段地址
说明:该指令先将CS 、IP或EIP压栈保护返回地址。然后转移到由DST(DST为汇编语言中的过程名)指定的转移地址。
(4)段间间接调用
格式:CALL DST ;DST为mem
功能: 操作数16位:
SP← (SP)-2 , [SP] ← (CS)
SP← (SP)-2 , [SP] ← (IP) //放入当前地址
IP ←(EA) //低16位为偏移量
CS←(EA+2)//高16位为段地址
(5)段内返回
格式:RET
操作数16位:
IP←栈弹出2字节,SP ← (SP)+2
(6)段间返回
格式:RET
功能:
操作数16位:
IP←栈弹出2字节,SP ← (SP)+2
CS←栈弹出2字节,SP ← (SP)+2
--9:中断指令
中断指令作用:调用中断服务程序。中断向量地址=中断类型码×4。
(1)中断指令
格式 : INT n
功能:
① SP←(SP)-2
② PUSH (FR) ;//标志寄存器FR进栈
③ SP←(SP)-2
④ PUSH (CS) ;//断点段地址CS进栈
⑤ SP←(SP)-2
⑥ PUSH (IP) ;//断点地址指针IP进栈
⑦ TF←0 ;//禁止单步
⑧ IF←0 ;//禁止中断
⑨ IP←[n×4] ;//转向中断服务程序 (地位)
⑩ CS←[n×4+2] //高位为段地址
(2)IRET中断返回
格式 : IRET
功能:
① IP←栈弹出2字节 ;//断点偏移量出栈
② SP←(SP)+2
③ CS←栈弹出2字节 ;//断点段地址出栈
④ SP←(SP)+2
⑤ FR←栈弹出2字节 ;//标志寄存器出栈
⑥ SP←(SP)+2
(3)系统功能调用
INT 21H
系统功能调用:DOS为系统程序员及用户提供的一组中断服务程序。
DOS规定用中断指令INT 21H作为进入各功能调用中断服务程序的总入口,再为每个功能调用规定一个功能号,以便进入相应各个中断服务程序的入口。
程序员使用系统功能调用的过程:
1)AH ←功能调用编号
2)设置入口参数
3)CPU执行 INT 21H
4)给出出口参数
-1:功能号1 :等待键盘输入,回送显示器
MOV AH,1 ;(AH) ←功能号01H
INT 21H ;调用21H号软中断
出口参数(AL)= 键入字符的ASCII码。
-2:功能号2 :输出字符送显示器
MOV DL,41H ;入口参数:(DL)←字符A的ASCII码
MOV AH,2 ;(AH) ←功能号02H
INT 21H ;在屏幕上显示输出字符A
没有出口参数
-3:功能号4CH:终止程序并返回
MOV AH,4CH ;(AH) ←功能号4CH
INT 21H ;调用21H号软中断
-10:处理器控制指令:
标志处理指令只设置或清除本指令的标志位,而不影响其他标志位。
CLC ;进位位置0, CF←0 (clear carry)
STC ;进位位置1, CF←1 (set carry)
CLD ;方向标志位置0,DF←0 (clear direction)
STD ;方向标志位置1,DF←1 (set direction)
CLI ;中断标志置0,IF←0,禁止中断(clear interrupt)
STI ;中断标志置1,IF←1,允许中断 (set interrupt)
NOP ;空操作,不执行任何操作。
HLT ;暂停,暂停指令停止软件的执行。有三种方式退出暂停:中断、硬件复位、DMA操作。
(ST=set ,CL =clear)
-6:伪指令
指示汇编程序完成规定的操作。如选择处理器、定义数据、分配存储区等
(1):END源程序结束
格式:END [标号]
功能:表示源程序结束,不可缺,源程序最后一条语句。
说明:
-标号指示程序开始执行的起始地址。
-主程序缺省值为代码段的第一条指令的地址。
-多个模块链接,主程序用标号,其他程序不用
(2)SEGMENTS 和 ENDS段定义伪指令
段定义:确定代码组织与数据存储的方式。
格式:段名 SEGMENT [定位类型] [组合类型] [字长类型] [‘类别’]
┇
段名 ENDS
定位类型: 指定段起始地址边界。
组合类型: 表示本段与其他模块段之间,具有相同段名的各段的组合关系。
字长类型: 386以后,说明使用16位寻址还是32位寻址。
类别:引号括起来的字符串。连接时,类别相同的段(它们可能不同名)放在连续的存储空间中,但它们仍然是不同的段。
功能:定义段名、段属性,并表示段的开始位置、结束位置。
-SEGMENT和ENDS必须成对出现,而且伪指令前面的段名也要相同
-段名是段的标识符,指明段的基址,由程序员指定。
-一般情况下,选项可以不用,使用默认值。但若需链接程序,就必须使用这些说明
(3)ASSUME 段分配伪指令
格式: ASSUME 段寄存器名:段名,段寄存器名:段名,……
功能:说明某个段使用哪一个段寄存器。
说明:
-程序段必须用CS,堆栈段必须用SS。
-该语句一般放在代码段最前面。
-说明性语句,除CS外(初始化赋值),各段寄存器在程序中赋值。
-取消语句: ASSUME NOTHING
(4)ORG地址计算器设置 (起始地址定义)
格式:ORG 数值表达式
功能:定义指令或数据的起始地址,$←表达式的值。
说明:数值表达式取值范围在0~65535之间
(5)EVEN偶地址定义(让地址计数器变为偶数)
格式:EVEN
功能:使下一个变量或指令从偶地址开始。
说明:便于字存储对准。 EVEN在代码段中可能多出一个NOP语句。
ALIGN 伪指令
ALIGN 4 表示使下一个存储单元地址按 4 字节边界对齐 。若当前地址不是 4 的倍数,会填充字节(保留原值 )直到地址是 4 的倍数 。
(6)数据定义伪指令
格式:[变量名] 操作符 操作数 [;注释]
功能:为操作数分配存储单元,用变量与存储单元相联系。
操作符:定义操作数类型。
DB: 一个操作数占有1个字节单元(8位),定义的变量为字节变量。
DW:一个操作数占有1个字单元(16位),定义的变量为字变量。
DD:一个操作数占有1个双字单元(32位),定义的变量为双字变量。
操作数:常数、表达式、字符串、?,DUP等
对于’?’,表示只分配空间,不赋值
对于DUP,就是一个复制操作符,比如
DATA1 DB 2 DUP(12H,34H,56H)
就会把()里面的内容写入两份到指定位置
举例:
从200H开始,
存入3个值12H,08H,34H,然后偶字节对齐,
然后存入一个字:789AH,然后4个字节对齐
存入一个双字12345678H
然后存入两个字,一个是当前的地址020CH,一个是6699H
(注意大小端编制的问题,大的在高地址)
(7):PROC,EDNP 过程定义伪指令
格式
过程名 PROC [属性]
┇ (过程体)
过程名 ENDP
功能:用于定义子程序结构,定义一段程序的入口(过程名)及属性。
说明:过程名是该过程(子程序)的入口,是CALL的操作数。
属性:FAR、NEAR(默认)
(8):EQU 赋值伪指令
格式:符号常数名 EQU 表达式 ;将表达式的值赋给符号常数
注意:只能定义一次(有点final的感觉)
DATA1 EQU 88
AAA1 EQU CX
DATA2 EQU DATA1+12
(9):返回值运算符
返回值运算符:返回变量或标号的段地址(SEG)、返回变量或标号的偏移地址(OFFSET)、返回变量或标号的类型值(TYPE)、返回变量的单元数(LENGTH)、返回变量的字节数(SIZE)。
举例:
MOV BX,OFFSET AA1
将AA1所在的段的偏移量送给BX
(10):PTR(临时改变类型属性运算符)
格式:类型 PTR 变量/标号 ;临时改变类型属性
说明:
变量:字节BYTE、字WORD、双字DWORD,等;
标号:近类型NEAR、远类型FAR。
举例:
DATA1 DW 1234H,5678H //存入两个字
DATA2 DB 99H,88H,77H,66H //存入4个字节
MOV AX,WORD PTR DATA2 //将DATA2 当做字送入AX(8899H)
MOV BL,BYTE PTR DATA1 //从DATA当做字节送入BL(34H)
汇编指令编程;
冒泡排序法:N个数据,相邻两个单元大小判断,位置交换,N- 1次后,排出最大(或最小)数据。经过N-1次的上述循环,便可实现数据排序。
DATA SEGMENT //数据段开始
NUMBER1 DB 100, 3, 90, 80, 99, 77, 44, 66, 50 ; 9个数据,定义字节类型变量NUMBER1并初始化 #
N EQU $ - NUMBER1 - 1 ; 数据个数减1(8个),$是汇编指针,计算NUMBER1变量所占字节数减1,用于循环次数控制 #
DATA ENDS //数据段结束
CODE SEGMENT //代码段开始
ASSUME CS:CODE, DS:DATA //定义下那个段使用那个段寄存器
START:
MOV AX, DATA ; 将数据段DATA的段地址传送到AX寄存器 #
MOV DS, AX ; 将AX中的数据段地址传送到数据段寄存器DS,完成数据段地址设置 #
MOV DX, N ; 将数据个数减1的值传送到DX寄存器,作为外循环计数初值,控制比较遍数 #
A1:
LEA BX, NUMBER1 ; 取NUMBER1的有效地址(偏移地址)传送到BX寄存器,作为数据首址指针 #
MOV CX, N ; 将数据个数减1的值传送到CX寄存器,作为内循环计数初值,控制每遍比较次数 #
A2:
MOV AL, [BX] ; 将BX指向的内存单元(NUMBER1数组当前元素)的字节数据传送到AL寄存器 #
CMP AL, [BX+1] ; 比较AL与BX + 1指向的内存单元(NUMBER1数组相邻元素)的值,设置标志位 #
JNC A3 ; 当比较结果无进位(前数大于等于后数)时,跳转到A3,不交换数据 #
XCHG AL, [BX+1] ; 若前数小于后数,交换AL与BX + 1指向内存单元的值 #
MOV [BX], AL ; 将交换后AL的值存回BX指向的内存单元 #
A3:
INC BX ; BX加1,指向下一对要比较的相邻数据单元 #
LOOP A2 ; CX减1,若不为0,跳转到A2继续内循环比较 #
DEC DX ; 外循环计数器DX减1 #
JNZ A1 ; 若DX不为0,跳转到A1开始下一遍比较 #
MOV AH, 4CH ; 设置系统功能调用参数,4CH功能号表示程序正常结束返回操作系统 #
INT 21H ; 执行系统功能调用,触发中断21H,程序结束返回操作系统 #
CODE ENDS
END START