版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
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. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年辽宁医学院附属第二医院医护人员招聘笔试备考试题及答案详解
- 2026年郑州铁路中心医院医护人员招聘笔试备考试题及答案详解
- 2026年陕西中医药大学第二附属医院(西咸新区中心医院)医护人员招聘考试备考试题及答案详解
- 2026年厦门市第一医院医护人员招聘考试参考试题及答案详解
- 2026年华融湘江银行人员招聘考试参考试题及答案详解
- 2026年中国人民解放军一五O中心医院医护人员招聘考试备考试题及答案详解
- 2026年天津市胸科医院医护人员招聘笔试参考题库及答案详解
- 2026年天津中医药大学第一附属医院医护人员招聘考试参考试题及答案详解
- 2026年衡水市哈励逊国际和平医院医护人员招聘笔试参考题库及答案详解
- 2026年中国人民解放军青岛肝病治疗中心医护人员招聘考试备考题库及答案详解
- 高三生物考前指导课件
- 新疆保密管理办法
- 肝性脑病合并糖尿病护理
- 七一党课:传承红色基因勇担时代使命2025年建党104周年“七一”专题党课
- 带量采购培训课件
- 初三化学最后一课-主题班会【课件】
- 广东省深圳市2025年七年级下学期期末数学模拟试题五套附答案
- 工艺报警分级管理制度
- 建筑工程项目作业现场安全检查手册
- 投资效益评价模型-洞察分析
- 2024年江西省高考物理试卷真题(含答案解析)
评论
0/150
提交评论