资源描述
第四章第四章 ARM汇编语言程序设计汇编语言程序设计4.1 汇编语言程序格式汇编语言程序格式4.2 ARM汇编器的伪操作汇编器的伪操作4.3 汇编语言上机过程汇编语言上机过程4.4 汇编语言程序设计汇编语言程序设计第四章 ARM汇编语言程序设计4.1 汇编语言程序格式14.1 汇编语言程序格式汇编语言程序格式4.1.1 汇编语言程序的组成汇编语言程序的组成AREA Init,CODE,READONLYENTRYStartLDR R0,=0 x3FF5000LDR R1,0 xFFSTR R1,R0LDR R0,=0 x3FF5008LDR R1,0 x01STR R1,R0.END4.1 汇编语言程序格式4.1.1 汇编语言程序的组成2AREA Init,CODE,READONLYENTRYStartLDR R0,=0 x3FF5000LDR R1,0 xFFBLPRINT_TEXT.PRINT_TEXT.MOV PC,LRENDAREA Init,CODE,READONLY3;FULL SEGMENT DEFINITION-Intel 8086;-stack segment-STACKSEGMENT DB64 DUP(?)STACK ENDS;-data segment-DATASEGMENT;data definitions are placed hereDATAENDS;-code segment-CODESEGMENTMAIN PROC FAR ASSUME CS:CODE,DS:DATA,SS:STACK MOV AX,DATA MOV DS,AX -MOV AH,4CH INT 21HMAIN ENDPCODEENDS END MAIN;FULL SEGMENT DEFINITION-44.1.2 汇编语言的语句格式汇编语言的语句格式ARM汇编语言程序的每行语句由14部分组成。LABELOPERATION OPERAND;COMMENT标号域操作助记符域 操作数域注释域4.1.2 汇编语言的语句格式ARM汇编语言程序的每行语句由54.2 ARM汇编器的伪操作汇编器的伪操作符号定义伪操作(Symbol Definition)数据定义伪操作(Data Definition)汇编控制伪操作(Assembly Control)框架描述伪操作(Frame Description)其他伪操作(Miscellaneous)4.2 ARM汇编器的伪操作符号定义伪操作(Symbol D6数据定义伪操作数据定义伪操作数据定义伪操作用于为特定的数据分配存储单元,同时可完成已分配存储单元的初始化。DCB分配一片连续的字节存储单元并初始化。DCW分配一片连续的半字存储单元并初始化。DCD分配一片连续的字存储单元并初始化。SPACE分配一片连续的存储单元并初始化为0。MAP定义一个结构化的内存表首地址。FIELD定义一个结构化的内存表的数据域。数据定义伪操作数据定义伪操作用于为特定的数据分配存储单元,同7DCB格式:标号 DCB表达式功能:DCB伪操作用于分配一片连续的字节存储单元,并用伪操作中指定的表达式初始化。其中,表达式可以为0255的数值或字符串。DCB也可以用“=”代替。示例:StrDCB“This is a test!”DCB8DCW格式:标号 DCW表达式功能:DCW伪操作用于分配一片连续的半字存储单元,并用伪操作中指定的表达式初始化。其中,表达式可以为程序标号或数值表达式。用DCW分配的存储单元是半字对齐的。示例:DataTestDCW 1,2,3DCW9DCD格式:标号 DCD表达式功能:DCD伪操作用于分配一片连续的字存储单元,并用伪操作中指定的表达式初始化。其中,表达式可以为程序标号或数值表达式。用DCD分配的存储单元是字对齐的。DCD也可 以用 “&”代替。示例:Test DCD4,5,6DCD10SPACE格式:标号 SPACE表达式功能:SPACE伪操作用于分配一片连续的存储区域并初始化为0。其中,表达式为要分配的字节数。SPACE也可以用 “%”代替。示例:DataSpace SPACE100SPACE11MAP格式:MAP 表达式,基址寄存器功能:MAP伪操作用于定义一个结构化的内存表首地址。表达式可以为程序标号或数值表达式,基址寄存器为可选项,当基址寄存器选项不存在时,表达式的值即为内存表的首地址。否则,内存表的首地址为表达式的值与基址寄存器的和。也可以用 “”代替。示例:MAP 0 x100,R0;首地址的值为0 x100+R0MAP12FIELD格式:标号 FIELD 表达式 功能:FIELD伪操作用于定义一个结构化的内存表中的数据域。表达式的值为当前数据域在内存表中所占的字节数。FIELD伪操作常与MAP配合使用 来定义结构化的内存表。注意:MAP和FIELD仅用于定义数据结构,并不实际分配存储单元。FIELD也可以用 “#”代替。由MAP和FIELD配合定义的内存表有3种:FIELD13(1)表达式是一个基于绝对地址的内存表:MAP 0 x100;首地址为0 x100AFIELD 4;A的长度为4字节,位置为0 x100BFIELD 4;B的长度为4字节,位置为0 x104SFIELD 16;S的长度为16字节,位置为0 x108.LDRR0,=A;读取A的地址0 x100LDRR1,R0;将A的内容读到R1(1)表达式是一个基于绝对地址的内存表:14(2)表达式是一个数值,是一个相对地址的内存表:MAP0 x04,R9;首地址为R9的值AFIELD 4;A的长度为4字节,相对位置为0BFIELD 8;B的长度为8字节,相对位置为4SFIELD 96;S的长度为96字节,相对位置为12.LDRR9,=0 x900;表的首地址为0 x904ADRR0,A;读取A的地址0 x904LDRR2,R0;将A的内容读到R2.LDRR9,=0 x2000;同一表的首地址为0 x2004ADRR1,B;读取B的地址0 x2008STRR9,R1;将R9的内容写到B(2)表达式是一个数值,是一个相对地址的内存表:15(3)表达式是一个标号,基于PC的内存表:Data SPACE 100;分配100字节的内存单元初始化0MAPData;首地址为Data内存单元AFIELD 4;A的长度为4字节,相对位置为0BFIELD 4;B的长度为4字节,相对位置为4SFIELD 4;S的长度为4字节,相对位置为8.LDRR5,B;相当于LDR R5,PC,#4(3)表达式是一个标号,基于PC的内存表:16其它常用的伪操作其它常用的伪操作AREA格式:AREA 段名属性1,属性2,功能:AREA伪操作定义一个代码段、数据段或特定属性的段。CODE:定义代码段。DATA:定义数据段。READONLY:只读,代码段默认。READWRITE:可读可写,数据段默认。一个汇编程序至少包含一个段,当程序太长时,也可以将程序分为多个代码段和数据段。其它常用的伪操作AREA17AREA Init,CODE,READONLYENTRYBSTARTAREA Stack,DATA,READWRITESAVESPACE20AREA Init,CODE,READONLYSTARTADDR1,R2,R3BSTARTAREA Init,CODE,READONLY18ALIGN格式:ALIGN表达式,偏移量功能:ALIGN可通过添加填充字节的方式,使当前位置满足一定的对齐方式。其中,表达式的值用于指定对齐方式,可能取的值为2的幂,如1、2、4、8、16等。如果没有指定表达式,则将当前位置对齐到下一个字的位置。ADDR0,R4,R5BSTARTDATA1DCB“strin”ALIGN 4STARTLDRR0,R5ALIGN194.3 汇编语言上机过程汇编语言上机过程1.编辑汇编语言源程序2.编译源程序3.链接汇编程序4.调试汇编程序4.3 汇编语言上机过程1.编辑汇编语言源程序20嵌入式系统arm汇编语言程序设计课件214.4 汇编语言程序设计汇编语言程序设计4.3.1 程序设计步骤程序设计步骤4.3.2 简单程序设计(顺序、分支、循环)简单程序设计(顺序、分支、循环)4.3.3 子程序设计子程序设计4.3.4 模式切换程序设计模式切换程序设计4.3.5 汇编语言和汇编语言和C语言编程语言编程4.4 汇编语言程序设计4.3.1 程序设计步骤22嵌入式系统arm汇编语言程序设计课件23模块化的程序设计模块化的程序设计(从功能分析(从功能分析战略上)战略上)模块化的程序设计(从功能分析战略上)24嵌入式系统arm汇编语言程序设计课件25嵌入式系统arm汇编语言程序设计课件26汇编语言程序设计的基本方法(战术上看)汇编语言程序设计的基本方法(战术上看)程序设计步骤(对每一模块)程序设计步骤(对每一模块)1.1.问题定义问题定义2.2.算法设计算法设计3.3.选择指令选择指令4.4.编写程序编写程序结构化程序设计(算法设计)结构化程序设计(算法设计)1.1.顺序结构顺序结构2.2.分支结构分支结构 3.3.循环结构循环结构4.4.子程序设计子程序设计上机过程(具体实现)上机过程(具体实现)1.1.编辑程序编辑程序2.2.汇编源程序汇编源程序3.3.链接程序链接程序4.4.调试源程序调试源程序汇编语言程序设计的基本方法(战术上看)27结构化程序设计概述:结构化程序设计概述:写任何程序最成功的方式是先人工的解决问题写任何程序最成功的方式是先人工的解决问题找出算找出算法!法!用结构用结构IFTHENELSE,CASE,REPEATUNTIL,WHILEDO,FORDO写算法,然后再将该算法翻译成一种合适的程序设计语言写算法,然后再将该算法翻译成一种合适的程序设计语言结构化的程序设计!结构化的程序设计!结构化程序设计概述:28程序设计步骤程序设计步骤 1.1.问题的定义问题的定义仔细思考程序所要解决的问题,即用自然语言描述仔细思考程序所要解决的问题,即用自然语言描述“做什么做什么?以及程序做这些工作时的时序?以及程序做这些工作时的时序”如:如:1.1.从传感器读取温度值。从传感器读取温度值。2.2.加上调整因子。加上调整因子。3.3.将结果存储在存储单元里。将结果存储在存储单元里。2.2.算法及表示方法算法及表示方法用来表示程序设计问题的操作序列或步骤用来表示程序设计问题的操作序列或步骤算法,算法,即即“怎样做怎样做?”。表示方法:表示方法:1 1)流程图)流程图 2 2)伪指令)伪指令程序设计步骤29嵌入式系统arm汇编语言程序设计课件303.3.选择适当的指令(按功能)选择适当的指令(按功能)一、数据传送类指令一、数据传送类指令二、算术运算指令二、算术运算指令三、逻辑操作指令三、逻辑操作指令四、程序控制指令四、程序控制指令4.4.编写程序(从算法到程序)编写程序(从算法到程序)3.选择适当的指令(按功能)31(1 1)建立算法使用的数据结构)建立算法使用的数据结构 1 1)数据将存放在存储器还是存放在寄存)数据将存放在存储器还是存放在寄存器中?器中?2 2)数据类型是字节、半字或字?)数据类型是字节、半字或字?3 3)有多少数据项?)有多少数据项?4 4)数据为无符号数还是符号数?)数据为无符号数还是符号数?(1)建立算法使用的数据结构32(2 2)在代码段开始处写出变量、段寄存器、外围设)在代码段开始处写出变量、段寄存器、外围设备等所需要的初始化指令备等所需要的初始化指令(3 3)选择实现算法中每一主要动作所需要的指令,)选择实现算法中每一主要动作所需要的指令,并决定数据在这些指令中的存放形式。并决定数据在这些指令中的存放形式。(4 4)按照主要指令的要求,用)按照主要指令的要求,用LDR、STR指令或指令或MOV指令把数据送到正确的位置。指令把数据送到正确的位置。(2)在代码段开始处写出变量、段寄存器、外围设备等所需要的初33顺序程序设计:已知32位变量X、Y存放在存储器的地址0 x90010、0 x90014中,要求实现Z=X+Y,并且Z的值存放在0 x90018中。AREA Exam,CODE,READONLYENTRYSTARTLDRR0,=0 x90010LDRR1,R0,#4LDRR2,R0,#4ADDR1,R1,R2STRR1,R0END顺序程序设计:34分支程序设计:已知32位有符号数X存放在存储器的地址0 x90010中,要求实现:Y=X (X=0)或 Y=-X (X0)AREA Exam CODE READONLYENTRYSTARTLDRR1,=0 x90010LDRR2,R1MOVR0,#0CMPR2,R0SUBLT R2,R0,R2STRR2,R1END分支程序设计:35已知32位有符号数X存放在存储器的地址0 x90010中,要求实现:Y=1(X0)或 Y=0(X=0)或Y=-1(X=num then simply return ADR r3,JumpTable ;Load address of jump table LDR pc,r3,r0,LSL#2 ;Jump to the appropriate routineJumpTable DCD DoAdd DCD DoSubDoAdd ADD r0,r1,r2 ;Operation 0 MOV pc,lr ;ReturnDoSub SUB r0,r1,r2 ;Operation 1 MOV pc,lr ;Return END ;mark the end of this file ENTRY ;40循环程序设计:循环程序设计:计数控制:当循环次数已知时,通常使用计数控制法。MOV Rn,#N;循环初值部分LOOPA;循环体SUBS Rn,Rn,#1;修改部分CMP Rn,#0BGTLOOPA;控制部分直到Rn=0时,循环结束。循环程序设计:计数控制:当循环次数已知时,通常使用计数控制法41另,每循环一次计数其加一,直到与设定的值相等时结束。MOV Rn,#0;循环初值部分LOOPA;循环体ADDS Rn,Rn,#1;修改部分CMP Rn,#NBNELOOPA;控制部分直到Rn=N时,循环结束。另,每循环一次计数其加一,直到与设定的值相等时结束。42例如:编制程序使S=1+2*3+3*4+4*5+N(N+1),直到N等于10为止。AREA Exam,CODE,READONLYENTRYSTARTMOV R0,#1;R0累加,置初值1,SMOV R1,#2;R1第一个乘数置为2,NREPEATADDR2,R1,#1;R2第二个乘数,N+1MULR3,R2,R1;N(N+1)存于R3ADDR0,R0,R3;将部分积累加到R0ADDR1,R1,#1;修改循环次数CMP R1,#10BLEREPEATBSTARTEND例如:编制程序使S=1+2*3+3*4+4*5+N(N+43条件控制:有些情况下,循环次数事先无法确定,但它与某些条件有关。例如:求两个数组DATA1、DATA2对应的数据之和,并将和存入新数组SUM中,计算一直到两数之和为零时结束,并把新数组的长度存于R0中。AREA BlockData,DATA,READWRITEDATA1DCD2,5,0,3,-4,5,0,10,9DATA2DCD3,5,4,-2,0,8,3,-10,5SUMDCD0,0,0,0,0,0,0,0,0条件控制:有些情况下,循环次数事先无法确定,但它与某些条件有44AREA,Exam,CODE,READONLYENTRYSTARTLDRR1,=DATA1LDRR2,=DATA2LDRR3,=SUMMOV R0,#0LOOPLDRR4,R1,#4LDRR5,R2,#4ADDS R4,R4,R5ADDR0,R0,#1STRR4,R3,#4BNELOOPBSTARTENDAREA,Exam,CODE,READONLY45多重循环:即循环体内嵌套循环。设计时可以从外层循环到内层循环,一层一层的进行。通常在设计外层时,仅把内层看成一个处理粗框,然后再将该粗框细化成置初值、工作、修改和控制等四个部分。例:在以BUF为首地址的字存储区中存放有10个无符号数0 x0FF,0 x00,0 x40,0 x10,0 x90,0 x20,0 x80,0 x30,0 x50,0 x70,0 x60现需将他们按从小到大的顺序排列在BUF中,使编写其程序。分析:“冒泡排序法”。寄存器分配如下:多重循环:即循环体内嵌套循环。设计时可以从外层循环到内层循环46R0:指示缓冲区初始地址R1:外循环计数器R2:内循环计数器R3:外循环地址指针R4:内循环地址指针R5:内循环下一个数地址指针R6:存放内循环一轮比较的最小值R7:存放内循环取出的下一个比较值源程序如下:AREABlockData,DATA,READWRITEBUFDCD 0 x0FF,0 x00,0 x40,0 x10,0 x90,0 x20,0 x80,0 x30,0 x50,0 x70,0 x60NEQU10R0:指示缓冲区初始地址47 AREA Exam,CODE,READONLY ENTRYSTART LDRR0,=BUF;指向数组的首地址 MOVR1,#0;外循环计数器 MOVR2,#0;内循环计数器LOOPI ADDR3,R0,R1,LSL#2;外循环首地址放入R3 MOVR4,R3;内循环首地址放入R4 ADDR2,R1,#1;内循环计数器初值 MOVR5,R4;内循环下一地址初值 LDRR6,R4;取内循环第一个值R4LOOPJ ADDR5,R5,#4;内循环下一地址值 LDRR7,R5;取出下一地址值R7 CMPR6,R7;比较 BLTNEXT;小则取下一个 SWPR7,R6,R5;大则交换,最小值R6 MOVR6,R7 AREAExam,CODE,READONLY48NEXTADDR2,R2,#1;内循环计数器CMPR2,#N;循环终止条件BLTLOOPJ;小于N则继续内循环,实现比较一轮SWPR7,R6,R3;否则,内循环一轮结束,;将最小数存入外循环的首地址处ADDR1,R1,#1;外循环计数CMPR1,#N-1;外循环终止条件BLTLOOPI;小于N-1继续执行外循环BSTARTEND程序运行的结果:00H,10H,20H,30H,40H,50H,60H,70H,80H,90H,0FFHNEXTADDR2,R2,#1;内循环计数器494.3.3 子程序设计子程序设计保护现场、参数传递、恢复现场、子程序返回AREA Exam,CODE,READONLYENTRYSTARTLDRR0,=0 x3FF5000LDRR1,=0 x3FF5008STMFD R13!,R0-R2,R14 BLPrint_TextPrint_TextLDMFD R13!,R0-R2,PC MOV PC,R14END4.3.3 子程序设计保护现场、参数传递、恢复现场、子程序返504.3.4 模式切换程序设计模式切换程序设计处理器模式处理器模式说说 明明备备 注注USR正常程序运行的工作模式不能直接切换到其它模式特权模式SYS用于支持操作系统的特权任务等可直接切换到其它模式异常模式SVC操作系统使用的一种保护模式只有在系统复位和软件中断响应时,才进入此模式FIQ快速中断请求处理只有在FIQ异常响应时,才进入此模式IRQ中断请求处理只有在IRQ异常响应时,才进入此模式ABT用于虚拟内存和存储器保护在ARM7内核中没有用UND支持软件仿真的硬件协处理器只有在位定义指令异常响应时,才进入此模式4.3.4 模式切换程序设计处理器模式说 51嵌入式系统arm汇编语言程序设计课件52处理器工作在什么模式下是由状态寄存器CPSR的模式位M4:0来决定的。注意:某些组合会导致处理器进入一个不可恢复的状态。要实现模式之间的切换只需通过专用指令MRS、MSR修改CPSR模式位即可实现。例:堆栈初始化的子程序:InitStack MOVR0,LR;R0-LR保存返回地址;切换到管理模式并设置其堆栈MSRCPSR_c,#0 xd3;CPSR4:0-10011LDRSP,STACKSVC;STACKSVC堆栈地址处理器工作在什么模式下是由状态寄存器CPSR的模式位M4:53;切换到中断模式并设置其堆栈MSRCPSR_c,#0 xd2;CPSR4:0-10010LDR SP,STACKIRQ ;STACKIRQ堆栈地址;切换到快中断模式并设置其堆栈MSRCPSR_c,#0 xd1;CPSR4:0-10001LDR SP,STACKFIQ;STACKFIQ堆栈地址;切换到中止模式并设置其堆栈MSRCPSR_c,#0 xd7;CPSR4:0-10111LDR SP,STACKABT;STACKABT堆栈地址;切换到未定义模式并设置其堆栈MSRCPSR_c,#0 xdb;CPSR4:0-11011LDR SP,STACKUND;STACKUND堆栈地址;切换到系统模式并设置其堆栈MSRCPSR_c,#0 xdf;CPSR4:0-11111LDR SP,STACKSYS;STACKSYS堆栈地址MOV PC,R0;调用返回;切换到中断模式并设置其堆栈544.3.5 汇编语言和汇编语言和C语言编程语言编程在实际编程时,程序的初始化部分用汇编语言完成,用C或C+完成主要的编程任务。为了保证程序调用时参数传递的正确性,汇编语言程序的设计要遵守APCS(ARM Produce Call Standard),这些基本规则包括子程序调用过程中寄存器的使用规则、堆栈的使用规则以及参数传递规则等。APCS:(1)寄存器的使用规则(2)堆栈的使用规则(3)参数传递使用规则4.3.5 汇编语言和C语言编程在实际编程时,程序的初始化部55(1)寄存器的使用规则)寄存器的使用规则子程序间通过寄存器R0-R3来传递参数,记作A0-A3。被调用的子程序在返回前无需恢复寄存器R0-R3的内容也即这些寄存器的值是由调用者保存的。子程序使用R4-R11寄存器来保存局部变量,记作V1-V8。如果被调用的子程序要用到R4-R11,在进入时要保存这些寄存器的值压栈,使用完后在返回前必须恢复这些寄存器的值出栈,也即这些寄存器的值是由被调用者保存的。寄存器R12用作子程序间临时寄存器,记作IP。寄存器R13用作数据栈指针,记作SP,不能用作他用。在子程序进入和退出时SP的值必须相等。寄存器R14称为链接寄存器,记作LR。它用作保存子程序的返回地址。寄存器R15是程序计数器,记作PC。不能用作其他用途。(1)寄存器的使用规则56寄存器寄存器别名别名特殊名称特殊名称使用规则使用规则R0A1参数/结果/临时寄存器1R1A2参数/结果/临时寄存器2R2A3参数/结果/临时寄存器3R3A4参数/结果/临时寄存器4R4V1局部变量寄存器1R5V2局部变量寄存器2R6V3局部变量寄存器3R7V4局部变量寄存器4R8V5局部变量寄存器5R9V6局部变量寄存器6R10V7SL局部变量寄存器7/堆栈限制指针R11V8FP帧指针R12IP子程序内部调用的临时寄存器R13SP堆栈指针R14LR链接寄存器R15PC程序寄存器寄存器别名特殊名称使用规则R0A1参数/结果/临时寄存器1R57(2)堆栈的使用规则)堆栈的使用规则只要有一个函数被调用,在堆栈中就产生一个新的活动帧,其中包含回溯记录、局部变量等。堆栈可分为满栈和空栈,当栈指针指向最后一个入栈的数据元素时,成为满栈。否则称为空栈。根据栈的增长方向不同可以分为递增栈和递减栈。满递减栈(Full Descending)空递减栈(Empty Descending)满递增栈(Full Ascending)空递增栈(Empty Ascending)ATPCS规定堆栈为FD类型,并且对堆栈的操作是8字节对齐的。(2)堆栈的使用规则58(3)参数传递使用规则)参数传递使用规则对于参数可变的子程序,当参数不超过4个时,可以使用寄存器R0R3来传递;当参数超过4个时,将剩余的参数用堆栈来传递,入栈的顺序与参数的顺序相反,最后一个先入栈。结果为一个32位整数时,通过R0返回。结果为一个64位整数时,通过R0、R1返回,依此类推。对于位数更多的结果,需要通过内存来传递。(3)参数传递使用规则对于参数可变的子程序,当参数不超过4个59lC程序调用汇编程序示例程序调用汇编程序示例C语言源程序strtest.c:#include Extern void Strcopy(char*d,const char*s);int main()const char*srcstr=“First string source“;char dststr =“Second string destination“;printf(“Before copying:n“);printf(“%s n%s n”,srcstr,dststr);strcopy(dststr,srcstr);printf(“After copying:n“);printf(“%s n%s n”,srcstr,dststr);return 0;C程序调用汇编程序示例60汇编语言源程序Scopy.sAREAScopy,CODE,READONLYEXPORT strcopyStrcopy;R0指向目标地址;R1指向源地址LDRBR2,R1,#1STRBR2,R0,#1CMPR2,#0BNEStrcopyMOVPC,LREND 汇编语言源程序Scopy.s61汇编程序调用汇编程序调用C程序程序汇编语言调用C程序之前,要用IMPORT伪指令来声明被调用的C程序,并用BL指令来调用。下例中,C语言程序g()完成5个整数相加的功能,汇编程序ARM_add则要调用g()完成5个整数和的功能,参数传递为14个均在R0R3中,第5个参数利用堆栈传送。C语言源程序C_add.c:#include int g(int a,int b,int c,int d,int e);实现5个整数求和 return a+b+c+d+e;汇编程序调用C程序62汇编源程序ARM_add.s:AREAARM_add,CODE,READONLYEXPORT ARM_addIMPORT gENTRYSTRLR,SP,#-4!MOVR0,#1MOVR1,#2MOVR2,#3MOVR3,#4MOVR4,#5STRR4,SP,#-4!BLgADDSP,SP,#4LDRPC,SP,#4END汇编源程序ARM_add.s:63
展开阅读全文