常用ARM及汇编指令
用ARM指令及汇编包括 (2)
指令集介绍 (4)
ARM数据处理指令包括 (7)
ARM伪指令介绍 (9)
ARM汇编程序设计及一些格式要求说明 (13)
用ARM指令及汇编包括
1、ARM处理器寻址方式
2、指令集介绍
3、伪指令
4、ARM汇编程序设计
5、C与汇编混合编程
ARM处理器寻址方式
1、寄存器寻址:操作数的值在寄存器中,指令中的地址码字段指出的是寄存器编号,指令执行时直接取出寄存器值操作
MOV R1, R2 ;R2->R1
SUB R0, R1,R2 ;R1-R2 -> R0
2、立即寻址:立即寻址指令中的操作码字段后面的地址码部分就是操作数本身,也就是说,数据就包含在指令当中,取出指令就取出了可以立即使用的操作数SUBS R0,R0,#1 ;R0-1 -> R0
MOV R0,#0xff00 ;0xff00 -> R0
注:立即数要以"#"为前缀,表示16进制数值时以"0x"表示
3、寄存器偏移寻址:是ARM指令集特有的寻址方式,当第2操作数是寄存器偏移方式时,第2个寄存器操作数在与第1个操作数结合之前选择进行移位操作MOV R0,R2,LSL #3 ;R2的值左移3位,结果存入R0,即R0 = R2 * 8 ANDS R1,R1,R2,LSL R3 ;R2的值左移R3位,然后和R1相与操作,结果放入R1
寄存器偏移寻址可采用的移位操作如下
(1)、LSL(Logical Shift Left)逻辑左移,寄存器中字的低端空出补0
(2)、LSR(Logical Shift Right)逻辑右移,寄存器中字的高端空出补0
(3)、ASR(Arthmetic Shift Right)算术右移,移位中保持符号位不变,即如果源操作数为正数,字高端空出补0,否则补1
(4)、ROR(Rotate Right)循环右移,由字的低端移出的位填入高端空出的位
(5)、RRX(Rotate Right eXtended by 1 place),操作数右移一位,左侧空位由CPSR的C填充
4、寄存器间接寻址:寄存器间接寻址指令中的地址码给出的是一个通用寄存器的编号,所需要的操作数保存在寄存器指定地址的存储单元中,即寄存器为操作数的地址指针
LDR R1,[R2] ;将R2中的数值作为地址,取出此地址中的数据保存在R1中SWP R1,R1,[R2] ;将R2中的数值作为地址,取出此地址中的数值与R1中的值交换
5、基址寻址:将基址寄存器的内容与指令中给出的偏移量相加,形成操作数的有效地址,基址寻址用于访问基址附近的存储单元,常用于查表,数组操作,功能部件寄存器访问等。
LDR R2,[R3,#0x0F] ;将R3的数值加0x0F作为地址,取出此地址的数值保存在R2中
STR R1,[R0,#-2] ;将R0中的数值减2作为地址,把R1中的内容保存到此地址位置
6、多寄存器寻址:一次可以传送几个寄存器值,允许一条指令传送16个寄存器的任何子集或所有寄存器
LDMIA R1!,{R2-R7,R12} ;将R1所指向的地址的数据读出到R2-R7,R12,R1
自动更新
STMIA R0!,{R3-R6,R10} ;将R3-R6,R10中的数值保存到R0指向的地址,R0自动更新
7、堆栈寻址:堆栈是特定顺序进行存取的存储区,堆栈寻址时隐含的使用一个专门的寄存器(堆栈指针),指向一块存储区域(堆栈),存储器堆栈可分为两种:
向上生长:向高地址方向生长,称为递增堆栈
向下生长:向低地址方向生长,称为递减堆栈
如此可结合出四中情况:
1、满递增:堆栈通过增大存储器的地址向上增长,堆栈指针指向内含有效数据项的最高地址,指令如 LDMFA,STMFA
2、空递增:堆栈通过增大存储器的地址向上增长,堆栈指针指向堆栈上的第一个空位置,指令如 LDMEA,STMEA
3、满递减:堆栈通过减小存储器的地址向下增长,堆栈指针指向内含有效数据项的最低地址,指令如 LDMFD,STMFD
4、空递减:堆栈通过减小存储器的地址向下增长,堆栈指针指向堆栈下的第一个空位置,指令如 LDMED,STMED
STMFD SP!,{R1-R7,LR} ;将R1-R7,LR入栈,满递减堆栈
LDMFD SP!,{R1-R7,LR} ;数据出栈,放入R1-R7,LR寄存器,满递减堆栈
8、块拷贝寻址:多寄存器传送指令用于一块数据从存储器的某一位置拷贝到另一位置
STMIA R0!,{R1-R7} ;将R1-R7的数据保存到存储器中,存储器指针在保存第一个值之后增加,方向为向上增长
STMIB R0!,{R1-R7} ;将R1-R7的数据保存到存储器中,存储器指针在保存第一个值之前增加,方向为向上增长
SIMDA R0!,{R1-R7} ;将R1-R7的数据保存到存储器中,存储器指针在保存第一个值之后增加,方向为向下增长
STMDB R0!,{R1-R7} ;将R1-R7的数据保存到存储器中,存储器指针在保存第一个值之前增加,方向为向下增长
不论是向上还是向下递增,存储时高编号的寄存器放在高地址的内存,出来时,
高地址的内容给编号高的寄存器
9、相对寻址:是基址寻址的一种变通,由程序计数器PC提供基准地址,指令中的地址码字段作为偏移量,两者相加后得到的地址即为操作数的有效地址
BL ROUTE1 ;调用到 ROUTE1 子程序
BEQ LOOP ;条件跳转到 LOOP 标号处
===================================================================== ===========================================
指令集介绍
指令格式:
其中<>内的项是必须的,{}内的项是可选的
opcode 指令助记符,如 LDR,STR等
cond 执行条件,如 EQ,NE等
S 是否影响CPSR寄存器的值,书写时影响CPSR,否则不影响
Rd 目标寄存器
Rn 第一个操作数的寄存器
operand2 第二个操作数
指令格式举例如下:
LDR R0,[R1] ;读取R1地址上的存储器单元内容,执行条件AL(无条件执行)
BEQ DATAEVEN ;跳转指令,执行条件EQ,即相等跳转到DATAEVEN ADDS R1,R1,#1 ;加法指令,R1+1 => R1 影响CPSR寄存器,带有S SUBNES R1,R1,#0xD ;条件执行减法运算(NE),R1-0xD => R1,影响CPSR寄存器,带有S
条件码表
条件码应用举例:
1、比较两个值大小,C代码如下:
if(a>b) a++;
else b++;
写出相应的ARM指令
代码如下:设R0为a,R1为b
CMP R0, R1 ; R0与R1比较
ADDHI R0,R0,#1 ; 若R0>R1,则R0=R0+1
ADDLS R1,R1,#1 ; 若R0<=R1,则R1=R1+1
2、若两个条件均成立,则将这两个数值相加
C代码为: if((a!=10)&&(b!=20)) a=a+b;
对应的ARM指令为:
CMP R0,#10 ;比较R0是否为10
CMPNE R1,#20 ;若R0不为10,则比较R1是否为20
ADDNE R0,R0,R1; 若R0不为10且R1不为20,则执行 R0 = R0+R1
3、若两个条件有一个成立,则将这两个数值相加
C代码为: if((a!=10)||(b!=20)) a=a+b;
对应的ARM指令为:
CMP R0,#10
CMPEQ R1,#20
ADDNE R0,R0,R1
ARM存储访问指令:
LDR、STR、LDM、STM、SWP
LDR/STR:加载/存储字和无符号字节指令
从寻址方式的地址计算方法分,加载/存储指令有以下4种形式:
1,零偏移:LDR Rd,[Rn]
2,前索引偏移: LDR Rd,[Rn,#0x04]!,LDR Rd,[Rn,#-0x04] Rn不允许为R15 3,程序相对偏移:LDR Rd,label,label为程序标号,该形式不能使用后缀!4,后索引偏移: LDR Rd,[Rn],#0x04,Rn不允许是R15
指令举例如下:
LDR R2,[R5] ;加载R5指定地址上的数据(字),放入R2中
STR R1,[R0,#0x04] ;将R1的数据存储到 R0+0x04存储单元,R0的值不变(若有!,则R0就要更新)
LDRB R3,[R2],#1 ;读取R2地址上的一字节数据并保存到R3中,R2=R2+1 STRH R1,[R0,#2]! ;将R1的数据保存到R0+2的地址中,只存储低2字节数据,R0 =R0+2
LDM和STM是批量加载/存储指令,LDM为加载多个寄存器,STM为存储多个寄存器,主要用途是现场保护,数据复制、参数传递等,其模式有8种,前4种用于数据块的传输,后4种用于堆栈操作
IA:每次传送后地址加4
IB:每次传动前地址加4
DA:每次传送后地址减4
DB:每次传送前地址减4
FD:满递减堆栈
ED:空递增堆栈
FA:满递增堆栈
EA:空递增堆栈
批量加载/存储指令举例如下:
LDMIA R0!,{R3-R9} ;加载R0指向的地址上的多字数据,保存到R3-R9中,R0值更新
STMIA R1!,{R3-49} ;将R3-R9的数据存储到R1指向的地址上,R1值更新STMFD SP!,{R0-R7,LR} ; 现场保存,将R0~R7、LR入栈
LDMFD SP!,{R0-R7,PC}^ ;恢复现场,异常处理返回
使用LDM/STM进行数据复制
LDR R0,=SrcData ;设置源数据地址,LDR此时作为伪指令加载地址要加 = LDR R1,=DstData ;设置目标地址
LDMIA R0,{R2-R9} ;加载8字数据到寄存器R2 ~ R9
STMIA R1,{R2-R9} ;存储寄存器R2-R9到目标地址上
使用LDM/STM进行现场保护,常用在子程序或异常处理中
STMFD SP!,{R0-R7,LR} ;寄存器入栈
.....
BL DELAY ;调用DELAY子程序
.....
LDMFD SP!,{R0-R7,PC} ;恢复寄存器,并返回
SWP是寄存器和存储器交换指令,可使用SWP实现信号量操作
12C_SEM EQU 0x40003000 ;EQU定义一个常量
12C_SEM_WAIT ;标签
MOV R1,#0
LDR R0,=12C_SEM
SWP R1,R1,[R0] ;取出信号量,并设置为0
CMP R1,#0 ;判断是否有信号
BEQ 12C_SEM_WAIT ;若没有信号,则等待
ARM数据处理指令包括
1、数据传送指令
2、算术逻辑运算指令
3、比较指令
4、乘法指令
ADC指令:带进位加法指令,将操作数2的数据与Rn的值相加,再加上CPSR中C条件标志位,结果保存到Rd中
使用ADC指令实现64位加法
ADDS R0,R0,R2 ; R0+R2 => R0,影响CPSR中的值
ADC R1,R1,R3 ;(R1、R0) = (R1、R0)+(R3、R2)
SBC指令:带借位减法指令,用寄存器Rn减去操作数2,再减去CPSR中的C条件标志位的非(即若C标志清零,则结果减去1),结果保存在Rd中
使用SBC实现64位减法
SUBS R0,R0,R2
SBC R1,R1,R3 ;使用SBC实现64位减法,(R1,R0) - (R3,R2)
AND指令:按位与操作
ANDS R0,R0,#0x01 ;取出最低位数据
ORR指令:按位或操作
ORR R0,R0,#0x0F ;将R0的低4位置1
EOR指令是进行异或操作,BIC指令是位清除指令(遇1清0)
TST:位测试指令
TST R0,#0x01 ; 判断R0的最低位是否是为0
TEQ:相等测试指令
TEQ R0,R1 ; 比较R0与R1是否相等,也可看作相减,相等则为0,Z=1
MUL指令:乘法指令
MUL R1,R2,R3 ; R1=R2*R3
MULS R0,R3,R7 ; R0=R3*R7,同时设置CPSR中的N位和Z位
MLA是乘加指令,将操作数1和操作数2相乘再加上第3个操作数,结果的低32位存入到Rd中
UMULL是64位无符号乘法指令
UMULL R0,R1,R5,R8 ; (R1、R0) = R5 * R8
BL指令:带链接的跳转指令,指令将下一条指令拷贝到R14(即LR)链接寄存器中,然后跳转到指定地址运行
BL指令用于子程序调用,例如:BL DELAY
BX指令:带状态切换的跳转指令,例如 BX R0 ;跳转到R0指定的地址,并根据R0的最低位来切换处理器的状态
MCR:ARM寄存器到协处理器寄存器的数据传送指令
MRC:协处理器寄存器到ARM寄存器的数据传送指令
MRC/MCR指令格式如下:
MRC/MCR {cond} coproc,opcode1,Rd,CRn,CRm{,opcode2}
coproc是指令操作的协处理器名,标准名为pn,n为0-15
opcode1 协处理器的特定操作码
Rd MRC操作时,作为目标寄存器的协处理器寄存器,MCR操作时,作为ARM处理器的寄存器
CRn 存放第1个操作数的协处理器寄存器
CRm 存放第2个操作数的协处理器寄存器
opcode2 可选的协处理器特定操作码
MRC/MCR指令举例如下:
mcr/mrc p15,0,r0,c1,c0,0
SWI指令:SWI指令用于产生中断,从而实现用户模式变换到管理模式,CPSR保存到管理模式的SPSR中,执行转移到SWI向量
SWI 0x123456 ;软中断,中断立即数 0x123456
在SWI异常中断处理程序中,取出SWI立即数的步骤为:首先确定引起软中断的SWI指令是ARM指令还是THUMB指令,这可通过对SPSR访问得到,然后要取得该SWI指令的地址,这可通过访问LR寄存器得到,接着读出指令,分解出立即数
程序代码如下:
T_bit EQU 0x20 ;0010 0000
SWI_Hander
STMFD SP!,{R0-R3,R12,LR} ;现场保护
MRS R0,SPSR ;读取SPSR
STMFD SP!,{R0} ;保存SPSR
TST R0, #T_bit ;测试T标志位,0为ARM,1为THUMB
LDRNEH R0,[LR,#-2] ;若是THUMB指令,读出产生中断的指令码(16位)
BICNE R0,R0,#0xFF00 ;取得THUMB指令的8位立即数
LDREQ R0,[LR,#-4] ;若是ARM指令,读取产生中断的指令码(32
位)
BICEQ R0,R0,#0xFF000000 ;取得ARM指令的24位立即数
BL C_SWI_Handler
LDMFD SP!,{R0-R3,R12,PC}^ ;SWI异常中断返回
MRS指令:读状态寄存器指令,在ARM处理器中,只有MRS指令可以从状态寄存器CPSR或SPSR读出到通用寄存器
MRS R1,CPSR ;将CPSR状态寄存器读取,保存到R1
MRS R2,SPSR ;将SPSR状态寄存器读取,保存到R2
MRS应用:
1、使能IRQ中断
ENABLE_IRQ
MRS R0,CPSR
BIC R0,R0,#0x80 ;1000 0000
MSR CPSR,R0
MOV PC,LR
2、禁止IRQ中断
DISABLE_IRQ
MRS R0,CPSR
ORR R0,R0,#0x80
MSR CPSR,R0
MOV PC,LR
MSR:写状态寄存器指令,在ARM处理器中,只有MSR指令可以直接设置状态寄存器CPSR或SPSR
===================================================================== ===========================================
ARM伪指令介绍
ARM伪指令不是ARM指令集中的指令,只是为了编程方便编译器定义了伪指令ARM地址读取伪指令有四条,分别是
ADR 伪指令
ADRL 伪指令
LDR 伪指令
NOP 伪指令
作用的范围不一样,由小到大: ADR,ADRL,LDR
ADR、ADRL指令将基于PC相对偏移的地址读取到存储器中,例如
ADR R0 , DISP_TAB ; 加载转换表地址
LDR R1, [R0,R2] ;使用R2作为参数,进行查表
.....
DISP_TAB
DCB
0xc0,0xf9,0xa4,0x99,0x92,0x82,0xf8,0x80
LDR伪指令用于加载32位的立即数或一个地址值到指定寄存器,前加 =
LDR R0,=0x123456 ;加载32位立即数0x123456
LDR R0,=DATA_BUF+60 ;加载DATA_BUF地址+60
NOP是空操作伪指令
宏是一段独立的程序代码,它是通过伪指令定义的,在程序中使用宏指令即可调用宏,当程序被汇编时,汇编程序将对每个调用进行展开,用宏定义取代源程序中的宏指令
符号定义伪指令
1、全局变量声明:GBLA、GBLL 和 GBLS
2、局部变量声明:LCLA、LCLL 和 LCLS
3、变量赋值:SETA、SETL、和 SETS
4、为一个通用寄存器列表定义名称:RLIST
5、为一个协处理器的寄存器定义名称:CN
6、为一个协处理器定义名称:CP
最后一个字符 A代表算术变量,初始值为0,L代表逻辑变量,初值为FALSE,S 代表字符串,初值为空
伪指令应用举例如下:
MACRO ;声明一个宏
SENDDAT $dat ;宏的原型 $表示后面是变量
LCLA bitno ;声明一个局部算术变量
...
bitno SETA 8 ;设置变量值为8
...
MEND ;结束
RLIST指令格式:
name RLIST {reglist},例如: LoReg RLIST {R0-R7} ;定义寄存器列表LoReg CN指令的用法:
name CN expr,其中name是要定义的协处理器的寄存器名称,expr对应的协处理器的寄存器编号,数值范围 0 ~ 15
MemSet CN 1 ;将协处理器的寄存器1名称定义为 MemSet
CP指令的用法,举例如下:
DivRun CP 5 ;将协处理器5名称定义为DivRun
数据定义伪指令:
1、声明一个文字池:LTORG
2、定义一个结构化的内存表的首地址:MAP 或 ^
3、定义结构化内存表中的一个数据域:FIELD 或 #
4、分配一块内存空间,并用0初始化: SPACE 或 %
5、分配一段字节内存单元,并用指定的数据初始化: DCB
6、分配一段字的内存单元,并用指令的数据初始化: DCD 和 DCDU
7、分配一段双字的内存单元,并用64位整数数据初始化: DCQ 和 DCQU
8、分配一段半字的内存单元,并用指定的数据初始化: DCW 和 DCWU
LTORG 用于声明一个文子池,在使用LDR伪指令时,要在适当的地址加入LTORG 声明文子池,这样就会把要加载的数据保存在文子池内,再用ARM的加载指令读出数据(若没有使用LTORG声明文子池,则汇编器会在程序末尾自动声明)LTORG伪指令应用举例如下:
...
LDR R0,=0x12345678
ADD R1,R1,R0
MOV PC,LR
LTORG ;声明文子池
DCD 0x333
DCD 0x555
MAP 用于定义一个结构化的内存表的首地址,^与MAP同义
MAP 0x00, R9 ;定义内存表的首地址为R9
FIELD 用于定义一个结构化内存表的数据域,#与FIELD同义
^ _ISR_STARTADDRESS ; ^ is synonym for MAP
HandleReset # 4 ; 定义数据域 HandleReset,长度为4字节
SPACE用于分配一块内存单元,并用0初始化,%与SPACE同义
伪指令应用举例如下:
AREA DataRAM,DATA,READWROTE ;声明一数据段,名为DataRAM
DataBuf SPACE 1000 ;分配1000字节空间
DCB伪指令格式:
{label} DCB expr{,expr} ...
加{}的代表可有可无,DCD、DCW指令格式与DCB基本相同
ASSERT为断言错误伪指令,在汇编编译器对汇编程序的第二遍扫描中,若其中ASSERT条件不成立,ASSERT伪指令将报告该错误信息
ASSERT Top<>Temp ;断言Top 不等于 Temp
ASSERT :DEF:ENDIAN_CHANGE
汇编控制伪指令
1、条件汇编控制:IF、ELSE 和 ENDIF
IF、ELSE 和 ENDIF 伪指令能够根据条件把一段代码包括在汇编程序内或将其排除在程序之外
[ 与 IF同义,| 与 ELSE 同义, ] 与 ENDIF 同义
伪指令应用举例如下:
[ {CONFIG} = 16 ; [ 代表 IF
BL __rt_udiv_1
| ; | 代表 ELSE
BL __rt_div0
] ; ] 代表 ENDIF
2、MACRO 和 MEND
MACRO 和 MEND 伪指令用于宏定义,MACRO表示宏定义的开始,MEND表示宏定义的结束,用MACRO和MEND定义的一段代码,称为宏定义体,伪指令应用如下:MACRO
CSI_SETB ;宏名为CSI_SETB,无参数
LDR R0,=rPDATG ;读取GPG0 口的值
LDR R1,[R0]
ORR R1,R1,#0x01 ;CSI置位操作
STR R1,[R0] ;输出控制
MEND
3、WHILE 和 WEND
WHILE 和 WEND 伪指令用于根据条件重复编相同的或几乎相同的一段源程序伪指令应用举例
WHILE no< 5
no SETA no+1
...
WEND
杂项伪指令:在汇编程序设计较为常用,如段定义伪指令,入口点设置伪指令,包含文件伪指令,标号导出或引入声明
1、边界对齐:ALIGN
2、段定义: AREA
3、指令集定义:CODE16 和 CODE32
4、汇编结束: END
5、程序入口: ENTRY
6、常量定义:EQU
7、声明一个符号可以被其它文件引用:EXPORT 和 GLOBAL
8、声明一个外部符号:IMPORT 和 EXTERN
9、包含文件: GET 和 INCLUDE
10、给特定的寄存器命名: RN
ARM汇编程序设计及一些格式要求说明
一般地,ARM源程序文件名的后缀名如下:
汇编文件: *.S
引入文件: *.INC
C程序: *.c
头文件: *.h
汇编语句格式:
[ 标号 ] <指令 | 条件 | S > <操作数> [ ;注释]
1、所有标号必须在一行的顶格书写,其后面不要加:
2、所有指令均不能顶格书写
3、ARM汇编器对标识符大小写敏感,书写标号及指令时字母大小要一致,在ARM 汇编程序中,一个ARM指令,伪指令,寄存器名可以全部为大写字母,也可以全部为小写字母,但不要大小写混合使用
4、注释使用 ;或者 @,@表示开始到此行结束,注释可以在一行顶格书写(对ADS汇编格式,只支持 ; )
5、源程序中允许空行
6、如果单行太长,可以使用字符 / 将其分行, / 后不能有任何字符,包括空格
7、对于变量的设置,常量的定义,其标识符必须在一行的顶格书写
标号:在ARM汇编中,标号代表一个地址,根据标号生成方式,可以分为以下3种
1、基于PC的标号,例如: BL LEDTEST
2、基于寄存器的标号,例如: MAP 0x00,R9
3、绝对地址,例如: LDR R0,=WTCON
局部标号:主要用于局部范围代码中,对宏定义也非常有用,格式如下:
N { routname }
N是局部标号,为 0 ~ 99
routname是局部标号作用范围的名称
局部标号引用格式: % {F | B } {A | T} N {routname }
其中:
% 表示局部标号引用操作
F 指示编译器只向前搜索
B 指示编译器只向后搜索
A 指示编译器搜索宏的所有嵌套层次
T 指示编译器搜索宏的当前层
应用举例如下:
mov r1, #16
0 subs r1,r1, #1
bne %B0
宏定义及其作用
:使用宏定义可以提高程序的可读性,简化程序代码和同步修改,宏首先要定义,然后再使用,当源程序被汇编时,汇编器将展开每一个宏调用,用宏定义体代表程序中的宏调用,并使用实际的参数值代替宏定义时的形式参数
宏定义应用举例如下:
.....
MACRO ;宏定义
CALL $FUNCTION , $DAT1 , $DAT2 ;宏名称为CALL,带有3个参数IMPORT $FUNCTION ; 声明外部子程序
MOV R0, $DAT1 ; 设置子程序参数,R0 = $DAT1
MOV R1, $DAT2 ;
BL FUNCTION ; 调用子程序
MEND ; 宏定义结束
......
汇编预处理后,宏调用将被展开,程序清单如下:
......
IMPORT FADD1
MOV R0, #3
MOV R1, #3
BL FADD1
子程序的调用
:使用BL指令进行调用,该指令会把返回的PC值保存在LR示例如下:
......
BL DELAY
......
DELAY ....
MOV PC,LR
当子程序指令完毕后,使用 MOV, B/BX , STMFD 等指令返回,STMFD 要与 LDMFD 配套使用
STMFD SP! , {R0-R7, LR}
......
LDMFD SP! , {R0-R7,PC }
ARM7TDMI (-S) 是没有BLX指令的,但可以通过以下几条程序实现其功能
ADR R1 , DELAY+1
MOV LR , PC ; 保存返回地址到LR
BX R1 ; 跳转并切换指令集
......
该程序要注意的是 3级流水线,PC执行到哪里是关键
特殊寄存器定义及应用:基于ARM核的芯片一般有片内外设,它们通过其特殊寄存器访问
示例如下:
WDTC EQU 0xE000000 ;寄存器定义
....
LDR R0, =WDTC ; 加载立即数要加 =
MOV R1, #0x12
STR R1, [R0] ; WDTC = 0x12
散转功能是汇编程序常用的一种算法,其示例如下:
CMP R0, #MAXINDEX ; 判断索引号是否超过最大索引值
ADDLO PC , PC , R0 , LSL #2 ; 若没有超出,则跳转到相应位置 B ERROR ; 若已经超出,则进行出错处理
; 散转表,对应索引号为 0 ~ N
B FUN1
B FUN2
B FUN3
查表操作是汇编程序常用的一种操作,其示例如下:
LDR R3, =DISP_TAB ;取得表头
LDR R2 , [R3, R5, LSL #2] ;根据R5的值查表,取出相应的值 ......
;下表为 0 - F 的自模
DISR_TAB DCD 0xC0, 0xF9 , 0xA4 , 0x99 , 0x92 , 0xA1, 0xC6, 0x83 DCD 0x82. 0xF8 , 0x80 , 0x90 , 0x88 , 0x86, 0x8E , 0xFF
长跳转功能的实现:ARM的B 和 BL 指令不能全空间跳转,但通过对PC
进行复制,实现32位地址的跳转
ADD LR , PC , #4 ;保存返回地址,即RET_FUN
LDR PC , [PC , # -4] ; 跳转到 LADR_FUN
DCD LADR_FUN
RET_FUN ....
也可以使用伪指令 LDR PC, =LADR_FUN 实现长跳转
汇编程序一个完整的例子:
ABC EQU 0x12
AREA Example , CODE , READONLY ;声明一个代码段 Example ENTRY ; 入口处
CODE32
ADR R0, THUMB_START + 1 ; 装载地址,并设置第0位为1
BX R0 ; 切换到THUMB状态
CODE 16 ; 声明 16位代码
THUMB_START
MOV R1, #ABC
ADD R1, R1 , #0x10
B THUMB_START
END
外围部件控制:在ARM核芯片中,其外围部件的控制寄存器,一般会设置“置位/复位”寄存器,这样可以方便的实现位操作,而不影响到其它位,操作示例如
下:
LDR R0 , =GPIO_BASE
MOV R1 , #0x00
STR R1 , [R0 , #0x04 ]
MOV R1 , #0x10
STR R1 , [R0 , #0x0C]
===================================================================== =============================
C与汇编混合编程
在需要C与汇编混合编程时,可使用直接内存汇编的方法混合编程,或者将汇编文件以文件的形式加入项目中
内嵌汇编的语法:
__asm
{
指令 [;指令] /*注释*/
......
[指令]
}
应用举例:
__inline void enable_IRQ(void)
{
int temp
__asm //嵌入汇编代码
{
MRS tmp , CPSR //读取CPSR的值
BIC tmp , tmp, #0x80 //IRQ中断禁止位I清零,即允许中断
MSR CPSR , tmp //设置CPSR的值
}
}
ARM编译器特定的关键词
__asm:告诉编译器下面的代码是用汇编写的
__inline:声明该函数在其被调用的地方展开
__irq:声明该函数可以被用做irq或者fiq异常的中断处理程序
__pure:声明一个函数,其结果仅仅依赖于其输入参数,而且它没有负效应
__int64:是long long 的同义词
__volatile:告诉编译器该对象可能在程序之外被修改
__weak:用于限定一个对象,该对象如果连接时不存在,不会报错
内嵌汇编的指令用法:
1、不能直接向PC寄存器赋值,程序跳转只能使用 B 或 BL指令实现,但是只有B可以使用C程序中的标号,BL不能
2、在内嵌汇编指令中,常量前面的 # 可以省略
3、所有的内存分配均由C编译器完成,内嵌汇编器不支持内嵌汇编程序用于内存分配的伪指令
以上的常见的注意事项
内嵌汇编器与armasm 汇编器的差异
1、内嵌汇编器不支持通过 " . " 指示符或 PC 获取当前指令地址,不支持LDR Rn , =expr伪指令
2、使用 Mov Rn , expr 指令向寄存器赋值,不支持标号表达式,不支持 ADR 和ADRL,不支持BX,不能向PC赋值
3、N、Z、C 和V标志中的C不具有真实意义
内存汇编还有一些注意事项:
1、不要使用寄存器代替变量,尽管有时候寄存器明显对应某个变量
int had_f (int x)
{
__asm
{
ADD R0,R0, #1 //发生寄存器冲突,实际上x的值没有变化
}
return(x) ;
}
使用 IMPORT 伪指令来引入全局变量,并利用LDR 和 STR 指令根据全局变量的地址访问它们
下面例子是一个汇编代码的函数,它读取全局变量 glovbvar,将其加1后返回
AREA globats , CODE , READONLY
EXPORT asmsubroutime
IMPORT glovbvar
asmsubroutime
LDR R1, =glovbvar
LDR R0, [R1]
ADD R0 , R0 , #1
STR R0 , [R1]
MOV PC , LR
END
C与汇编相互调用
寄存器的使用规则为:子程序间通过寄存器R0 - R3 来传递参数,使用 R4 - R11来保存局部变量, R12用作过程调用中间临时寄存器,记作 IP, R13用作堆栈指针,R14作为链接寄存器,记作 LR,R15是程序计数器
子程序参数传递规则:当寄存器不超过4个时,使用 R0 - R3来传递参数,当超过4个时,可以使用堆栈来传递参数,入栈的顺序与参数顺序相反,即最后一个字数据先入栈
子程序结果返回规则:结果为一个32位的整数时,可以通过寄存器R0返回,如果是64位,通过R0和R1返回,对于位数更多的结果,需要通过内存来传递
===================================================================== ============================
C语言调用汇编程序:在汇编程序中使用 EXPORT 伪指令声明本子程序,使其它程序可以调用子程序,在C语言程序中使用extern关键字声明外部函数(声明要调用的汇编子程序),即可调用此汇编子程序
C程序调用汇编程序例子如下:
被调用的汇编子程序代码:
AREA SCopy , CODE , READONLY
EXPORT strcopy ; 声明strcopy ,以便外部程序引用
strcopy
;R0 为目标字符串的地址
; R1 为源字符串的地址
LDRB R2,[R1] , #1 ; 读取字节数据,源地址加1
STRB R2,[R0], #1 ; 保存读取的1字节数据,目标地址加1
CMP R2, #0 ; 判断字符串是否复制完毕
BNE strcopy ; 没有复制完毕,继续循环
MOV PC,LR ; 返回
END
调用汇编的C函数:
Code:
===================================================================== ============================
汇编程序调用C程序:
在汇编程序中使用IMPORT伪指令声明将要调用的C程序函数,在调用C程序时,要正确设置入口参数,然后使用BL调用
C程序函数代码:
Code:
DSP汇编指令总结
DSP汇编指令总结 一、寻址方式: 1、立即寻址: 短立即寻址(单指令字) 长立即数寻址(双指令字) 第一指令字 第二指令字 16位常数=16384=4000h 2、直接寻址 ARU 辅助寄存器更新代码,决定当前辅助寄存器是否和如何进行增或减。N规定是否改变ARP值,(N=0,不变)
4.3.1、算术逻辑指令(28条) 4.3.1.1、加法指令(4条); 4.3.1.2、减法指令(5条); 4.3.1.3、乘法指令(2条); 4.3.1.4、乘加与乘减指令(6条); 4.3.1.5、其它算数指令(3条); 4.3.1.6、移位和循环移位指令(4条); 4.3.1.7、逻辑运算指令(4条); 4.3.2、寄存器操作指令(35条) 4.3.2.1、累加器操作指令(6条) 4.3.2.2、临时寄存器指令(5条) 4.3.2.3、乘积寄存器指令(6条) 4.3.2.4、辅助寄存器指令(5条) 4.3.2.5、状态寄存器指令(9条) 4.3.2.6、堆栈操作指令(4条) 4.3.3、存储器与I/O操作指令(8条)4.3.3.1、数据移动指令(4条) 4.3.3.2、程序存储器读写指令(2条) 4.3.3.3、I/O操作指令(2条) 4.3.4、程序控制指令(15条) 4.3.4.1、程序分支或调用指令(7条) 4.3.4.2、中断指令(3条) 4.3.4.3、返回指令(2条) 4.3.4.4、其它控制指令(3条)
4.3.1、算术逻辑指令(28条) 4.3.1.1、加法指令(4条); ▲ADD ▲ADDC(带进位加法指令) ▲ADDS(抑制符号扩展加法指令) ▲ADDT(移位次数由TREG指定的加法指令) 4.3.1.2、减法指令(5条); ★SUB(带移位的减法指令) ★SUBB(带借位的减法指令) ★SUBC(条件减法指令) ★SUBS(减法指令) ★SUBT(带移位的减法指令,TREG决定移位次数)4.3.1.3、乘法指令(2条); ★MPY(带符号乘法指令) ★MPYU(无符号乘法指令) 4.3.1.4、乘加与乘减指令(6条); ★MAC(累加前次积并乘)(字数2,周期3) ★MAC(累加前次积并乘) ★MPYA(累加-乘指令) ★MPYS(减-乘指令) ★SQRA(累加平方值指令) ★SQRS(累减并平方指令) 4.3.1.5、其它算数指令(3条); ★ABS(累加器取绝对值指令) ★NEG(累加器取补码指令) ★NORM(累加器规格化指令) 返回 4.3.1.6、移位和循环移位指令(4条); ▲ SFL(累加器内容左移指令) ▲ SFR(累加器内容右移指令) ▲ROL(累加器内容循环左移指令) ▲ROR(累加器内容循环右移指令) 返回 4.3.1.7、逻辑运算指令(4条); ▲ AND(逻辑与指令) ▲ OR(逻辑或指令) ▲ XOR(逻辑异或指令) ▲ CMPL(累加器取反指令) 返回 4.3.2、寄存器操作指令(35条) 4.3.2.1、累加器操作指令(6条)
(完整word版)汇编语言常用指令大全,推荐文档
MOV指令为双操作数指令,两个操作数中必须有一个是寄存器. MOV DST , SRC // Byte / Word 执行操作: dst = src 1.目的数可以是通用寄存器, 存储单元和段寄存器(但不允许用CS段寄存器). 2.立即数不能直接送段寄存器 3.不允许在两个存储单元直接传送数据 4.不允许在两个段寄存器间直接传送信息 PUSH入栈指令及POP出栈指令: 堆栈操作是以“后进先出”的方式进行数据操作. PUSH SRC //Word 入栈的操作数除不允许用立即数外,可以为通用寄存器,段寄存器(全部)和存储器. 入栈时高位字节先入栈,低位字节后入栈. POP DST //Word 出栈操作数除不允许用立即数和CS段寄存器外, 可以为通用寄存器,段寄存器和存储器. 执行POP SS指令后,堆栈区在存储区的位置要改变. 执行POP SP 指令后,栈顶的位置要改变. XCHG(eXCHanG)交换指令: 将两操作数值交换. XCHG OPR1, OPR2 //Byte/Word 执行操作: Tmp=OPR1 OPR1=OPR2 OPR2=Tmp 1.必须有一个操作数是在寄存器中 2.不能与段寄存器交换数据 3.存储器与存储器之间不能交换数据. XLAT(TRANSLATE)换码指令: 把一种代码转换为另一种代码. XLAT (OPR 可选) //Byte 执行操作: AL=(BX+AL) 指令执行时只使用预先已存入BX中的表格首地址,执行后,AL中内容则是所要转换的代码. LEA(Load Effective Address) 有效地址传送寄存器指令 LEA REG , SRC //指令把源操作数SRC的有效地址送到指定的寄存器中. 执行操作: REG = EAsrc 注: SRC只能是各种寻址方式的存储器操作数,REG只能是16位寄存器 MOV BX , OFFSET OPER_ONE 等价于LEA BX , OPER_ONE MOV SP , [BX] //将BX间接寻址的相继的二个存储单元的内容送入SP中 LEA SP , [BX] //将BX的内容作为存储器有效地址送入SP中 LDS(Load DS with pointer)指针送寄存器和DS指令 LDS REG , SRC //常指定SI寄存器。 执行操作: REG=(SRC), DS=(SRC+2) //将SRC指出的前二个存储单元的内容送入指令中指定的寄存器中,后二个存储单元送入DS段寄存器中。
(完整word版)汇编语言指令集合-吐血整理,推荐文档
8086/8088指令系统记忆表 数据寄存器分为: AH&AL=AX(accumulator):累加寄存器,常用于运算;在乘除等指令中指定用来存放操作数,另外,所有的I/O指令都使用这一寄存器与外界设备传送数据. BH&BL=BX(base):基址寄存器,常用于地址索引; CH&CL=CX(count):计数寄存器,常用于计数;常用于保存计算值,如在移位指令,循环(loop)和串处理指令中用作隐含的计数器. DH&DL=DX(data):数据寄存器,常用于数据传递。他们的特点是,这4个16位的寄存器可以分为高8位: AH, BH, CH, DH.以及低八位:AL,BL,CL,DL。这2组8位寄存器可以分别寻址,并单独使用。 另一组是指针寄存器和变址寄存器,包括: SP(Stack Pointer):堆栈指针,与SS配合使用,可指向目前的堆栈位置; BP(Base Pointer):基址指针寄存器,可用作SS的一个相对基址位置; SI(Source Index):源变址寄存器可用来存放相对于DS段之源变址指针; DI(Destination Index):目的变址寄存器,可用来存放相对于ES 段之目的变址指针。 指令指针IP(Instruction Pointer) 标志寄存器FR(Flag Register) OF(overflow flag) DF(direction flag) CF(carrier flag) PF(parity flag) AF(auxiliary flag) ZF(zero flag) SF(sign flag) IF(interrupt flag) TF(trap flag) 段寄存器(Segment Register) 为了运用所有的内存空间,8086设定了四个段寄存器,专门用来保存段地址: CS(Code Segment):代码段寄存器; DS(Data Segment):数据段寄存器; SS(Stack Segment):堆栈段寄存器;
AVRmega8汇编指令汇总.
指令集概述 指令操作数说明操作标志 # 时钟数 算数和逻辑指令 ADD Rd, Rr 无进位加法Rd ← Rd + Rr Z,C,N,V,H 1 ADC Rd, Rr 带进位加法Rd ← Rd + Rr + C Z,C,N,V,H 1 ADIW Rdl,K 立即数与字相加Rdh:Rdl ← Rdh:Rdl + K Z,C,N,V,S 2 SUB Rd, Rr 无进位减法Rd ← Rd - Rr Z,C,N,V,H 1 SUBI Rd, K 减立即数Rd ← Rd - K Z,C,N,V,H 1 SBC Rd, Rr 带进位减法Rd ← Rd - Rr - C Z,C,N,V,H 1 SBCI Rd, K 带进位减立即数Rd ← Rd - K - C Z,C,N,V,H 1 SBIW Rdl,K 从字中减立即数Rdh:Rdl ← Rdh:Rdl - K Z,C,N,V,S 2 AND Rd, Rr 逻辑与Rd ← Rd ? Rr Z,N,V 1 ANDI Rd, K 与立即数的逻辑与操作Rd ← Rd ? K Z,N,V 1 OR Rd, Rr 逻辑或Rd ← Rd v Rr Z,N,V 1 ORI Rd, K 与立即数的逻辑或操作Rd ← Rd v K Z,N,V 1 EOR Rd, Rr 异或Rd ← Rd ⊕ Rr Z,N,V 1 COM Rd 1 的补码Rd ← 0xFF ? Rd Z,C,N,V 1 NEG Rd 2 的补码Rd ← 0x00 ? Rd Z,C,N,V,H 1 SBR Rd,K 设置寄存器的位Rd ← Rd v K Z,N,V 1
CBR Rd,K 寄存器位清零Rd ← Rd ? (0xFF - K Z,N,V 1 INC Rd 加一操作Rd ← Rd + 1 Z,N,V 1 DEC Rd 减一操作Rd ← Rd ? 1 Z,N,V 1 TST Rd 测试是否为零或负Rd ← Rd ? Rd Z,N,V 1 CLR Rd 寄存器清零Rd ← Rd ⊕ Rd Z,N,V 1 SER Rd 寄存器置位Rd ← 0xFF None 1 MUL Rd, Rr 无符号数乘法R1:R0 ← Rd x Rr Z,C 2 MULS Rd, Rr 有符号数乘法R1:R0 ← Rd x Rr Z,C 2 MULSU Rd, Rr 有符号数与无符号数乘法 R1:R0 ← Rd x Rr Z,C 2 FMUL Rd, Rr 无符号小数乘法R1:R0 ← (Rd x Rr << 1 Z,C 2 FMULS Rd, Rr 有符号小数乘法R1:R0 ← (Rd x Rr << 1 Z,C 2 FMULSU Rd, Rr 有符号小数与无符号小数乘法R1:R0 ← (Rd x Rr << 1 Z,C 2跳转指令 RJMP k 相对跳转PC ← PC + k + 1 无 2 IJMP 间接跳转到(Z PC ← Z 无 2 RCALL k 相对子程序调用PC ← PC + k + 1 无 3 ICALL 间接调用(Z PC ← Z 无 3 RET 子程序返回PC ← STACK 无 4 RETI 中断返回PC ← STACK I 4
汇编语言指令汇总
汇编语言程序设计资料简汇 通用寄存器 8位通用寄存器8个:AL、AH、BL、BH、CL、CH、DL、DH。 16位通用寄存器8个:AX、BX、CX、DX、SI、DI、BP、SP。 AL与AH、BL与BH、CL与CH、DL与DH分别对应于AX、BX、CX和DX的低8位与高8位。专用寄存器 指令指针:IP(16位)。 标志寄存器:没有助记符(FLAGS 16位)。 段寄存器 段寄存器:CS、DS、ES、SS。 内存分段:80x86采用分段内存管理机制,主要包括下列几种类型的段: ?代码段:用来存放程序的指令序列。 ?数据段:用来存放程序的数据。 ?堆栈段:作为堆栈使用的内存区域,用来存放过程返回地址、过程参数等。 物理地址与逻辑地址 ?物理地址:内存单元的实际地址,也就是出现在地址总线上的地址。 ?逻辑地址:或称分段地址。 ?段地址与偏移地址都是16位。 ?系统采用下列方法将逻辑地址自动转换为20位的物理地址: 物理地址= 段地址×16 + 偏移地址 ?每个内存单元具有唯一的物理地址,但可由不同的逻辑地址描述。 与数据有关的寻址方式 立即寻址方式 立即寻址方式所提供的操作数紧跟在操作码的后面,与操作码一起放在指令代码段中。立即数可以是8位数或16位数。如果是16位数,则低位字节存放在低地址中,高位字节存放在高地址中。 例:MOV AL,18 指令执行后,(AL)= 12H 寄存器寻址方式 在寄存器寻址方式中,操作数包含于CPU的内部寄存器之中。这种寻址方式大都用于寄存器之间的数据传输。 例3:MOV AX,BX 如指令执行前(AX)= 6789H,(BX)= 0000H;则指令执行后,(AX)= 0000H,(BX)保持不变。 直接寻址方式 直接寻址方式是操作数地址的16位偏移量直接包含在指令中,和指令操作码一起放在代码段,而操作数则在数据段中。操作数的地址是数据段寄存器DS中的内容左移4位后,加上指令给定的16位地址偏移量。直接寻址方式适合于处理单个数据变量。 寄存器间接寻址方式 在寄存器间接寻址方式中,操作数在存储器中。操作数的有效地址由变址寄存器SI、DI或基址寄存器BX、BP提供。 如果指令中指定的寄存器是BX、SI、DI,则用DS寄存器的内容作为段地址。 如指令中用BP寄存器,则操作数的段地址在SS中,即堆栈段。
常用汇编指令表
1. 通用数据传送指令. MOV 传送字或字节. MOVSX 先符号扩展,再传送. MOVZX 先零扩展,再传送. PUSH 把字压入堆栈. POP 把字弹出堆栈. PUSHA 把AX,CX,DX,BX,SP,BP,SI,DI依次压入堆栈. POPA 把DI,SI,BP,SP,BX,DX,CX,AX依次弹出堆栈. PUSHAD 把EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI依次压入堆栈. POPAD 把EDI,ESI,EBP,ESP,EBX,EDX,ECX,EAX依次弹出堆栈. BSWAP 交换32位寄存器里字节的顺序 XCHG 交换字或字节.( 至少有一个操作数为寄存器,段寄存器不可作为操作数) CMPXCHG 比较并交换操作数.( 第二个操作数必须为累加器AL/AX/EAX ) XADD 先交换再累加.( 结果在第一个操作数里) XLAT 字节查表转换. —— BX 指向一张256 字节的表的起点, AL 为表的索引值(0-255,即 0-FFH); 返回AL 为查表结果. ( [BX+AL]->AL ) 2. 输入输出端口传送指令. IN I/O端口输入. ( 语法: IN 累加器, {端口号│DX} ) OUT I/O端口输出. ( 语法: OUT {端口号│DX},累加器) 输入输出端口由立即方式指定时, 其范围是0-255; 由寄存器DX 指定时, 其范围是0-65535. 3. 目的地址传送指令. LEA 装入有效地址. 例: LEA DX,string ;把偏移地址存到DX. LDS 传送目标指针,把指针内容装入DS. 例: LDS SI,string ;把段地址:偏移地址存到DS:SI. LES 传送目标指针,把指针内容装入ES. 例: LES DI,string ;把段地址:偏移地址存到ES:DI.
汇编指令大全
ORG 0000H NOP ;空操作指令 AJMP L0003 ;绝对转移指令 L0003: LJMP L0006 ;长调用指令 L0006: RR A ;累加器A内容右移(先置A为88H) INC A ; 累加器A 内容加1 INC 01H ;直接地址(字节01H)内容加1 INC @R0 ; R0的内容(为地址) 的内容即间接RAM加1 ;(设R0=02H,02H=03H,单步执行后02H=04H) INC @R1 ; R1的内容(为地址) 的内容即间接RAM加1 ;(设R1=02H,02H=03H,单步执行后02H=04H) INC R0 ; R0的内容加1 (设R0为00H,单步执行后查R0内容为多少) INC R1 ; R1的内容加1(设R1为01H,单步执行后查R1内容为多少) INC R2 ; R2的内容加1 (设R2为02H,单步执行后查R2内容为多少) INC R3 ; R3的内容加1(设R3为03H,单步执行后查R3内容为多少) INC R4 ; R4的内容加1(设R4为04H,单步执行后查R4内容为多少) INC R5 ; R5的内容加1(设R5为05H,单步执行后查R5内容为多少) INC R6 ; R6的内容加1(设R6为06H,单步执行后查R6内容为多少) INC R7 ; R7的内容加1(设R7为07H,单步执行后查R7内容为多少) JBC 20H,L0017; 如果位(如20H,即24H的0位)为1,则转移并清0该位L0017: ACALL S0019 ;绝对调用 S0019: LCALL S001C ;长调用 S001C: RRC A ;累加器A的内容带进位位右移(设A=11H,C=0 ;单步执行后查A和C内容为多少) DEC A ;A的内容减1 DEC 01H ;直接地址(01H)内容减1 DEC @R0 ;R0间址减1,即R0的内容为地址,该地址的内容减1 DEC @R1 ; R1间址减1 DEC R0 ; R0内容减1 DEC R1 ; R1内容减1 DEC R2 ; R2内容减1 DEC R3 ; R3内容减1 DEC R4 ; R4内容减1 DEC R5 ; R5内容减1 DEC R6 ; R6内容减1 DEC R7 ; R7内容减1 JB 20H,L002D;如果位(20H,即24H的0位)为1则转移 L002D: AJMP L0017 ;绝对转移 RET ;子程序返回指令 RL A ;A左移 ADD A,#01H ;A的内容与立即数(01H)相加 ADD A,01H ; A的内容与直接地址(01H内容)相加 ADD A,@R0 ; A的内容与寄存器R0的间址内容相加 ADD A,@R1 ; A的内容与寄存器R1的间址内容相加
汇编指令大全
汇编指令大全 (DST:destination目的操作数/地址;SRC:source源操作数/地址;port:端口;ac:Accumulator累加器;reg:register寄存器;cnt:counter计数器;opr:除了立即数之外的所有寻址方式(寄存器);立即数:直接包含在代码中,作为代码的一部分,不需要保存在寄存器中的操作数,相当于高级语言中的常量;r8/r16:8位通用寄存器/16位通用寄存器;SR:segment register段寄存器,包括DS、SS、ES、CS;mem:memory,表示存储器操作数;addr:address,表示内存单元地址;) [数据传送指令] 一、通用数据传送指令 1、传送指令 MOV (move) 指令的汇编格式:MOV DST,SRC 指令的基本功能:(DST)←(SRC) 将原操作数(字节或字)传送到目的地址。 指令支持的寻址方式:目的操作数和源操作数不能同时用存储器寻址方式,这个限制适用于所有指令。 指令的执行对标志位的影响:不影响标志位。 指令的特殊要求:目的操作数DST和源操作数SRC不允许同时为段寄存器; 目的操作数DST不能是CS,也不能用立即数方式。 2、进栈指令 PUSH (push onto the stack) 出栈指令 POP (pop from the stack) 指令的汇编格式:PUSH SRC ;POP DST 指令的基本功能:PUSH指令在程序中常用来暂存某些数据,而POP指令又可将这些数据恢复。 PUSH SRC (SP)←(SP)-2 ;(SP)←(SRC) POP DST (DST)←((SP));(SP)←(SP) 指令支持的寻址方式:push 和 pop指令不能不能使用立即数寻址方式。 指令对标志位的影响:PUSH 和 POP指令都不影响标志位。 指令的特殊要求:PUSH 和 POP指令只能是字操作,因此,存取字数据后,SP的修改必须是+2 或者 -2;POP指令的DST不允许是CS寄存器; 3、交换指令 XCHG (exchange) 指令的汇编格式:XCHG OPR1,OPR2 指令的基本功能:(OPR1)←>(OPR2) 指令支持的寻址方式:一个操作数必须在寄存器中,另一个操作数可以在寄存器或存储器中。 指令对标志位的影戏:不影响标志位。 指令的特殊要求:不允许使用段寄存器。 二、累加器专用传送指令 4、输入指令 IN (input) 输出指令 OUT(output) 指令的汇编格式:IN ac,port port<=0FFH IN ac,DX port>0FFH OUT port,ac port<=0FFH OUT DX,ac port>0FFH 指令的基本功能:对8086及其后继机型的微处理机,所有I/O端口与CPU之间的通信都由输入输出指令IN和OUT来完成。IN指令将信息从I/O输入到CPU,OUT指令将信息从CPU输出到I/O端口,因此,IN和OUT指令都要指出I/O端口地址。 IN ac,port port<=0FFH (AL)←(port)传送字节或(AX)←(port+1,port)传送字 IN ac,DX port>0FFH (AL)←((DX))传送字节或(AX)←((DX)+1,(DX))传送字 OUT port,ac port<=0FFH (port)←(AL)传送字节或(port+1,port)←(AX)传送字 OUT DX,ac port>0FFH (DX)←(AL)传送字节或((DX)+1,(DX))←(AX)传送字 指令对标志位的影响:不影响标志位。 指令的特殊要求:只限于在AL或AX与I/O端口之间传送信息。 传送16位信息用AX,传送8位信息用AL,这取决于外设端口的宽度。
微型计算机汇编指令大全
数据传送指令集 MOV 功能: 把源操作数送给目的操作数 语法: MOV 目的操作数,源操作数 格式: MOV r1,r2 MOV r,m MOV m,r MOV r,data XCHG 功能: 交换两个操作数的数据 语法: XCHG 格式: XCHG r1,r2 XCHG m,r XCHG r,m PUSH,POP 功能: 把操作数压入或取出堆栈 语法: PUSH 操作数POP 操作数 格式: PUSH r PUSH M PUSH data POP r POP m PUSHF,POPF,PUSHA,POPA 功能: 堆栈指令群 格式: PUSHF POPF PUSHA POPA LEA,LDS,LES 功能: 取地址至寄存器 语法: LEA r,m LDS r,m LES r,m XLAT(XLATB) 功能: 查表指令 语法: XLAT XLAT m 算数运算指令 ADD,ADC 功能: 加法指令 语法: ADD OP1,OP2 ADC OP1,OP2 格式: ADD r1,r2 ADD r,m ADD m,r ADD r,data 影响标志: C,P,A,Z,S,O SUB,SBB 功能:减法指令 语法: SUB OP1,OP2 SBB OP1,OP2 格式: SUB r1,r2 SUB r,m SUB m,r SUB r,data SUB m,data 影响标志: C,P,A,Z,S,O
INC,DEC 功能: 把OP的值加一或减一 语法: INC OP DEC OP 格式: INC r/m DEC r/m 影响标志: P,A,Z,S,O NEG 功能: 将OP的符号反相(取二进制补码) 语法: NEG OP 格式: NEG r/m 影响标志: C,P,A,Z,S,O MUL,IMUL 功能: 乘法指令 语法: MUL OP IMUL OP 格式: MUL r/m IMUL r/m 影响标志: C,P,A,Z,S,O(仅IMUL会影响S标志) DIV,IDIV 功能:除法指令 语法: DIV OP IDIV OP 格式: DIV r/m IDIV r/m CBW,CWD 功能: 有符号数扩展指令 语法: CBW CWD AAA,AAS,AAM,AAD 功能: 非压BCD码运算调整指令 语法: AAA AAS AAM AAD 影响标志: A,C(AAA,AAS) S,Z,P(AAM,AAD) DAA,DAS 功能: 压缩BCD码调整指令 语法: DAA DAS 影响标志: C,P,A,Z,S 位运算指令集 AND,OR,XOR,NOT,TEST 功能: 执行BIT与BIT之间的逻辑运算 语法: AND r/m,r/m/data OR r/m,r/m/data XOR r/m,r/m/data TEST r/m,r/m/data NOT r/m 影响标志: C,O,P,Z,S(其中C与O两个标志会被设为0) NOT指令不影响任何标志位SHR,SHL,SAR,SAL 功能: 移位指令 语法: SHR r/m,data/CL SHL r/m,data/CL SAR r/m,data/CL SAL r/m,data/CL
汇编指令大全[pdf阅读版]
汇编指令大全 一、数据传输指令 ───────────────────────────────────────它们在存贮器和寄存器、寄存器和输入输出端口之间传送数据.汇编指令大全 1.通用数据传送指令. MOV传送字或字节. MOVSX先符号扩展,再传送. MOVZX先零扩展,再传送. PUSH把字压入堆栈. POP把字弹出堆栈. PUSHA把AX,CX,DX,BX,SP,BP,SI,DI依次压入堆栈. POPA把DI,SI,BP,SP,BX,DX,CX,AX依次弹出堆栈. PUSHAD把EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI依次压入堆栈. POPAD把EDI,ESI,EBP,ESP,EBX,EDX,ECX,EAX依次弹出堆栈. BSWAP交换32位寄存器里字节的顺序 XCHG交换字或字节.(至少有一个操作数为寄存器,段寄存器不可作为操作数) CMPXCHG比较并交换操作数.(第二个操作数必须为累加器AL/AX/EAX) XADD先交换再累加.(结果在第一个操作数里) XLAT字节查表转换. ──BX指向一张256字节的表的起点,AL为表的索引值(0-255,即0-FFH);返回AL为查表结果.([BX+AL]->AL) 2.输入输出端口传送指令. IN I/O端口输入.(语法:IN累加器,{端口号│DX}) OUT I/O端口输出.(语法:OUT{端口号│DX},累加器) 输入输出端口由立即方式指定时,其范围是0-255;由寄存器DX指定时, 其范围是0-65535. 3.目的地址传送指令. LEA装入有效地址. 例:LEA DX,string;把偏移地址存到DX. LDS传送目标指针,把指针内容装入DS. 例:LDS SI,string;把段地址:偏移地址存到DS:SI. LES传送目标指针,把指针内容装入ES. 例:LES DI,string;把段地址:偏移地址存到ES:DI. LFS传送目标指针,把指针内容装入FS. 例:LFS DI,string;把段地址:偏移地址存到FS:DI. LGS传送目标指针,把指针内容装入GS. 例:LGS DI,string;把段地址:偏移地址存到GS:DI. LSS传送目标指针,把指针内容装入SS. 例:LSS DI,string;把段地址:偏移地址存到SS:DI.
汇编语言最全指令表
伪指令? 1、定位伪指令 ORG m ?2、定义字节伪指令 DB X1,X2,X3,…,Xn ?3、字定义伪指令 DW Y1,Y2,Y3,…,Yn 4、汇编结束伪指令 END 寻址方式 MCS-51单片机有五种寻址方式: 1、寄存器寻址 2、寄存器间接寻址 3、直接寻址 4、立即数寻址 5、基寄存器加变址寄存器间接寻址 6、相对寻址 7、位寻址 数据传送指令 一、以累加器A为目的操作数的指令(4条) ?MOV A,Rn ;(Rn)→A n=0~7 ?MOV A,direct ;(direct )→A ?MOV A,@Ri ;((Ri))→A i=0~1 ?MOV A,#data ;data →A 二、以Rn为目的操作数的指令(3条) MOV Rn ,A;(A)→ Rn MOV Rn ,direct;(direct )→ Rn MOV Rn ,#data;data → Rn ?三、以直接寻址的单元为目的操作数的指令(5条) MOV direct,A;(A)→direct MOV direct,Rn;(Rn)→direct MOV direct,direct ;(源direct)→目的direct MOV direct,@Ri;((Ri))→direct MOV direct,#data;data→direct 四、以寄存器间接寻址的单元为目的操作数的指令(3条) MOV @Ri,A;(A)→(Ri) MOV @Ri,direct;(direct)→(Ri) MOV @Ri,#data;data→(Ri) 五、十六位数据传送指令(1条) MOV DPTR,#data16;dataH→DPH,dataL →DPL 六、堆栈操作指令
汇编指令大全汇总
一、数据传输指令 1. 通用数据传送指令. MOV 传送字或字节. MOVSX先符号扩展,再传送. MOVZX先零扩展,再传送. PUSH把字压入堆栈. POP把字弹出堆栈. PUSHA把AX,CX,DX,BX,SP,BP,SI,DI依次压入堆栈. POPA把DI,SI,BP,SP,BX,DX,CX,AX依次弹出堆栈. PUSHAD把EAX,ECX,EDX,EBX,ESP,EBP,ESI, EDI依次压入堆栈. POPAD把EDI,ESI,EBP,ESP,EBX,EDX,ECX, EAX依次弹出堆栈. BSWAP交换32位寄存器里字节的顺序 XCHG交换字或字节.( 至少有一个操作数为寄存器,段寄存器不可作为操作数) CMPXCHG 比较并交换操作数.( 第二个操作数必须为累加器AL/AX/EAX ) XADD先交换再累加.( 结果在第一个操作数里) XLAT字节查表转换. ──BX 指向一张256 字节的表的起点, AL 为表的索引值(0-255,即0-FFH); 返回AL 为查表结果. ( [BX+AL]->AL ) 2. 输入输出端口传送指令. IN I/O端口输入. ( 语法: IN 累加器, ) OUT I/O端口输出. ( 语法: OUT ,累加器) 输入输出端口由立即方式指定时, 其范围是0-255; 由寄存器DX 指定时, 其范围是0-65535. 3. 目的地址传送指令. LEA装入有效地址. 例: LEA DX,string;把偏移地址存到DX. LDS传送目标指针,把指针内容装入DS. 例: LDS SI,string;把段地址:偏移地址存到DS:SI. LES传送目标指针,把指针内容装入ES. 例: LES DI,string;把段地址:偏移地址存到ES:DI. LFS传送目标指针,把指针内容装入FS. 例: LFS DI,string;把段地址:偏移地址存到FS:DI. LGS传送目标指针,把指针内容装入GS. 例: LGS DI,string;把段地址:偏移地址存到GS:DI. LSS传送目标指针,把指针内容装入SS. 例: LSS DI,string;把段地址:偏移地址存到SS:DI. 4. 标志传送指令. LAHF标志寄存器传送,把标志装入AH. SAHF标志寄存器传送,把AH内容装入标志寄存器. PUSHF标志入栈. POPF标志出栈. PUSHD32位标志入栈. POPD32位标志出栈. 二、算术运算指令 ─────────────────────────────────────── ADD加法. ADC带进位加法. INC加1. AAA加法的ASCII码调整. DAA加法的十进制调整. SUB减法. SBB带借位减法. DEC减1. NEC求反(以0 减之). CMP比较.(两操作数作减法,仅修改标志位,不回送结果). AAS减法的ASCII码调整. DAS减法的十进制调整. MUL无符号乘法. IMUL整数乘法. 以上两条,结果回送AH和AL(字节运算),或DX和AX(字运算).
汇编指令大全(完整版有注释)
汇编指令大全(有注释) 一、数据传输指令 ───────────────────────────────────────它们在存贮器和寄存器、寄存器和输入输出端口之间传送数据. 1. 通用数据传送指令. MOV 传送字或字节. MOVSX 先符号扩展,再传送. MOVZX 先零扩展,再传送. PUSH 把字压入堆栈. POP 把字弹出堆栈. PUSHA 把AX,CX,DX,BX,SP,BP,SI,DI依次压入堆栈. POPA 把DI,SI,BP,SP,BX,DX,CX,AX依次弹出堆栈. PUSHAD 把EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI依次压入堆栈. POPAD 把EDI,ESI,EBP,ESP,EBX,EDX,ECX,EAX依次弹出堆栈. BSWAP 交换32位寄存器里字节的顺序 XCHG 交换字或字节.( 至少有一个操作数为寄存器,段寄存器不可作为操作数) CMPXCHG 比较并交换操作数.( 第二个操作数必须为累加器AL/AX/EAX ) XADD 先交换再累加.( 结果在第一个操作数里) XLAT 字节查表转换. ── BX 指向一张256 字节的表的起点, AL 为表的索引值(0-255,即 0-FFH); 返回AL 为查表结果. ( [BX+AL]->AL ) 2. 输入输出端口传送指令. IN I/O端口输入. ( 语法: IN 累加器, {端口号│DX} ) OUT I/O端口输出. ( 语法: OUT {端口号│DX},累加器) 输入输出端口由立即方式指定时, 其范围是0-255; 由寄存器DX 指定时, 其范围是0-65535. 3. 目的地址传送指令. LEA 装入有效地址. 例: LEA DX,string ;把偏移地址存到DX. LDS 传送目标指针,把指针内容装入DS. 例: LDS SI,string ;把段地址:偏移地址存到DS:SI. LES 传送目标指针,把指针内容装入ES. 例: LES DI,string ;把段地址:偏移地址存到ES:DI. LFS 传送目标指针,把指针内容装入FS. 例: LFS DI,string ;把段地址:偏移地址存到FS:DI. LGS 传送目标指针,把指针内容装入GS. 例: LGS DI,string ;把段地址:偏移地址存到GS:DI. LSS 传送目标指针,把指针内容装入SS. 例: LSS DI,string ;把段地址:偏移地址存到SS:DI. 4. 标志传送指令. LAHF 标志寄存器传送,把标志装入AH. SAHF 标志寄存器传送,把AH内容装入标志寄存器. PUSHF 标志入栈.
汇编语言指令大全
AAA 未组合的十进制加法调整 指令 AAA(ASCII Adgust for Addition) 格式: AAA 功能: 对两个组合的十进 制数相加运算(存在AL中) 的结果进行调整,产生一个 未组合的十进制数放在AX 中. 说明: 1. 组合的十进制数和未组合的十进制数:在计算中,十进制数可用四位二进制数编码,称为BCD码. 当一个节(8位)中存放一位BCD码,且放在字节的低4位, 高4位为时称为未组合的BCD码. 2. AAA的调整操作 若(AL) and 0FH>9 或 AF=1,则调整如下: (AL)<--(AL)+6,(AH)<--(AH)+1,AF=1,CF<--AF,(AL)<--(AL) and 0FH AAD 未组合十进制数除法调整 指令 AAD(ASCII Adjust for Division) 格式: AAD 功能: 在除法指令前对AX 中的两个未组合十进制数 进行调整,以便能用DIV指 令实现两个未组合的十进 制数的除法运算,其结果为 未组合的十进制数,商(在 AL中)和余数(在AH中). 说明: 1. AAD指令是在执行除法DIV之前使用的,以便得到二进制结果存于AL中,然后除以OPRD,得到的商在AL中,余数在AH 中. 2. 示例: MOV BL,5 MOV AX,0308H AAD ;(AL)<--1EH+08H=26H,(AH)<--0 DIV BL ;商=07H-->(AL),余数=03H-->(AH). AAM 未组合十进制数乘法调整 指令 AAM(ASCII Adjust MULtiply) 格式: AAM 功能: 对两个未组合的十 进制数相乘后存于AX中的 结果进行调整,产生一个未 组合的十进制数存在AL中. 说明: 1. 实际上是两个未组合的十进制数字节相乘,一个0~9的数与另一个0~9的数相乘其积最大为81.为了得到正确的结果,应进行如下调整: 乘积: (AH)<--(AL)/10 (AL)<--(AL)MOD10 2. 本指令应跟在MUL指令后使用,乘积的两位十进制结果,高位放在AH中,低位放在AL中.AH内容是MUL指令的结果被10除的商,即(AL)/10,而最后的AL内容是乘积被10整除的余数(即个位数). AAS 未组合十进制减法调整指 令 AAS(ASCII Adjust for Subtraction) 格式: AAS 功能: 对两个未组合十进 制数相减后存于AL中的结 果进行调整,调整后产生一 个未组合的十进制数数且 仍存于AL中. 说明: 1. 本指令影响标志位CF及AF. 2. 调整操作 若(AL) and 0FH > 9 或 AF=1 则(AL)<--(AL)-6,(AH)<--(AH)-1,CF<--AF,(AL)<--(AL) and 0FH, 否则(AL)<--(AL) and 0FH ADC 带进位加法指令 ADC(Addition Carry) 格式: ADC OPRD1,OPRD2 功能: OPRD1<--OPRD1 + OPRD2 + CF 说明: 1. OPRD1为任一通用寄存器或存储器操作数,可以是任意一 个通用寄存器,而且还可以是任意一个存储器操作数. OPRD2为立即数,也可以是任意一个通用寄存器操作数.立即 数只能用于源操作数. 2. OPRD1和OPRD2均为寄存器是允许的,一个为寄存器而另 一个为存储器也是允许的,但不允许两个都是存储器操作数. 3. 加法指令运算的结果对CF、SF、OF、PF、ZF、AF都会有影响.以上标志也称为结果标志. 4. 该指令对标志位的影响同ADD指令. ADD 加法指令 ADD(Addition) 格式: ADD OPRD1,OPRD2 功能: 两数相加说明: 1. OPRD1为任一通用寄存器或存储器操作数,可以是任意一个通用寄存器,而且还可以是任意一个存储器操作数. OPRD2为立即数,也可以是任意一个通用寄存器操作数.立即数只能用于源操作数. 2. OPRD1和OPRD2均为寄存器是允许的,一个为寄存器而另一个为存储器也是允许的, 但不允许两个都是存储器操作数. 3. 加法指令运算的结果对CF、SF、OF、PF、ZF、AF都会有影响.以上标志也称为结果标志.加法指令适用于无符号数或
8086汇编指令大全
8086汇编指令大全 标志寄存器:9个有效位,分6个状态寄存器和3个控制寄存器 CF 当执行一个加法(减法)使最高位产生进位(借位)时CF=1 否则CF=0 PF 指令执行的结果低8位有偶数个一时,CF=1 否则CF=0 AF 当执行一个加法(减法)使运算结果低4位向高4位有进位(借位)时AF=1 否则AF+0 ZF 当前运算结果为零,ZF=1 否则ZF=0 SF 符号标志位 OF 溢出标志位 DF 方向标志位 IF 中断允许位IF=1时响应外部中断 TF 跟踪标志位 操作数:[目的操作数(OPD),源操作数(OPS)] ;立即操作数,寄存器操作数,存储器操作数。 寻址方式: 1) 寄存器寻址例:INC AX;MOV AX,BX 2) 寄存器间接寻址(寄存器只能是BX,DI,SI,BP);[PA=(BX、DI、SI)+DS》4)或BP+SS》4]
3) 寄存器相对寻址 4) 基址变址寻址 5) 相对基址变址寻址 6) 直接寻址 7) 立即数寻址 i. 立即数寻址立即数寻址不能用在单操作数指令中 ii. 在双操作数中,立即数寻址方式不能用于目的操作数字段 指令系统: 1) 数据传送指令mov 注意: 不允许在两个存储单元之间直接传送数据 不允许在两个段寄存器之间传送数据 不允许用立即数直接为段寄存器赋值 不影响标志位 不允许寄存器或存储单元到除CS外的段寄存器 2) 入栈(出栈)指令PUSH(POP) 注意: PUSH操作数不能是“立即数”POP操作数不能是段寄存器CS 不影响标志位 先进后出
单操作符 3) 交换指令XCHG 注意: 只允许寄存器与存储单元之间的交换 不影响标志位 4) 换码指令XLAT 5) 地址传送指令LEA(load effective address):偏移地址() 6) 数据段指针送寄存器LDS :低地址的字送指定的通用寄存器(SI)、高地址的字送DS 7) 附加段指针送寄存器指令LES :与LDS相似,低地址的字送通用寄存器(DI)、高地址送ES 上三指令不影响标志位 8) 标志寄存器传送指令 LAHF :标志寄存器低八位送AH SAHF :AH送标志寄存器低八位 PUSHF:标志寄存器压入堆栈 POPF :栈顶内容送标志寄存器 9) 加法指令ADD 目的操作数只能是寄存器或存储单元 对CF,OF,SF,PF,ZF,AF有影响 10) 加1指令INC