汇编语言(基于64位ARMv8体系结构)PPT完整全套教学课件_第1页
汇编语言(基于64位ARMv8体系结构)PPT完整全套教学课件_第2页
汇编语言(基于64位ARMv8体系结构)PPT完整全套教学课件_第3页
汇编语言(基于64位ARMv8体系结构)PPT完整全套教学课件_第4页
汇编语言(基于64位ARMv8体系结构)PPT完整全套教学课件_第5页
已阅读5页,还剩231页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

64位ARM汇编语言汇编语言(基于64位ARMv8体系结构)目

录第1章

汇编语言基础第2章

整型数据处理第3章

分支和循环程序第4章

模块化程序设计第5章

浮点数据处理第6章

SIMD数据处理第1章

汇编语言基础1.1

计算机系统概述

1.1.1

计算机硬件组成

1.1.2

处理器的发展

1.1.3

ARM处理器1.2

64位ARMv8编程结构 1.2.1ARMv8结构基础 1.2.2ARMv8寄存器 1.2.3ARMv8存储器模型1.364位ARM汇编语言 1.3.1ARM指令集 1.3.2汇编语言程序 1.3.3汇编语言开发1.1计算机系统概述掌握计算机系统的硬件组成结构

理解汇编语言程序员看到的计算机硬件了解处理器的发展概况

认识精简指令集计算机RISC的必然趋势熟悉ARM处理器的发展

知晓ARMv8结构和Cortex系列处理器5计算机系统的硬件组成I/O接口主存储器系统总线CPU寄存器控制器运算器辅助存储器输入设备输出设备汇编语言将计算机硬件抽象为:寄存器存储器地址输入输出地址6通用处理器和专用处理器专用处理器微控制器数字信号处理器DSP

用于嵌入式系统Intel80868038680486奔腾奔腾II奔腾4802868086奔腾III酷睿多核系列4004IA-32处理器16位80x86处理器奔腾多核系列Intel64处理器7CISC和RISC复杂指令集计算机(ComplexInstructionSetComputer)功能强大而复杂、指令条数繁多寻址方式多样、指令编码长短不一……精简指令集计算机(ReducedInstructionSetComputer)固定长度的机器代码、简单的寻址方式较多的通用寄存器、面向寄存器的数据处理……8ARM处理器Cortex-A(Application)Cortex-R(Real-time)Cortex-M(Microcontroller)9ARMv8-A处理器ARMCortex-A72用于树莓派

4B(RaspberryPi)1.264位ARMv8编程结构理解ARMv8体系结构的异常和执行状态

认识应用程序的异常层和64位执行状态(AArch64)掌握64位ARM体系结构的可编程寄存器

记忆通用寄存器、专用寄存器的作用和名称

理解程序状态PSTATE和系统寄存器的含义了解ARMv8体系结构的存储器模型

掌握字节存储顺序、地址边界对齐的概念

熟悉外设统一编址和存储管理下的存储空间分配11异常(Exception)ARMv8体系结构支持多层次执行特权

异常层(EL,ExceptionLevel),共4层EL0对应非特权层,即应用程序运行的层次EL1、EL2、EL3为特权层一个典型软件层次EL0——用于常规用户应用程序EL1——用于操作系统核心程序(典型的特权层程序)EL2——用于系统监测、虚拟机管理程序EL3——用于包含安全监控的底层固件

12执行状态(Executionstate)64位执行状态(AArch64)地址和指令使用64位寄存器支持64位指令集A6432位执行状态(AArch32)地址和指令使用32位寄存器支持A32(ARM)和T32(Thumb-2)指令集32位执行状态用于向后兼容ARMv7(和更早)的代码1364位ARM结构(AArch64、ARM64)31个64位通用寄存器64位程序计数器PC、堆栈指针SP和异常连接寄存器ELR等专用寄存器32个128位浮点和SIMD向量寄存器唯一的A64指令集具有4异常层次的ARMv8异常模型支持64位虚拟地址……中国华为的鲲鹏920处理器基于完全知识产权的ARMv8体系结构仅支持64位执行状态14ARMv8通用寄存器31个64位通用寄存器:X0~X3031个32位通用寄存器:W0~W30

注:X30用于过程调用的连接寄存器LR15ARMv8专用寄存器零值寄存器ZR(Zeroregister),64位:XZR、32位:WZR程序计数器PC(ProgramCounter)栈指针SP(Stackpointer),32位:WSP16处理状态PSTATE位描述N负数(Negative)条件标志。如果指令执行结果是补码表达的有符号整数,则结果是负数,N=1;结果是正数或0,N=0。Z零(Zero)条件标志。指令执行结果是0,Z=1;否则,Z=0。C进位(Carry)条件标志。指令执行结果导致进位(例如,加法结果导致无符号数溢出),C=1;否则,C=0。V溢出(Overflow)条件标志。指令执行结果导致溢出(例如,加法结果导致有符号数溢出),V=1;否则,V=0。17字节存储顺序ARMv8体系结构既支持小端方式、也支持大端方式多数ARM处理器默认采用小端方式Linux操作系统默认ARM处理器采用小端方式A64指令字、所有存储器映射的外设必须采用小端方式18地址边界对齐对ARMv8体系结构来说A64指令必须字(4字节)对齐访问外设地址也要求对齐地址有些数据访问则要求地址边界对齐19外设统一编址ARM处理器采用统一编址方式ARMv8体系结构提供两种互斥的存储器类型常规(Normal)——用于存储器操作设备(Device)——用于外设操作主存部分I/O部分存储器空间0主存空间I/O空间020存储管理1.364位ARM汇编语言了解ARM指令集的发展情况

了解A64(64位ARM指令集)的指令分类和指令编码

掌握A64指令集的一般指令格式熟悉GNU汇编语言的程序结构

掌握汇编语言的语句格式、常量表达和常用指示符

熟悉汇编语言的信息显示程序实践汇编语言程序的开发过程和操作方法

理解C语言的预处理、编译、汇编和连接过程

掌握GCC和AS开发汇编语言的方法22A64指令集指令类型典型指令(助记符)举例数据处理传送:MOV、MOVK,加减:ADD{S}、SUB{S}、CMP乘除:MUL、MADD、MSUB、UDIV、SDIV逻辑运算:AND、ORR、EOR、MVN、TST移位:LSL、LSR、ASR、ROR位段操作:UXTB、UXTH、SXTB、SXTH、SXTW存储器访问载入:LDR、LDP,存储:STR、STP,地址生成:ADR、ADRP流程控制无条件跳转:B、BR,调用:BL、BLR,返回:RET条件分支:B.cond、CBZ/CBNZ、TBZ/TBNZ条件执行:CSEL,条件设置:CSET、CSETM系统控制等系统调用:SVC,系统寄存器访问:MRS,MSR空操作:NOP,调试指令:BRK,HLT23A64指令编码24A64指令格式

opcodeRd,Rn{,operand2}opcode:指令操作码,使用助记符表达Rd:目的寄存器Rn:源操作数寄存器operand2:第2个源操作数addx0,x1,x2 //64位加法:X0=X1+X2addw5,w3,w4 //32位加法:W5=W3+W4subx6,x7,x8 //64位减法:X6=X7-X8subsw9,w11,w12 //32位减法:W9=W11-W12,更新NZCV标志25GNU汇编语言的语句格式标号:指令|指示符|伪指令 //注释

movx15,x16 //将寄存器X16内容传送给X15,即X15=X16

movx0,0

//将数值0传送给寄存器X0,即X0=0msg: .string"Hello,ARMv8!\n" //定义字符串(以0结尾)

len=.-msg

//符号常量len定义为字符串长度

.byte74,0x4A,0X4a,0112,0b01001010,'J'//本语句的每个常量具有相同的数值

.ascii"TogetherforaSharedFuture!"

//字符串

.equNULL,0 //使用NULL表示数值0

NULL=0

//使用NULL表示数值026GNU汇编语言的常量表达数据进制表达规则常数示例十进制由0~9数字组成,以非0数字开头100,255十六进制由0~9数字、A~F(a~f)字母组成以0X(0x)开头0X64,0xff二进制由0、1两个数字组成以0B(b)开头0B011001000b11111111八进制由0~7数字组成,以数字0开头0144,037727GNU汇编语言的主要指示符 .text //可执行、只读的代码(文本)区段 .data //可读可写的数据区段 .global标号

//声明函数名或变量名为全局标号 .type标识符,%object

//类型声明:数据对象 .type标识符,%function

//类型声明:函数名 .align数值表达式

//地址对齐变量名: 数据定义指示符

数值表达式1,数值表达式2,…变量名: .space 存储单元数,数值表达式28GNU汇编语言的数据定义指示符指示符数据类型变量定义功能.BYTE8位、1个字节字节单元,每个数据是8位、字节量.HWORD|.SHORT16位、2个字节半字单元,每个数据是16位、半字量.WORD|.INT32位、4个字节字单元,每个数据是32位、字量.XWORD|.DWORD|.LONG|.QUAD64位、8个字节双字单元,每个数据是64位、双字量.OCTA128位、16个字节4字单元,每个数据是128位、4字量.ASCII字符串字节单元,每个数据是8位字符.STRING|.ASCIZ字符串字节单元,每个数据是8位字符,结尾添加029信息显示程序#include<stdio.h>intmain(){printf("Hello,world!\n");return0;} .data

//数据区msg: .string"Hello,ARMv8!\n"

//定义字符串 .text

//代码区 .globalmain

//主函数main: stpx29,x30,[sp,-16]!

//保护X29和X30 adrx0,msg

//获取字符串地址 blprintf

//调用printf显示 movx0,0

//返回值 ldpx29,x30,[sp],16

//恢复X29和X30 ret

//主函数返回C语言程序汇编语言程序30A64汇编语言源程序框架(GNU语法) .data

//数据区

… //数据定义 .text

//代码区 .globalmain

//主函数main: stpx29,x30,[sp,-16]!

//保护X29和X30

… //汇编语言指令 movx0,0

//返回值 ldpx29,x30,[sp],16

//恢复X29和X30 ret

//主函数返回31C语言程序的开发过程32汇编语言的开发命令

//使用GCC开发汇编语言程序 gcc-oe102_hello

e102_hello.s

//使用AS开发汇编语言程序 as-oe102_hello.oe102_hello.s gcc-oe102_hello

e102_hello.o第1章

汇编语言基础汇编语言在低层但不低级汇编、汇编一定会编64-bitARMAssembly汇编语言(基于64位ARMv8体系结构)64位ARM汇编语言汇编语言(基于64位ARMv8体系结构)目

录第1章

汇编语言基础第2章

整型数据处理第3章

分支和循环程序第4章

模块化程序设计第5章

浮点数据处理第6章

SIMD数据处理第2章

整型数据处理2.1数据传送 2.1.1

寄存器传送指令 2.1.2

立即数传送2.2

加减运算 2.2.1加减指令 2.2.2带进位的加减指令 2.2.3设置标志的加减指令2.3

乘除运算 2.3.1乘法指令 2.3.2除法指令 2.3.3乘加和乘减指令2.4

位操作

2.4.1逻辑运算指令

2.4.2移位指令

2.4.3位段操作指令2.5存储器访问 2.5.1存储器寻址方式 2.5.2载入和存储指令 2.5.3成对载入和存储指令 2.5.4地址生成指令2.1数据传送掌握通用寄存器之间的传送指令

区别64位和32位整型数据传送掌握通用寄存器与栈指针寄存器的传送指令

知晓栈指针传送的作用熟悉立即数传送指令

理解立即数的限制和多种立即数传送的作用

理解指令别名的含义和作用Move39寄存器传送指令通用寄存器传送

MOVXd,Xm //64位:

movx2,x1

MOVWd,Wm //32位:

movw4,w3栈指针传送

MOVXd|SP,Xm|SP //64位:

movx29,sp

MOVWd|WSP,Wm|WSP //32位:

movwsp,w2940立即数传送指令立即数传送

MOVRd|SP,imm12立即数移位传送

MOVZRd,imm16{,LSLamount}立即数保持传送

MOVKRd,imm16{,LSLamount}立即数求反传送

MOVNRd,imm16{,LSLamount}≈立即数传送MOVRd,imm1641【例2-1】立即数传送1//源程序代码mov x1,100mov

x3,65535mov x5,0x2010movn

w7,0x0mov

w8,-65000//反汇编代码,不使用别名movz

x1,#0x64movz

x3,#0xffffmovz

x5,#0x2010movz

w7,#0x0movn

w8,#0xfdef反汇编命令

objdump-Mno-aliases-de201_imm.o>e201_imm6.txt42【例2-1】立即数传送2//源程序代码movz

w6,0x6666,lsl16movn

w7,0x0mov

w7,-1mov

w8,-65000movn

w9,0xffffmovn

x10,0xffff,lsl32//反汇编代码,使用别名mov

w6,#0x66660000 //#1717960704mov

w7,#0xffffffff //#-1mov

w7,#0xffffffff //#-1mov

w8,#0xffff0218 //#-65000movn

w9,#0xffffmov

x10,#0xffff0000ffffffff2.2加减运算掌握加法ADD、减法SUB指令

认识第2个操作数operand2的多种形式

理解逻辑左移LSL、逻辑右移LSR、算术右移ASR和循环右移ROR

理解无符号整数的零位扩展和有符号整的符号扩展熟悉带进位的加法ADC、减法SBC指令熟悉设置标志的加法ADDS、减法SUBS指令

理解条件标志NZCV及其作用AddSubtract44立即数加减指令立即数加法指令

ADDRd|SP,Rn|SP,imm12{,LSL12}立即数减法指令

SUBRd|SP,Rn|SP,imm12{,LSL12}addx1,x2,100 //64位加法:X1=X2+100subwsp,wsp,0x10 //32位减法:WSP=WSP-0x10subx3,x4,0x10,lsl12 //64位减法:X3=X4-0x1000045寄存器移位的加减指令寄存器移位的加法指令

ADDRd,Rn,Rm{,shiftamount}寄存器移位的减法指令

SUBRd,Rn,Rm{,shiftamount}求补指令(减法指令的别名)

NEGRd,Rm{,shiftamount}addx10,x10,x10 //X10=X10+X10addx10,x10,0x10lsl2 //X10=X10+X10×446移位操作(shift)//逻辑左移:LSL//逻辑右移:LSR//算术右移:ASR//循环右移:ROR加减法指令不支持47寄存器扩展的加减指令寄存器扩展的加法指令

ADDRd|SP,Rn|SP,Rm{,extendamount}寄存器扩展的减法指令

SUBRd|SP,Rn|SP,Rm{,extendamount}addw11,w12,w13,uxtb //W11=W12+W13低8位addx14,x15,w16,sxth //X14=X15+W16低16位符号扩展addx17,x18,w19,sxtw//X17=X18+

W19符号扩展addx22,x20,w21,uxtw4//X22=X20+W21无符号扩展、左移4位48扩展操作(extend)无符号数的零位扩展

扩展的高位全部是0———————————

UXTB 字节无符号扩展

UXTH 半字无符号扩展

UXTW 字无符号扩展有符号数的符号扩展

扩展的高位全部是符号位———————————SXTB 字节有符号扩展SXTH 半字有符号扩展SXTW 字有符号扩展数据的位数扩展、表达的数值不变49带进位的加减指令带进位的加法指令

ADCRd,Rn,Rm //Rd=Rn+Rm+C带进位的减法指令

SBCRd,Rn,Rm //Rd=Rn-Rm-1+C带进位的求补指令

NGCRd,Rm //Rd=0-Rm-1+C用于支持超过64位整数的加减运算50条件标志NZCV负数标志N:运算结果是负数、即最高位、符号位为1,则N=1;

否则(正数,最高位、符号位为0),N=0零标志Z:

运算结果是0,则Z=1;否则(不是0),Z=0进位标志C:

无符号数加法有进位、减法无借位,则C=1;

否则(加法无进位、减法有借位),C=0溢出标志V:

有符号数加减结果超出表达范围,则V=1;

否则(未超出范围),V=051设置标志的加减指令不设置条件标志———————加法指令:ADD减法指令:SUB求补指令:NEG进位加法:ADC进位减法:SBC进位求补:NGC设置条件标志———————加法指令:ADDS减法指令:SUBS求补指令:NEGS进位加法:ADCS进位减法:SBCS进位求补:NGCS比较指令:CMP负数比较:CMN52【例2-2】加减法指令mov

w2,0x48

//W2=0x48adds

w3,w2,0x27 //W3=W2+0x27=0x48+0x27=0x6F

//标志状态:NZCV=0b0000=0x0subs

w4,w2,0x27 //W4=W2-0x27=0x48-0x27=0x21

//标志状态:NZCV=0b0010=0x2mov

x7,-2

//X7=-2=0xfffffffffffffffe

//假设:X5=0x8070605040302010adds

x8,x7,x5 //X8=0x807060504030200e,NZCV=0b1010=0xbsubs

x9,x7,x5 //X9=0x7f8f9fafbfcfdfee,NZCV=0b1000=0x82.3乘除运算掌握乘法指令

理解乘法结果的等长乘积和倍长乘积掌握除法指令

理解无符号除法和有符号除法的不同熟悉乘加和乘减指令

理解乘法和加减法结合指令的作用

了解使用乘减指令求除法余数的方法MultiplyDivide54乘法指令32位乘法MULWd,Wn,Wm //32位乘积:Wd=Wn×WmUMULLXd,Wn,Wm //无符号64位乘积SMULLXd,Wn,Wm //有符号64位乘积64位乘法MULXd,Xn,Xm //64位乘积:Xd=Xn×XmUMULHXd,Xn,Xm //无符号乘积高64位SMULHXd,Xn,Xm //有符号乘积高64位55【例2-3】128位乘积__int128_tlongMul(longa,longb){

return(__int128_t)a*(__int128_t)b;} .typelongMul,%functionlongMul: smulh

x2,x0,x1 //X2=(X0×X1)128位乘积的有符号高64位结果 mul

x0,x0,x1 //X0=(X0×X1)128位乘积的低64位结果 mov

x1,x2 //X1=

X2 retX0=a,X1=b;X1.X0=a*b56除法指令无符号数除法

UDIVWd,Wn,Wm //32位除法:Wd=Wn÷WmUDIVXd,Xn,Xm //64位除法:Xd=Xn÷Xm有符号数除法

SDIVWd,Wn,Wm //32位除法:Wd=Wn÷WmSDIVXd,Xn,Xm //64位除法:Xd=Xn÷Xm57【例2-4】温度转换mov

w1,9

//W1=9smull

x0,w0,w1 //X0=W0×9=9×Cmov

x1,5

//X1=5sdiv

x0,x0,x1 //X0=9×C/5add

w0,w0,32 //F=W0=9×C/5+32F=(9/5)×C+32add

x0,xzr,w0,sxtw //X0=W0符号扩展add

x0,x0,x0,lsl3 //X0=X0+X0×8=9×C58乘加指令32位乘加指令:Wd=Wa+

Wn×Wm MADDWd,Wn,Wm,Wa64位乘加指令:Xd=Xa+

Xn×Xm MADDXd,Xn,Xm,Xa32位无符号乘、64位加指令:Xd=Xa+

Wn×Wm(倍长) UMADDLXd,Wn,Wm,Xa32位有符号乘、64位加指令:Xd=Xa+

Wn×Wm(倍长)

SMADDLXd,Wn,Wm,Xa59乘减指令32位乘减指令:Wd=Wa-

Wn×Wm MSUBWd,Wn,Wm,Wa64位乘减指令:Xd=Xa-

Xn×Xm MSUBXd,Xn,Xm,Xa32位无符号乘、64位减指令:Xd=Xa-

Wn×Wm(倍长) UMSUBLXd,Wn,Wm,Xa32位有符号乘、64位减指令:Xd=Xa-

Wn×Wm(倍长)

SMSUBLXd,Wn,Wm,Xa60乘补指令32位乘补指令:Wd=0-

Wn×Wm MNEGWd,Wn,Wm64位乘补指令:Xd=0-

Xn×Xm MNEGXd,Xn,Xm32位无符号乘、64位补指令:Xd=0-

Wn×Wm(倍长) UMNEGLXd,Wn,Wm32位有符号乘、64位补指令:Xd=0-

Wn×Wm(倍长)

SMNEGLXd,Wn,Wm2.4位操作掌握逻辑运算指令

熟悉逻辑与、或、非、异或的运算规则掌握移位指令

区别3种右移操作熟悉位段操作指令

掌握位扩展的正确应用

理解位反转、位统计和位复制Bit62逻辑运算指令逻辑与AND、逻辑或ORR、逻辑异或EOR指令: AND|ORR|EORRd|SP,Rn,imm12 AND|ORR|EORRd,Rn,Rm{,shiftamount}逻辑非与BIC、逻辑非或ORN、逻辑非异或EON指令: BIC|ORN|EONRd,Rn,Rm{,shiftamount}逻辑非(求反传送)MVN指令: MVNRd,Rm{,shiftamount}63设置标志的逻辑运算指令设置标志的逻辑与ANDS指令: ANDSRd|SP,Rn,imm12 ANDSRd,Rn,Rm{,shiftamount}设置标志的逻辑非与BICS指令: BICSRd,Rn,Rm{,shiftamount}测试TST指令: TSTRn,imm12 TSTRn,Rm{,shiftamount}主要应用零标志Z和负数标志N64移位指令左移LSL、逻辑右移LSR、算术右移ASR、循环右移ROR指令: LSL|LSR|ASR|RORRd,Rn,amount|Rm //Rd=Rn移位amount或Rm指定的位数lsl w9,w9,9 //左移:W9=W9<<9(左移9位)add w9,wzr,w9,lsl9 //加法:W9=W9<<9(左移9位)ror x10,x9,45 //循环右移:X10=X9循环右移45位orr x10,xzr,x9,ror45 //逻辑或:X10=X9循环右移45位65位扩展指令无符号扩展字节UXTB、半字UXTH指令: UXTB|UXTH Wd,Wn有符号扩展字节SXTB、半字SXTH、字SXTW指令: SXTB|SXTH Rd,Wn SXTW Xd,Wn//16位(半字)无符号加uxthw3,w4add w3,w3,w5,uxth//16位(半字)有符号加sxthw3,w4add w3,w3,w5,sxth66位反转指令位反转:

RBIT

Wd,Wn字节反转:

REVWd,Wn16位字节反转:

REV16Wd,Wn32位字节反转:

REV32

Xd,Xn67位统计指令统计高位0的个数 CLZRd,Rnmov x0,0x1234 //X0=0x1234clz x1,x0 //零位统计:X1=51(=64-12)mvn x0,x0,lsl20 //X0=0xfffffffedcbfffffcls x2,x0 //符号位统计:X2=30统计高位中符号位的个数 CLSRd,Rn68位复制指令位段插入:BFIRd,Rn,lsb,width抽取插入:BFXILRd,Rn,lsb,width抽取寄存器:EXTRRd,Rn,Rm,lsb69【例2-5】自然数求和//限定自然数累加和值是64位整数,只采用64位整数运算:X0=nmadd

x0,x0,x0,x0 //乘加运算:X0=n+n×nlsr

x0,x0,1

//逻辑右移:X0=X0>>1=(1+n)×n÷21+2+3+…+n=(1+n)×n÷2//考虑64位整数相乘、128位乘积,计算更大的n值(n<264)add

x1,x0,1

//X1=n+1,X0=nmul

x2,x1,x0

//X2=(1+n)×n乘积低64位umulhx3,x1,x0

//X3=(1+n)×n乘积高64位lsr

x1,x3,1

//X1=高64位逻辑右移1位extr

x0,x3,x2,1

//X0=抽取组合成低64位:128位逻辑右移1位2.5存储器访问掌握ARM存储器寻址方式 理解寻址、指令寻址和数据寻址的含义

熟悉各种存储器间接寻址的特点掌握载入和存储指令掌握成对载入和成对存储指令的应用

理解栈和栈操作掌握地址生成指令

理解相对地址的含义

理解载入地址伪指令的实质LoadStore71载入(Load)和存储(Store)载入指令: LDRRt,[address] //

Rt←[address]存储指令: STRRt,[address] //

Rt→[address]72ARM存储器间接寻址存储器的间接寻址指令表达格式[address]寄存器间接寻址(仅基址寄存器)[Xn|SP]带立即数偏移量的寄存器间接寻址[Xn|SP,imm12]后索引寻址[Xn|SP],imm9前索引寻址[Xn|SP,imm9]!带寄存器偏移量的寄存器间接寻址[Xn|SP,Wm|Xm{,extend0|2|3}]73载入指令载入一个双字指令: LDR Xt,[address]载入一个字指令: LDR Wt,[address]载入一个字节、零位扩展指令:LDRB Wt,[address]载入一个半字、零位扩展指令:LDRH Wt,[address]载入一个字节、符号扩展指令:LDRSB Rt,[address]载入一个半字、符号扩展指令:LDRSH Rt,[address]载入一个字、符号扩展指令:

LDRSW Xt,[address]74存储指令存储一个双字指令: STR Xt,[address]存储一个字指令: STR Wt,[address]存储一个字节指令:STRB Wt,[address]存储一个半字指令:STRH Wt,[address]75【例2-6】C语言的全局变量//C语言语句longxvar

=

1234567890;intwvar

=

12345678;shorthvar

=

1234;charbvar

=

12;//汇编语言语句(变量声明)xvar: .xword1234567890wvar: .word12345678hvar: .hword1234bvar: .byte12//汇编语言语句(变量载入),X0=变量地址ldr

x1,[x0] //载入64位变量:X1←xvar变量值ldr

w2,[x0,8] //载入32位变量:W2←wvar变量值ldrsh

w3,[x0,12] //载入16位变量,符合扩展:W3←hvar变量值ldrb

w4,[x0,14] //载入8位变量,零位扩展:W4←bvar变量值76寄存器对的存储器访问指令载入两个双字指令: LDP Xt1,Xt2,[address]载入两个字指令: LDP Wt1,Wt2,[address]载入两个字、符号扩展指令:

LDPSW Xt1,Xt2,[address]存储两个双字指令:STP Xt1,Xt2,[address]存储两个字指令:STP Wt1,Wt2,[address]77栈操作stpx29,x30,[sp,-16]!//压入

ldpx29,x30,[sp,-16]!//弹出

78【例2-7】C语言的局部变量1//GCC生成汇编语言代码(存储到栈区)stp

x29,x30,[sp,-32]! //保护X29和X30,SP减量32,为局部变量预留空间add

x29,sp,0

//X29=SP,作为该函数的帧指针mov

x0,722movk

x0,0x4996,lsl16 //X0=1234567890=(0x4996<<16)+722str

x0,[x29,24]

//保存X0,即变量xvarmov

w0,24910movk

w0,0xbc,lsl16 //W0=12345678=(0xBC<<16)+24910str

w0,[x29,20]

//保存W0,即变量wvarmov

w0,1234

//W0=1234strh

w0,[x29,18]

//保存W0低半字,即变量hvar79【例2-7】C语言的局部变量2//GCC生成汇编语言代码(从栈区载入)mov

w0,12

//W0=12strb

w0,[x29,17]

//保存W0低字节,即变量bvarldrsh

w1,[x29,18]

//W1←hvarldrb

w2,[x29,17]

//W2←bvar …ldr

w2,[x29,20]

//W2←wvarldr

x1,[x29,24]

//X1←xvar …ldp

x29,x30,[sp],32 //恢复X29和X30,SP增量32,释放占用的栈空间ret80获取地址获取PC相对地址指令: ADRXd,label //Xd=label的地址(1MB范围内) ADRPXd,label //Xd=label的地址(高21位)地址生成操作符: :lo12:label //label的地址低12位//获取4GB范围的相对地址adrpx0,label //X0=地址高21位(低12位为0)add x0,x0,:lo12:label //X0=高21位+低12位=33位地址81载入地址载入地址伪指令: LDRRd,=label //Rd=label的地址(数值)载入地址指令: LDRRt,label //Rt←[label]82【例2-8】自然数求和显示程序1

//C语言程序

unsignedlongN;printf("Enteranumber:");scanf("%lu",&N);printf("TheSumis:%lu\n",(1+N)*N/2);//汇编语言程序,数据区

msgin1: .string"Enteranumber:"

msgin2: .string"%lu"

msgout: .string"TheSumis:%lu\n"

N:

.xword083【例2-8】自然数求和显示程序2//汇编语言程序,代码区

ldr

x0,=msgin1

//X0=msgin1的地址

bl

printf

//显示输入一个数值

ldr

x0,=msgin2

//X0=msgin2的地址

ldr

x1,=N

//X1=变量N的地址

bl

scanf

//输入一个数值

ldr

x1,=N

//X1=变量N的地址

ldr

x1,[x1]

//载入数值:X1=N …

//自然数求和:X1=(1+N)×N÷2

ldr

x0,=msgout

//X0=msgout的地址

bl

printf

//显示自然数求和结果第2章

整型数据处理汇编、汇编一定会编例题上机演示,熟悉指令功能单步调试分析,理解指令实质习题编程实践,掌握指令应用64-bitARMAssembly汇编语言(基于64位ARMv8体系结构)64位ARM汇编语言汇编语言(基于64位ARMv8体系结构)目

录第1章

汇编语言基础第2章

整型数据处理第3章

分支和循环程序第4章

模块化程序设计第5章

浮点数据处理第6章

SIMD数据处理第3章

分支和循环程序3.1

分支指令 3.1.1

无条件分支 3.1.2

条件分支 3.1.3

条件选择 3.1.4

条件比较3.2

分支程序 3.2.1单分支结构 3.2.2双分支结构 3.2.3多分支结构3.3

循环程序 3.3.1计数控制循环 3.3.2条件控制循环 3.3.3多重循环3.1分支指令掌握无条件分支指令

理解指令寻址的相对寻址和寄存器间接寻址掌握条件分支指令

熟悉条件标志NZCV构成的各种条件cond掌握条件选择指令

知晓消除分支的基本方法了解条件比较指令Branch90无条件分支指令(相对寻址)无条件跳转

Blabel

//跳转到label(间接寻址)无条件跳转

BRXn

//跳转到Xn指定的地址

91条件分支指令条件分支指令

B.condlabel//条件cond成立,跳转到label;//否则,顺序执行 cmpx5,100 //比较X5和100 b.hsnext //X5>=100,转移到标号next movx6,0 //X5<100,则X6=0next:92条件cond条件符号含义EQ

Equal,相等(零)NE

NotEqual,不相等(非零)MIMinus,negative,负数PL

Plus,positiveorzero,正数或零VS

oVerflowSet,溢出VC

oVerflowClear,未溢出CS|HS

CarrySet|HigherorSame,进位、无符号高于或等于CC|LO

CarryClear|Lower,无进位,无符号低于HI

unsignedHigher,无符号高于LS

unsignedLowerorSame,无符号低于或等于GE

signedGreaterthanorEqual,有符号大于或等于LT

signedLessThan,有符号小于GT

signedGreaterThan,有符号大于LE

signedLessthanorEqual,有符号小于或等于93比较数据是否为0的分支指令Rt为0跳转

CBZlabelcmpRt,0 //比较Rt是否为0b.eqlabel //为0,转移到labelRt不为0跳转

CBNZlabelcmpRt,0 //比较Rt是否为0b.nelabel //不为0,转移到label94测试某位是否为0的分支指令Rt的imm6位为0跳转

TBZRt,imm6,labeltbzw1,0,again//W1最低位为0,转移Rt的imm6不为0跳转

TBNZRt,imm6,labeltbnzw1,31,again//W1最高位为1,转移95条件选择指令指令指令格式条件成立条件不成立条件选择CSELRd,Rn,Rm,condRd=RnRd=Rm条件选择增量CSINCRd,Rn,Rm,condRd=RnRd=Rm+1条件选择求反CSINVRd,Rn,Rm,condRd=RnRd=~Rm条件选择求补CSNEGRd,Rn,Rm,condRd=RnRd=-Rm条件增量CINCRd,Rn,condRd=Rn+1Rd=Rn条件求反CINVRd,Rn,condRd=~RnRd=Rn条件求补CNEGRd,Rn,condRd=-RnRd=Rn条件置位CSETRd,condRd=1Rd=0条件屏蔽CSETMRd,condRd=-1Rd=096条件比较指令指令指令格式条件成立设置NZCV立即数条件比较CCMPRn,imm5,nzcv,condRn-imm5寄存器条件比较CCMPRn,Rm,nzcv,condRn-Rm立即数条件负数比较CCMNRn,imm5,nzcv,condRn+imm5寄存器条件负数比较CCMNRn,Rm,nzcv,condRn+Rm条件成立,由比较结果设置NZCV;条件不成立,则NZCV=nzcv3.2分支程序掌握单分支程序结构

能够正确设置和选择条件掌握双分支程序结构

知晓双分支结构如何汇合到共同位置熟悉多分支程序结构

了解利用地址表编程的方法If-then98【例3-1】求绝对值1 cmp

x1,0

//与0比较 b.ge

done

//X1≥0,跳转 neg

x1,x1

//X1<0,负数求补done:

//使用条件求补指令优化,消除分支 cmp

x1,0

//与0比较 cneg

x1,x1,lt //X1<0,X1=0-X1;否则,X1=X199【例3-1】求绝对值2 cmp

x1,0

//与0比较 b.ge

next

//X1<0,跳转 b donenext:neg

x1,x1

//X1<0,负数求补done:

单分支结构需正确选择条件分支指令100【例3-3】位测试 tbz

x5,5,nomsg //位5为0,转移 ldr

x0,=yes_msg //位5为1,取yes_msg地址 b

done

//无条件跳转到done标号nomsg: ldr

x0,=no_msg //取no_msg地址done: 双分支结构无条件分支指令必不可少101【例3-5】地址表

sub

x0,x0,'0'

//将数字字符转换为数字

adr

x1,table

//X1←表地址

ldr

x0,[x1,x0,lsl3] //X0←对应编号的转移地址

br

x0disp1:

ldr

x0,=msg1

//X0=信息1的地址

b

dispdisp2:

…dispe:

ldr

x0,=msge

//X0=错误提示的地址disp:

bl

printf

//显示信息table:

.xword

dispe,disp1,disp2,disp3,disp4,disp5,disp63.3循环程序掌握计数控制循环的编程

区别增量计数和减量计数掌握条件控制循环的编程

区别“先判断后循环”和“先循环后判断”结构熟悉多重循环的编程

分辨内外循环,确定循环始末

Loop103【例3-6】求最大值1

adr

x2,array

//X2=数组首地址

ldr

w0,[x2]

//第一个元素给W0,暂存最大值

mov

x3,count-1

//X3=元素个数减1是循环次数again:

ldr

w1,[x2,4]!

//取下一个元素给W1

cmp

w0,w1

//与下一个数据比较

b.ge

next

//W0是较大值,继续下一个循环

mov

w0,w1

//W0取得更大的数据array:

.word

-3,0,20,… //假设一个数组count

=

(.-array)/4

//数组的元素个数max:

.word

0

//存放最大值104【例3-6】求最大值2

mov

x3,count-1

//X3=元素个数减1是循环次数again:… …

next:

subs

x3,x3,1

//循环次数减1,并设置标志

b.ne

again

//循环次数不为0,继续循环

adr

x1,max

str

w0,[x1]

//保存最大值减量计数控制循环结构105【例3-6】求最大值3

mov

x3,1

//X3=1,指向下一个元素again:

ldr

w1,[x2,x3,lsl2] //取出下一个元素给W1

cmp

w0,w1

//与下一个数据比较

csel

w0,w0,w1,ge //X0取得较大值

add

x3,x3,1

//X3增量,指向下一个元素

cmp

x3,count

//是否为最后一个元素

b.lo

again

//不是最后一个元素,继续循环增量计数控制循环结构106【例3-8】字符个数统计

mov

x0,xzr //X0记录字符个数,也是指向字符的指针

ldr

x1,=msg //X1获得字符串地址again:

ldrb

w2,[x1,x0] //载入一个字符

cbz

w2,done

//W2为0,字符串结尾,结束计数

add

x0,x0,1 //个数加1

b

again

//继续循环done:

//个数统计的结果保存于X0寄存器msg: .string"DoyouhavefunwithAssembly?" //0结尾字符串先判断后循环结构107【例3-9】斐波那契数列

mov

x1,3

//X1保存N值(从N=3开始循环)

mov

x2,1

//X2保存F(N-1):F(2)=1

mov

x3,1

//X3保存F(N-2):F(1)=1again:

adds

x4,x2,x3 //X4=F(N)=F(N-1)+F(N-2),设置标志

add

x1,x1,1 //N增量,为下一次循环准备

mov

x3,x2 //上次F(N-1)成为下次的F(N-2):X3=F(N-2)

mov

x2,x4 //上次F(N)成为下次的F(N-1):X2=F(N-1)

b.cc

again

//没有超出范围,继续循环先循环后判断结构F(1)=F(2)=1 N=1、2F(N)=F(N-1)+F(N-2)

N≥3108【例3-11】冒泡法排序1

mov

x5,

count-1

//外循环计数器X5=数组元素个数-1outlp:

mov

x4,x5

//内循环计数器X4=X5

ldr

x3,=array

//X3=数组首地址inlp:

ldr

w1,[x3]

//取前一个元素

ldr

w2,[x3,4]

//取后一个元素

cmp

w1,w2

//前后两个元素比较

b.le

next

//前一个不大于后一个元素,则不进行交换array:

.word

587,-632,… //0结尾字符串count

=

(.-array)/4

//数组的元素个数109【例3-11】冒泡法排序2

cmp

w1,w2

//前后两个元素比较

b.le

next

//前一个不大于后一个元素,则不进行交换

str

w2,[x3]

//否则,交换W1和W2保存的位置

str

w1,[x3,4]next:

add

x3,x3,4

//指向下一个元素

subs

x4,x4,1

//内循环次数减1

b.ne

inlp

//内循环尾

subs

x5,x5,1

//外循环次数减1

b.ne

outlp

//外循环尾计数控制多重循环结构第3章

分支和循环程序汇编、汇编一定会编例题上机演示,熟悉程序结构单步调试分析,理解控制流程习题编程实践,掌握编程方法64-bitARMAssembly汇编语言(基于64位ARMv8体系结构)64位ARM汇编语言汇编语言(基于64位ARMv8体系结构)目

录第1章

汇编语言基础第2章

整型数据处理第3章

分支和循环程序第4章

模块化程序设计第5章

浮点数据处理第6章

SIMD数据处理4.1

子程序及其调用 4.1.1

调用与返回指令 4.1.2

调用规范 4.1.3

模块化方法4.2

与C语言的混合编程 4.2.1模块连接 4.2.2嵌入汇编4.3Linux系统功能调用 4.3.1调用方法 4.3.2调用示例第4章

模块化程序设计4.4

A64系统类指令 4.4.1A64系统控制指令 4.4.2A64特殊存储器访问指令4.1子程序及其调用掌握调用与返回指令

熟悉子程序编程方法掌握64位ARM调用规范熟悉寄存器使用、栈帧和参数传递熟悉各种模块化编程方法

了解宏、源文件包含熟悉模块连接、静态库和共享库CallReturn116调用与返回指令调用指令

BLlabel //X30=PC+4,跳转到label BLRXn //X30=PC+4,跳转到Xn保存的地址返回指令

RET{Xn}//跳转到Xn保存的地址117【例4-1】大小写字母转换-主程序 ldr

x0,=msg //子程序的参数(字符串地址)

bl

tolower

//调用子程序,将字符串处理为小写字母 mov

x2,x0

//子程序返回值保存于X2,作为printf的参数2 ldr

x1,=msg //X1=printf的参数1 ldr

x0,=form //X0=printf的参数0 bl

printf

//显示字符串msg: .string

"DREAMitPOSSIBLE!\n"form: .string

"Themessageis:%sThelengthis%lu\n"118【例4-1】大小写字母转换-子程序1 .globaltolower //子程序:将指定字符串的大写字母全部转换为小写 .typetolower,%function

//参数:X0=字符串地址,返回值:X0=字符串长度tolower:

//子程序标号,即子程序名 mov

x2,0

//用于统计字符个数(初值为0)tol1: ldrb

w1,[x0,x2]

//W1载入一个字符 cbz

w1,tol3

//W1为0,字符串结尾,结束计数 cmp

w1,'A'

//与大写字母A比较 b.lo

tol2

//小于'A',不是大写字母,结束 cmp

w1,'Z'

//与大写字母Z比较 b.hi

tol2

//大于'Z',不是大写字母,结束119【例4-1】大小写字母转换-子程序2 orr

w1,w1,0x20

//大写字母转换为小写字母 strb

w1,[x0,x2]

//存入原位置tol2: add

x2,x2,1

//指向下一个字符 b

tol1

//继续循环tol3: mov

x0,x2

//返回值X0=X2(字符串长度)

ret子程序设计有一个标识符作为子程序名,并作为第一条可执行指令的标号子程序安排在代码区的主程序之外,使用RET指令返回主程序关注子程序的栈帧,保持栈的平衡主程序与子程序之间要遵循相同的调用规范120过程调用标准AAPCS64参数寄存器(X0~X7)

子程序(函数)的前8个参数依次通过X0~X7传递,

返回值通过X0传递调用者保存的临时寄存器(X9~X15)

子程序可以使用X0~X18,无需保护被调用者保存的寄存器(X19~X29)

子程序使用X19~X30前需要保护、使用后恢复原值特殊用途的寄存器(X8、X16~X18、X29和X30)

寄存器X29用作函数的帧指针FP

寄存器X30是连接寄存器LR121栈帧(StackFrame)调用函数时,创建栈帧①

调用程序入栈参数②

被调用程序预留栈帧空间,

将X29和X30保护压入栈帧③X29赋值,用于访问栈帧④寄存器保护栈帧⑤

局部变量存储到栈帧122子程序完整框架 .globalsubname

//子程序名subname .typesubname,%functionsubname:

//子程序入口 stp

x29,x30,[sp,-16]! //保护寄存器X29、X30 …

//保护其他寄存器,减量SP、预留空间 …

//实现子程序功能 …

//恢复其他寄存器,增量SP、释放空间 ldp

x29,x30,[sp],16 //恢复寄存器X29、X30

ret

//子程序返回123模块化方法:宏宏定义

.MACRO

宏名参数1,参数2,… … //宏定义体

.ENDM宏调用

宏名参数1,参数2,参数3,…//宏定义.macro

pushreg1,reg2stp\reg1,\reg2,[sp,-16]!.endm.macro

popreg1,reg2ldp\reg1,\reg2,[sp],16.endm//宏调用push

x29,x30 //压入栈pop

x29,x30 //弹出栈//宏展开stpx29,x30,[sp,-16]!ldpx29,x30,[sp],16124模块化方法:源文件包含源文件包含指示符

.INCLUDE“源文件名”//源文件包含.include“e405_macro.s”//e405_macro.s文件中的宏定义 .macro

tolowerreg //宏定义起始 mov

x2,001: ldrb

w1,[\reg,x2] cbz

w1,03f

… b

01b

03: .endm

//宏定义结束125模块化方法:模块连接//主程序e401_main.s…//子程序e401_sub.s.text.globaltolower.typetolower,%function…子程序生成目标模块文件,主程序连接

gcc-c

e401_sub.s gcc-oe401e401_main.se401_sub.o126模块化方法:静态库//主程序e401_main.s…//子程序e401_sub.s.text.globaltolower.typetolower,%function…创建目标模块静态文件库,主程序连接

ar

r

libstring.a

e401

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论