常用的ARM汇编指令总结
第一次写博客,请各路大神多多关照。
本人从事软件开发相关的工作,平时主要用c语言撸代码,前段时间因工作需要,接触到了ARM架构下的汇编指令,之前学过51单片机的汇编指令,早已经还给老师了,且ARM汇编指令与51的也有很大差别。故搞ARM汇编指令时,遇到不懂的就问度娘,并总结了下来,希望对从事相关行业的同仁有所帮助。闲话不多说,上干货。
1、 IMPORT和EXPORT
IMPORT ,定义表示这是一个外部变量的标号,不是在本程序定义的
EXPORT ,表示本程序里面用到的变量提供给其他模块调用的。
以上两个在汇编和C语言混合编程的时候用到。
2、AREA
语法格式:
AREA 段名 属性1 ,属性2 ,……
AREA伪指令用于定义一个代码段或数据段。其中,段名若以数字开头,则该段名需用“|”括起来,如:|1_test|。
属性字段表示该代码段(或数据段)的相关属性,多个属性用逗号分隔。常用的属性如下:
— CODE 属性:用于定义代码段,默认为READONLY 。
— DATA 属性:用于定义数据段,默认为READWRITE 。
— READONLY 属性:指定本段为只读,代码段默认为READONLY 。
— READWRITE 属性:指定本段为可读可写,数据段的默认属性为READWRITE 。
— ALIGN 属性:使用方式为ALIGN表达式。在默认时,ELF(可执行连接文件)的代码段和数据段是按字对齐的,表达式的取值范围为0~31,相应的对齐方式为2表达式次方。
— COMMON 属性:该属性定义一个通用的段,不包含任何的用户代码和数据。各源文件中同名的COMMON段共享同一段存储单元。
一个汇编语言程序至少要包含一个段,当程序太长时,也可以将程序分为多个代码段和数据段。
使用示例:
AREA Init ,CODE ,READONLY ; 该伪指令定义了一个代码段,段名为Init ,属性为只读。3、LDR、LDRB、LDRH
ARM微处理器支持加载/存储指令用于在寄存器和存储器之间传送数据,加载指令用于将存储器中的数据传送到寄存器,存储指令则完成相反的操作。常用的加载存储指令如下:
— LDR 字数据加载指令
— LDRB 字节数据加载指令
— LDRH 半字数据加载指令
1) LDR指令有两种用法:
a、ldr加载指令
LDR指令的格式为:
LDR{条件} 目的寄存器,<存储器地址>
LDR指令用亍从存储器中将一个32位的字数据传送到目的寄存器中。该指令通常用于从存储器中读取32位的字数据到通用寄存器,然后对数据迕行处理。当程序计数器PC作为目的寄存器时,指令从存储器中读取的字数据被当作目的地址,从而可以实现程序流程的跳转。该指令在程序设计中比较常用,丏寻址方式灵活多样,请读者认真掌握。
指令示例:
LDR R0,[R1] ;将存储器地址为R1的字数据读入寄存器R0。
LDR R0,[R1,R2] ;将存储器地址为R1+R2的字数据读入寄存器R0。
LDR R0,[R1,#8] ;将存储器地址为R1+8的字数据读入寄存器R0。
LDR R0,[R1,R2]!;将存储器地址为R1+R2的字数据读入寄存器R0,幵将新地址R1+R2写入R1。
LDR R0,[R1,#8]! ;将存储器地址为R1+8的字数据读入寄存器R0,幵将新地址R1+8写入R1。
LDR R0,[R1],R2 ;将存储器地址为R1的字数据读入寄存器R0,幵将新地址R1+R2写入R1。
LDR R0,[R1,R2,LSL#2]! ;将存储器地址为R1+R2×4的字数据读入寄存器R0,并将新地址R1+R2×4写入R1。
LDR R0,[R1],R2,LSL#2 ;将存储器地址为R1的字数据读入寄存器R0,幵将新地址R1+R2×4写入R1。”ARM是RISC结构,数据从内存到CPU间的移劢只能通过L/S指令来完成,也就是ldr/str指令。
比如想把数据从内存中某处读取到寄存器中,只能使用ldr
比如:
ldr r0, 0x12345678
就是把0x12345678返个地址中的值存放到r0中。b、ldr伪指令
ARM指令集中,LDR通常都是作加载指令的,但是它也可以作伪指令。
LDR伪指令的形式是“LDRRn,=expr”。
例子:
COUNT EQU 0x40003100
……
LDR R1,=COUNT
MOV R0,#0
STR R0,[R1]COUNT是我们定义的一个变量,地址为0x40003100。这种定义方法在汇编语言中是很常见的,如果使用过单片机的话,应该都熟悉这种用法。
LDR R1,=COUNT是将COUNT这个变量的地址,也就是0x40003100放到R1中。
MOV R0,#0是将立即数0放到R0中。最后一句STR R0,[R1]是一个典型的存储指令,将R0中的值放到以R1中的值为地址的存储单元去。实际就是将0放到地址为0x40003100的存储单元中去。下面还有一个例子
;将COUNT的值赋给R0
LDR R1,=COUNT
LDR R0,[R1]
LDR R1,=COUNT这条伪指令,是怎样完成将COUNT的地址赋给R1,有兴趣的可以看它编译后的结果。这条指令实际上会编译成一条LDR指令和一条DCD伪指令。2) LDRB指令
LDRB指令的格式为:
LDR{条件}B 目的寄存器,<存储器地址>
LDRB指令用于将存储器中低8位的字节数据传送到目的寄存器中,同时将寄存器的高24位清零,然后对数据进行处理。当程序计数器PC作为目的寄存器时,指令从存储器中读取的数据被当作目的地址,从而可以实现程序流程的跳转。
指令示例:
LDRB R0,[R1] ;将存储器地址为R1的字节数据读入寄存器R0,并将R0的高24位清零。
LDRB R0,[R1,#8] ;将存储器地址为R1+8的字节数据读入寄存器R0,并将R0的高24位清零。
3) LDRH指令
LDRH指令的格式为:
LDR{条件}H 目的寄存器,<存储器地址>
LDRH指令用于将存储器中低16位的半字数据传送到目的寄存器中,同时将寄存器的高16位清零,然后对数据进行处理。当程序计数器PC作为目的寄存器时,指令从存储器中读取的字数据被当作目的地址,从而可以实现程序流程的跳转。
指令示例:
LDRH R0,[R1] ;将存储器地址为R1的半字数据读入寄存器R0,并将R0的高16位清零。
LDRH R0,[R1,#8] ;将存储器地址为R1+8的半字数据读入寄存器R0,并将R0的高16位清零。
LDRH R0,[R1,R2] ;将存储器地址为R1+R2的半字数据读入寄存器R0,并将R0的高16位清零。
4、SUB
(Subtraction)
SUB{条件}{S} , , dest = op_1 - op_2
SUB 用操作数 one 减去操作数 two,把结果放置到目的寄存器中。操作数 1 是一个寄存器,操作数 2 可以是一个寄存器,被移位的寄存器,或一个立即值:
SUB R0, R1, R2 ;R0 = R1 - R2
SUB R0, R1, #256; R0 = R1 - 256
SUB R0, R2,R3,LSL#1 ; R0 = R2 - (R3 << 1)
减法可以在有符号和无符号数上进行。
ps:带进位的减法SBC
5、CMP 、TST、BNE、BEQ
BNE和BEQ经常与CMP 或TST搭配使用。
在讲解这几个指令前,先介绍下CPSR这个寄存器,因为CMP和TST指令会对CPSR中的某些位产生影响,而BNE和BEQ指令的动作正是与CPSR中被影响的这些位有关。
CMP:
假设现在AX寄存器中的数是0002H,BX寄存器中的数是0003H。执行的指令是:CMP AX, BX
执行这条指令时,先做用AX中的数减去BX中的数的减法运算。列出二进制运算式子:
0000 0000 0000 0010-0000 0000 0000 0011
_________________________________
(借位1) 1111 11111111 1111所以,运算结果是 0FFFFH
根据这个结果,各标志位将会被分别设置成以下值:
CF=1,因为有借位 // CF即为上述CPSR中的C
OF=0,未溢出 // OF即为上述CPSR中的V
SF=1,结果是负数 // SF即为上述CPSR中的N
ZF=0,结果不全是零 // ZF即为上述CPSR中的Z还有AF, PF等也会相应地被设置。
CMP 比较指令做了减法运算以后,根据运算结果设置了各个标志位。
标志位设置过以后,0FFFFH这个减法运算的结果就没用了,它被丢弃,不保存。
执行过了CMP指令以后,除了CF,ZF,OF,SF,等各个标志位变化外,其它的数据不变。
对照普通的减法指令 SUB AX, BX,它们的区别就在于:
SUB指令执行过以后,原来AX中的被减数丢了,被换成了减法的结果。
CMP指令执行过以后,被减数、减数都保持原样不变。TST:
逻辑处理指令,用于把一个寄存器的内容和另一个寄存器的内容或立即数进行按位与运算,并根据运算结果更新CPSR中条件标志位的值。当前运算结果为非0,则Z=0;当前运算结果为0,则Z=1
BEQ:数据跳转指令,标志寄存器中Z标志位不等于零时, 跳转到BEQ后标签处
6、STR、STRB、STRH指令
STR指令用于从源寄存器中将一个32位的字数据传送到存储器中。该指令在程序设计中比较常用,且寻址方式灵活多样,使用方式可参考指令LDR。
STR R0,[R1],#8 ;将R0中的字数据写入以R1为地址的存储器中,并将新地址R1+8写入R1。
STR R0,[R1,#8] ;将R0中的字数据写入以R1+8为地址的存储器中。
STRB指令用于从源寄存器中将一个8位的字节数据传送到存储器中。该字节数据为源寄存器中的低8位。
STRB R0,[R1] ;将寄存器R0中的字节数据写入以R1为地址的存储器中。
STRB R0,[R1,#8] ;将寄存器R0中的字节数据写入以R1+8为地址的存储器中。
STRH指令用于从源寄存器中将一个16位的半字数据传送到存储器中。该半字数据为源寄存器中的低16位。
STRH R0,[R1] ;将寄存器R0中的半字数据写入以R1为地址的存储器中。
STRH R0,[R1,#8] ;将寄存器R0中的半字数据写入以R1+8为地址的存储器中。
7、跳转指令B、BL、BX、BLX 和 BXJ的区别
跳转指令用于实现程序流程的跳转,在 ARM 程序中有两种方法可以实现程序流程的跳转:
通过向程序计数器 PC 写入跳转地址值,可以实现在4GB 的地址空间中的任意跳转,在跳转之前结合使用
等类似指令,可以保存下一条指令地址作为将来的返回地址值,从而实现在 4GB 连续的线性地址空间的子程序调用。
跳转、带链接跳转(带返回的跳转)、跳转并切换指令集、带链接跳转并切换指令集(带返回的跳转并切换指令集)、跳转并转换到 Jazelle 状态。
CMP R1 ,# 0 ;当 CPSR 寄存器中的 Z 条件码置位时,程序跳转到标号Label 处执行
BL Label ;当程序无条件跳转到标号 Label 处执行时,同时将当前的 PC 值保存到 R14 中
同时,子程序的返回可以通过将寄存器R14 值复制到PC 中来完成。
BX{条件} 目标地址
BX 指令跳转到指令中所指定的目标地址,目标地址处的指令既可以是ARM 指令,也可以是Thumb指令。
语法
op1{cond}{.W}<wbr />label
op2{cond} <wbr />Rm其中:
op1
是下列项之一:
B:跳转;BL:带链接跳转;BLX:带链接跳转并切换指令集。
op2
是下列项之一:
BX:跳转并切换指令集;BLX:带链接跳转并切换指令集;
BXJ:跳转并转换为Jazelle执行。
cond:是一个可选的条件代码。 cond 不能用于此指令的所有形式。
.W:是一个可选的指令宽度说明符,用于强制要求在 Thumb-2 中使用 32 位 B 指令。
label:是一个程序相对的表达式。
Rm:是一个寄存器,包含要跳转到的目标地址。
所有这些指令均会引发跳转,或跳转到 label,或跳转到包含在Rm中的地址处。此外:
BL 和 BLSTMCSIAX 指令可将下一个指令的地址复制到 lr(r14,链接寄存器)中。
BX 和 BLX 指令可将处理器的状态从 ARM 更改为 Thumb,或从 Thumb 更改为 ARM。
BLX label 无论何种情况,始终会更改处理器的状态。
BX Rm 和 BLX Rm 可从 Rm 的位 [0] 推算出目标状态:
如果 Rm 的位 [0] 为 0,则处理器的状态会更改为(或保持在)ARM 状态
如果 Rm 的位 [0] 为 1,则处理器的状态会更改为(或保持在)Thumb 状态。
BXJ 指令会将处理器的状态更改为 Jazelle
8、STMFD和LDMFD指令
这两条指令分别是入栈和出栈的意思,因此先来讲一下堆栈的相关概念:
a) 满堆栈:即入栈后堆栈指针sp指向最后一个入栈的元素。也就是sp先减一(加一)再入栈。
b) 空堆栈:即入栈后堆栈指针指向最后一个入栈元素的下一个元素。也就是先入栈sp再减一(或加一)。
c) 递增堆栈:即堆栈一开始的地址是低地址,向高地址开始递增。就如同一个水杯(假设上面地址大)开口的是大地址,从杯底开始装水。
d) 递减堆栈:即堆栈一开始的地址是高地址,向低地址开始递增。就如同刚才说的那个水杯,现在开口的是小地址,从大地址开始用。
有这些类型就可以构成4种不同的堆栈方式,arm的栈一般我们用满堆栈、递减堆栈。
一开始,看到 STMFD sp!{R0-R5,LR} 这条命令时真是有点疑惑。STMFD的意思是:ST(store 存储) M(multiple 多次)F(full 满堆栈)D(decrease 递减堆栈),合起来就是按满的递减的方式把后面的寄存器里的值都存到sp中。
STMFD sp!{R0-R5,LR}就是把lr r5-r0 依次存到sp中,并且sp会在存数据之前自动减一个数据的空间(因为arm栈是递减的)。至于最后一个问题,就是sp后为什么有一个“!”。如果有!号,表示在存入数据后sp会指向最后一个存入的数据的地址,否则sp会把自己的值加到一开始的地址。(就是sp在执行完这条指令之后sp指向的地址不变)。
例子:STMFD sp!,{r0} ;将r0中的值压入堆栈,压入过程是,由于r0中的值为32位的,首先将sp减去4(因为arm栈是递减的),将r0中的低八位放入sp这个位置,第九位到第十六位放入sp+1的地址,将第十七位到第二十四位放入sp+2的位置,将第二十五位到第三十二位放入sp+3的位置。
LDMFD sp!,{r2,r3};将堆栈中的内容出栈,出栈过程是,将sp这个位置的值放入r2中的低八位,将sp+1这个位置的值放入r2中的第九位到第十六位,将sp+2这个位置的值放入r2中的第十七位到第二十四位,将sp+3这个位置的值放入r2中的第二十五位到第三十二位;将sp+4这个位置的值放入r3中的低八位,将sp+5这个位置的值放入r3中的第九位到第十六位,将sp+6这个位置的值放入r3中的第十七位到第二十四位,将sp+4这个位置的值放入r3中的第二十五位到第三十二位。最后sp=sp+8。
此外,STR指令也可以用来入栈:strr1, [sp,#4] ,将r1中的值压入堆栈,压入过程是,由于r1中的值为32位的,将r0中的低八位放入sp+4这个位置,第九位到第十六位放入sp+5的地址,将第十七位到第二十四位放入sp+6的位置,将第二十五位到第三十二位放入sp+7的位置。
9、移位指令(操作)
a) LSL(或ASL)操作
LSL(或ASL)操作的格式为:
通用寄存器,LSL(或ASL) 操作数
LSL(或ASL)可完成对通用寄存器中的内容进行逻辑(或算术)的左移操作,按操作数所指定的数量向左移位,低位用零来填充。其中,操作数可以是通用寄存器,也可以是立即数(0~31)。
操作示例
MOV R0, R1,LSL#2 ;将R1中的内容左移两位后传送到R0中。
b) LSR操作
LSR操作的格式为:
通用寄存器,LSR 操作数
LSR可完成对通用寄存器中的内容进行右移的操作,按操作数所指定的数量向右移位,左端用零来填充。其中,操作数可以是通用寄存器,也可以是立即数(0~31)。
操作示例:
MOV R0, R1, LSR#2 ;将R1中的内容右移两位后传送到R0中,左端用零来填充。
c) ASR操作
ASR操作的格式为:
通用寄存器,ASR 操作数
ASR可完成对通用寄存器中的内容进行右移的操作,按操作数所指定的数量向右移位,左端用第31位的值来填充。其中,操作数可以是通用寄存器,也可以是立即数(0~31)。
操作示例:
MOV R0, R1, ASR#2 ;将R1中的内容右移两位后传送到R0中,左端用第31位的值来填充。
d) ROR操作
ROR操作的格式为:
通用寄存器,ROR 操作数
ROR可完成对通用寄存器中的内容进行循环右移的操作,按操作数所指定的数量向右循环移位,左端用右端移出的位来填充。其中,操作数可以是通用寄存器,也可以是立即数(0~31)。显然,当进行32位的循环右移操作时,通用寄存器中的值不改变。
操作示例:
MOV R0, R1, ROR#2 ;将R1中的内容循环右移两位后传送到R0中。
e) RRX操作
RRX操作的格式为:
通用寄存器,RRX 操作数
RRX可完成对通用寄存器中的内容进行带扩展的循环右移的操作,按操作数所指定的数量向右循环移位,左端用进位标志位C来填充。其中,操作数可以是通用寄存器,也可以是立即数(0~31)。
操作示例:
MOV R0, R1,RRX#2 ;将R1中的内容进行带扩展的循环右移两位后传送到R0中。
f) SHL和SHR:逻辑移位指令。
SHL是逻辑左移指令,它的功能为:
(1)将一个寄存器或内存单元中的数据向左移位;
(2)将最后移出的一位写入CF中;
(3)最低位用0补充。
指令:
MOV AL,01001000bSHL AL,1 ;将AL中数据左移一位
执行后(AL)=10010000b,CF=0。
注意:
如果移动位数大于1时,必须将移动位数放在CL中。
比如,指令:
MOV AL,01010001b
MOV CL,3
SHL AL,CL
执行后(AL)=10001000b,因为最后移出的一位是0,所以CF=0。LDRB
SHR是逻辑右移指令,它和SHL所进行的操作刚好相反。
10、逻辑指令
a) AND
逻辑与操作指令。将operand2 值与寄存器Rn 的值按位作逻辑与操作,结果保存到Rd 中。指令格式如下:
AND{cond}{S} Rd,Rn,operand2
AND 指令举例如下:
ANDS R0,R0,#x01 ;R0=R0&0x01,取出最低位数据
AND R2,R1,R3 ;R2=R1&R3b) ORR
逻辑或操作指令。将operand2 的值与寄存器Rn 的值按位作逻辑或操作,结果保存到Rd 中。指令格式如下:
ORR{cond}{S} Rd,Rn,operand2
ORR 指令举例如下:
ORR R0,R0,#x0F ;将R0 的低4 位置1
MOV R1,R2,LSR #4
ORR R3,R1,R3,LSL #8 ;使用ORR 指令将近R2 的高8 位数据移入到R3 低8 位中c) EOR
逻辑异或操作指令。将operand2 的值与寄存器Rn 的值按位作逻辑异或操作,结果保存到Rd 中。指令格式如下:
EOR{cond}{S}Rd,Rn,operand2
EOR 指令举例如下:
EOR R1,R1,#0x0F ;将R1 的低4 位取反
EOR R2,R1,R0 ;R2=R1^R0
EORS R0,R5,#0x01 ;将R5 和0x01 进行逻辑异或,结果保存到R0,并影响标志位11、条件助记符
ARM汇编指令的基本指令格式如下:
<opcode>[<cond>][s]<Rd>,<Rn>,[<op2>],其中,[<参数>]可选,指令长度32bit。第一项为操作码,第二项为条件助记符。常用的条件助记符及其含义如下表所示。由指令格式可知,操作码可与条件助记符结合起来一起使用,如MOVEQ,MOVNE,BLS等等,根据下表中条件助记符的含义和操作码的含义,对于上述组合命令也就不难理解了。
操作码
条件助记符
标志
含义
0000
EQ
Z=1
相等
0001
NE
Z=0
不相等
0010
CS/HS
C=1
无符号数大于或等于
0011
CC/LO
C=0
无符号数小于
0100
MI
N=1
负数
0101
PL
N=0
正数或零
0110
VS
V=1
溢出
0111
VC
V=0
没有溢出
1000
HI
C=1,Z=0
无符号数大于
1001
LS
C=0,Z=1
无符号数小于或等于
1010
GE
N=V
有符号数大于或等于
1011
LT
N!=V
有符号数小于
1100
GT
Z=0,N=V
有符号数大于
1101
LE
Z=1,N!=V
有符号数小于或等于
1110
AL
任何
无条件执行 (指令默认条件)
1111
NV
任何
从不执行(不要使用)
常用的ARM汇编指令总结相关推荐
- 常用的arm汇编指令(3) -学无止尽,积土成山,积水成渊
1. NEGS R3, R2; 求补指令 带进位加法指令 ADC(Addition Carry); Bpl是跳转指令,其中pl代表正号+,Bpl也就是当结果为正时,跳转; ORR( ...
- ARM 汇编指令 MOV32用法
前言 移植基于ARM平台的RTOS时,需要掌握一些基本的汇编指令,只有熟悉了这些ARM 的汇编指令,才能真正的掌握RTOS的移植方法 MOV32 指令,字面意思是 MOVE 一个 32位 值的意思,具 ...
- ARM汇编指令调试方法
学习ARM汇编时,少不了对ARM汇编指令的调试.作为支持多语言的调试器,gdb自然是较好的选择.调试器工作时,一般通过修改代码段的内容构造trap软中断指令,实现程序的暂停和程序执行状态的监控.为了在 ...
- arm汇编指令详细整理及实例详解
目录 一.简介 二.ARM 汇编指令说明 2.1 32位数据操作指令 2.2 32位存储器数据传送指令 2.3 32位转移指令 2.4 其它32位指令 三.实例讲解 3.1 MRS 3.2 MSR 3 ...
- arm汇编指令——分析问题的利器
文章目录 arm汇编指令为什么重要 1. 主导问题 2. arm汇编指令分类介绍 通用寄存器 状态寄存器 数据转移指令 寻址格式 运算指令 比较指令 跳转指令 3. 反汇编接口 4. 反汇编分析举例 ...
- ARM汇编指令学习---基于启动文件startup.S分析
本文主要是基于启动文件startup.s对ARM汇编指令进行学习分析. 以 . 开头一般是伪汇编/操作指令,形如: .section伪操作来定义一个段,形如: .section .testsectio ...
- 嵌入式工程师到底要不要学习ARM汇编指令?arm学习文章汇总
嵌入式工程师到底要不要学习ARM汇编指令? 网上搜索这个问题,答案很多,大部分的建议是不要学汇编,只要学C语言. 而一口君作为一个十几年经验的驱动工程师,个人认为,汇编语言还是需要掌握的,想要搞精.搞 ...
- ida pro 反汇编 Android so 库后修改 arm 汇编指令的方法总结
1 前言 最近博主在学习Android逆向的时候,参照吾爱破解论坛的<教我兄弟学Android逆向系列课程>学习的时候,学到第8章<教我兄弟学Android逆向08 IDA爆破签名验 ...
- 1.15.ARM汇编指令3之逻辑指令
ARM汇编指令之逻辑指令:and & orr & eor & bic * and 逻辑与操作指令,将operand2的值与寄存器Rn的值按位逻辑与操作,结果保存到Rd中. 指令 ...
最新文章
- 2019年,比特币现金爱好者线下见面会发展至6大洲30个国家
- 【checkStyle】ignore some class
- python发明者叫什么-看看9种编程语言的发明者是怎么说的
- Git SSH Key 生成并添加到github/gitee步骤
- html5微信摇一摇api,摇一摇关注JSAPI
- Ubuntu Linux 永山(mount)分
- java int相除向上取整_Java基础篇——Java运算符
- Log4j Bug –减慢您的应用程序
- flash影响中文输入
- LeetCode 1263. 推箱子(BFS+DFS / 自定义哈希set)
- LINUX mount -t用法
- 95-10-035-启动-Metrics
- qml入门学习(六):Component组件
- 微服务_SpringCloud微服务架构实战:高并发微服务架构设计
- 快速幂算法(矩阵快速幂还不是很会。。日后会更新)
- 【POJ1101OpenJudge2802】The Game 小游戏(BFS+记忆化)
- 关于抓包软件Fiddler的简单汉化
- 打印日历Java代码实现
- ks检验正态分布结果_SPSS实现Shapiro-Wilk正态分布检验
- 计算机网络水晶头博客,网线水晶头接法顺序图解分享,这个简单口诀记好了(超实用)...
热门文章
- 云呐医院行业固定资产管理系统软件
- 解析Android JNI机制
- PHP+新浪微博开放平台+新浪云平台(SAE)开发微博应用——建立微博应用的过程
- oracle查找某一天的数据,oracle统计时间段内每一天的数据(推荐)
- Oracle IS NULL
- c++ 11 原子操作库 (std::atomic)(二)
- ZCU106开发之SFP
- paraview输出高清晰度带速度箭头颗粒分布图
- Linux+Docker+Tensorlfow 部署探索
- blas daxpy dcopy函数的使用