ARMv7-A 那些事 - 6.常用汇编指令

news2024/12/27 16:29:20

By: Ailson Jack
Date: 2023.10.07
个人博客:http://www.only2fire.com/
本文在我博客的地址是:http://www.only2fire.com/archives/158.html,排版更好,便于学习,也可以去我博客逛逛,兴许有你想要的内容呢。

对于搞嵌入式驱动或者操作系统的人来说,掌握汇编语言的使用还是比较重要的,毕竟有时候在分析定位问题的时候,多多少少都会有汇编的身影。本文主要讲讲ARM指令集格式以及常用的ARM汇编指令(主要包括LDRSTR指令,LDMSTM指令,pushpop指令,MOV指令,CPS指令,MRSMSR指令,MRCMCR指令,其余指令暂时没列出来,用到时可以查看ARM手册进行了解)。

ARM指令集格式

ARMv7架构是一个32位的处理器架构。同时ARM架构是一个加载/存储体系结构,所有的数据处理操作需要在通用寄存器中完成。

要学习了解处理器的汇编指令,那么首先可以看看汇编指令的通用表达式,具体的指令也就是使用具体的指令和参数代替通用表达式的参数。ARM指令集的指令表达如下所示:

opcode{<cond>}{S} <Rd>, <Rn> {, <Rm>}

opcode:指令助记符,比如LDR,STR,MOV等。

{}:大括号括起来的内容表示可选。

<><>括起来的内容是必须的。

cond:条件码,比如EQ,NE,CS等,条件码的内容如下图所示:

在这里插入图片描述在这里插入图片描述
S:可选的后缀,如果指令中添加了S,那么指令的执行结果将会影响到CPSR寄存器的标志位域。

Rd:目标寄存器。

Rn:第一个操作数寄存器。

Rm:第二个操作数寄存器。

在了解了ARM指令的表达式之后,下面就讲讲常用的汇编指令。

LDR和STR指令

LDR指令用于从内存中读取数据存储到通用寄存器中。STR指令用于将通用寄存器中的值存储到内存中。LDR指令的语法如下所示:

LDR{type}{T}{cond} Rt, [Rn {, #offset}]
LDR{type}{cond} Rt, [Rn, #offset]!
LDR{type}{T}{cond} Rt, [Rn], #offset
LDR{type}{cond} Rt, [Rn, +/-Rm]
LDR{type}{cond} Rt, [Rn, +/-Rm]!
LDR{type}{T}{cond} Rt, [Rn], +/-Rm

STR指令的语法如下所示:

STR{type}{T}{cond} Rt, [Rn {, #offset}]
STR{type}{cond} Rt, [Rn, #offset]!
STR{type}{T}{cond} Rt, [Rn], #offset
STR{type}{cond} Rt, [Rn, +/-Rm]
STR{type}{cond} Rt, [Rn, +/-Rm]!
STR{type}{T}{cond} Rt, [Rn], +/-Rm

type:操作的数据宽度,可以是:B(unsigned byte),SB(signed byte),H(unsigned halfword),SH(signed halfword)。

cond:条件码。

Rt:目标寄存器。

Rn:存储内存操作基地址的寄存器。

Rm:存储偏移量的寄存器。

offset:立即数。

!:如果存在,表示最终的地址要写回Rn

T:表示处理器是在用户模式下访问内存地址。

加载存储指令有4种寻址方式,LDR的操作描述如下(STR指令的操作类似):

  • 寄存器寻址:要寻址的地址存放在寄存器中。
  • 前变基寻址:在内存访问之前,将寄存器中的内存地址加上偏移量之后作为新的内存地址进行内存访问。指令形式为:LDR Rt, [Rn, Op2]。偏移量Op2可以是正数或者是负数,可以是一个立即数,可以是另一个寄存器的值,可以是另一个寄存器中的数据进行移位之后的值。
  • 带写回的前变基寻址:指令形式为:LDR Rt, [Rn, Op2]!。该寻址模式和前变基寻址一样,只是在访问完内存之后Rn寄存器中的值就更新为运算之后得到的新内存地址的值。
  • 带写回的后变基寻址:指令形式为:LDR Rt, [Rn], #offsetLDR Rt, [Rn], +/-Rm。将寄存器Rn中存储的数值作为内存地址,将该内存地址中的数据读出来存储到Rt寄存器中,然后将内存地址加减立即数offset或者Rm寄存器中的数值得到新的内存地址存储到Rn寄存器中。

上面说的这些有可能不太好懂,下面简单的列举几个例子吧:

# 寄存器寻址
# 将R1地址处的数据读出,保存到R0中
LDR R0, [R1]

# 前变基寻址
# 将(R1+0x4)地址处的数据读出,保存到R0中
LDR R0, [R1, #0x4]
# 将(R1-0x4)地址处的数据读出,保存到R0中
LDR R0, [R1, #-0x4]
# 将(R1+R2)地址处的数据读出,保存到R0中
LDR R0, [R1, R2]
# 将((R1+(R2<<2))地址处的数据读出,保存到R0中
LDR R0, [R1, R2, LSL #2]

# 带写回的前变基寻址
# 将(R1+R2)地址处的数据读出,保存到R0中,然后更新R1=R1+R2
LDR R0, [R1, R2]!
# 将((R1+(R2<<2))地址处的数据读出,保存到R0中,然后更新R1=((R1+(R2<<2))
LDR R0, [R1, R2, LSL #2]!

# 带写回的后变基寻址
# 将R1地址处的数据读出,保存到R0中,然后更新R1=R1+0x4
LDR R0, [R1], #0x4
# 将R1地址处的数据读出,保存到R0中,然后更新R1=R1-0x4
LDR R0, [R1], #-0x4
# 将R1地址处的数据读出,保存到R0中,然后更新R1=R1+R2
LDR R0, [R1], R2
# 将R1地址处的数据读出,保存到R0中,然后更新R1=R1-R2
LDR R0, [R1], -R2

STR指令的操作和LDR指令类似,这里就不列举了。

LDR伪指令

LDR相关的伪指令语法如下所示:

# 将数据 constant 加载到 Rt 寄存器中
LDR Rt, =constant

# 将 label 所代表的地址加载到 Rt 寄存器中
LDR Rt, =label

下面是LDR伪指令简单的使用:

# 将 0xaa 加载到 R0 寄存器
LDR R0, =0xaa

# 将 _start 所代表的地址加载到 R0 寄存器
LDR R0, =_start

LDM和STM指令

LDM指令用于加载指定地址上的数据保存到一个或者多个寄存器中。STM指令用于将一个或者多个寄存器中的数据存储到指定地址上。LDMSTM指令主要用于现场保护和数据复制。

LDM指令的语法如下所示:

LDM{addr_mode}{cond} Rn{!},reglist{^}

STM指令的语法如下所示:

STM{addr_mode}{cond} Rn{!},reglist{^}

addr_mode:地址模式,用于数据块传输的地址模式,如下所示:

IA:每次传送后地址加4。
IB:每次传送前地址加4。
DA:每次传送后地址减4。
DB:每次传送前地址减4。

也可以使用相应的面向堆栈的寻址模式,如下所示:

FD:满递减堆栈(每次传送前地址减4)。
ED:空递增堆栈(每次传送前地址加4)。
FA:满递增堆栈(每次传送后地址减4)。
EA:空递增堆栈(每次传送后地址加4)。

cond:条件码。

Rn:Rn存储了用于传输的初始地址。

!:如果存在,表示最终的地址要写回Rn

reglist:用{}括起来的一个寄存器或者多个寄存器组成的列表。它可以是一个寄存器范围。如果{}中的寄存器超过一个,那么寄存器或者寄存器范围之间通过逗号(,)分隔。

^:如果在除了USR模式和SYS模式下存在该符号,意味着将发生下述的两个动作:

  • 当寄存器列表中不包含PC时,加载/存储的是USR模式的寄存器,而不是当前模式的寄存器。
  • 在使用LDM指令时,如果寄存器列表中包含PC时,那么除了正常的多寄存器传送外,会将SPSR 拷贝到CPSR 中,这可用于异常处理返回。

上面的内容可能不是很好理解,下面简单的列举写例子:

LDMIA和STMIA例子

LDMIA例子如下所示:

# IA:每次传送后地址加4,下面是指令执行流程的分解:
# R0=[R1]
# R2=[R1+4]
# R3=[R1+8]
# R4=[R1+12]
LDMIA R1, {R0, R2-R4}

# IA:每次传送后地址加4,最终地址要写回R1,下面是指令执行流程的分解:
# R0=[R1], R1=R1+4
# R2=[R1], R1=R1+4
# R3=[R1], R1=R1+4
# R4=[R1], R1=R1+4
LDMIA R1!, {R0, R2-R4}

STMIA例子如下所示:

# IA:每次传送后地址加4,下面是指令执行流程的分解:
# [R1]=R0
# [R1+4]=R2
# [R1+8]=R3
# [R1+12]=R4
STMIA R1, {R0, R2-R4}

# IA:每次传送后地址加4,最终地址要写回R1,下面是指令执行流程的分解:
# [R1]=R0, R1=R1+4
# [R1]=R2, R1=R1+4
# [R1]=R3, R1=R1+4
# [R1]=R4, R1=R1+4
STMIA R1!, {R0, R2-R4}

LDMIB和STMIB例子

LDMIB例子如下所示:

# IB:每次传送前地址加4,下面是指令执行流程的分解:
# R0=[R1+4]
# R2=[R1+8]
# R3=[R1+12]
# R4=[R1+16]
LDMIB R1, {R0, R2-R4}

# IB:每次传送前地址加4,最终地址要写回R1,下面是指令执行流程的分解:
# R1=R1+4, R0=[R1]
# R1=R1+4, R2=[R1]
# R1=R1+4, R3=[R1]
# R1=R1+4, R4=[R1]
LDMIB R1!, {R0, R2-R4}

STMIB例子如下所示:

# IB:每次传送前地址加4,下面是指令执行流程的分解:
# [R1+4]=R0
# [R1+8]=R2
# [R1+12]=R3
# [R1+16]=R4
STMIB R1, {R0, R2-R4}

# IB:每次传送前地址加4,最终地址要写回R1,下面是指令执行流程的分解:
# R1=R1+4, [R1]=R0
# R1=R1+4, [R1]=R2
# R1=R1+4, [R1]=R3
# R1=R1+4, [R1]=R4
STMIB R1!, {R0, R2-R4}

LDMDA和STMDA例子

LDMDA例子如下所示:

# DA:每次传送后地址减4,下面是指令执行流程的分解:
# R4=[R1]
# R3=[R1-4]
# R2=[R1-8]
# R0=[R1-12]
LDMDA R1, {R0, R2-R4}

# DA:每次传送后地址减4,最终地址要写回R1,下面是指令执行流程的分解:
# R4=[R1], R1=R1-4
# R3=[R1], R1=R1-4
# R2=[R1], R1=R1-4
# R0=[R1], R1=R1-4
LDMDA R1!, {R0, R2-R4}

STMDA例子如下所示:

# DA:每次传送后地址减4,下面是指令执行流程的分解:
# [R1]=R4
# [R1-4]=R3
# [R1-8]=R2
# [R1-12]=R0
STMDA R1, {R0, R2-R4}

# DA:每次传送后地址减4,最终地址要写回R1,下面是指令执行流程的分解:
# [R1]=R4, R1=R1-4
# [R1]=R3, R1=R1-4
# [R1]=R2, R1=R1-4
# [R1]=R0, R1=R1-4
STMDA R1!, {R0, R2-R4}

LDMDB和STMDB例子

LDMDB例子如下所示:

# DB:每次传送前地址减4,下面是指令执行流程的分解:
# R4=[R1-4]
# R3=[R1-8]
# R2=[R1-12]
# R0=[R1-16]
LDMDB R1, {R0, R2-R4}

# DB:每次传送前地址减4,最终地址要写回R1,下面是指令执行流程的分解:
# R1=R1-4, R4=[R1]
# R1=R1-4, R3=[R1]
# R1=R1-4, R2=[R1]
# R1=R1-4, R0=[R1]
LDMDB R1!, {R0, R2-R4}

STMDB例子如下所示:

# DB:每次传送前地址减4,下面是指令执行流程的分解:
# [R1-4]=R4
# [R1-8]=R3
# [R1-12]=R2
# [R1-16]=R0
STMDB R1, {R0, R2-R4}

# DB:每次传送前地址减4,最终地址要写回R1,下面是指令执行流程的分解:
# R1=R1-4, [R1]=R4
# R1=R1-4, [R1]=R3
# R1=R1-4, [R1]=R2
# R1=R1-4, [R1]=R0
STMDB R1!, {R0, R2-R4}

现场保护

在数据块的传输中:STMDBLDMIA对应使用,STMIALDMDB对应使用。

在堆栈操作中:STMFDLDMFD对应使用,STMFALDMFA对应使用。

在子程序或者异常处理时,使用LDMFDSTMFD进行现场保护的例子如下:

# 将R0-R7和LR入栈
STMFD SP!, {R0-R7, LR}

# 功能代码
MOV R0, #0x00
MOV R1, #0x11
MOV R2, #0x22

# 将R0-R7和LR出栈
LDMFD SP!, {R0-R7, LR}

同样的可以使用STMDBLDMIA指令进行现场保护,因此上述代码可以修改成下述形式:

# 将R0-R7和LR入栈
STMDB SP!, {R0-R7, LR}

# 功能代码
MOV R0, #0x00
MOV R1, #0x11
MOV R2, #0x22

# 将R0-R7和LR出栈
LDMIA SP!, {R0-R7, LR}

push和pop指令

pushpop指令主要用于子程序或者异常的现场保护。push指令用于将寄存器内容压入堆栈。pop指令用于将堆栈中的内容恢复到寄存器中。

push指令的语法如下所示:

PUSH{cond} reglist

pop指令的语法如下所示:

POP{cond} reglist

cond:条件码。

reglist:用{}括起来的一个寄存器或者多个寄存器组成的列表。它可以是一个寄存器范围。如果{}中的寄存器超过一个,那么寄存器或者寄存器范围之间通过逗号(,)分隔。

push指令等价于STMDB指令。pop指令等价于LDMIA指令。

使用push指令和pop指令保护现场的例子如下所示:

# 将R0-R7和LR入栈
push {R0-R7, LR}

# 功能代码
MOV R0, #0x00
MOV R1, #0x11
MOV R2, #0x22

# 将R0-R7和LR出栈
pop {R0-R7, LR}

MOV指令

MOV指令主要用于将数据搬移到寄存器中。MOV指令的语法如下所示:

MOV{S}{cond} Rn, Rm
MOV{cond} Rn, #imm

S:可选的后缀,如果指令中添加了S,那么指令的执行结果将会影响到CPSR寄存器的标志位域。

cond:条件码。

Rn:目标寄存器。

Rm:源寄存器。

imm:立即数。

MOV指令的使用例子如下:

# 将 R1 寄存器中的内容搬移到 R0 寄存器
MOV R0, R1

# 将 0xaa 搬移到 R0 寄存器
MOV R0, #0xaa

CPS指令

可以通过CPS(Change Processor State)指令来修改处理器模式。CPS指令也可以用来使能或者禁止异常。

CPS指令的语法如下所示:

CPS #mode
CPSIE iflags{, #mode}
CPSID iflags{, #mode}

mode是处理器的模式编码,比如在从其他模式下切换到SYS模式,使用下述代码即可:

# 切换到SYS模式
CPS #0x1f

IE使能中断或者终止。

ID禁止中断或者终止。

iflags由下面的一种或者几种组成:

  • a:表示异步终止(asynchronous abort);
  • i:表示中断(IRQ);
  • f:表示快中断(FIQ);

下述代码是CPS指令的一些简单用法:

# 使能中断
CPSIE I

# 禁止中断
CPSID I

# 使能异步终止和快中断
CPSIE AF

# 禁止异步终止和快中断
CPSID AF

# 使能中断并切换到SYS模式
CPSIE I, #0x1f

MRS与MSR指令

MRSMSR指令可用于读写程序状态寄存器CPSR,APSR和SPSR。

在ARM处理器中,只有MRS指令可以从程序状态寄存器CPSR,APSR和SPSR中读出数据到通用寄存器中。MRS指令操作程序状态寄存器的语法如下:

MRS{cond} Rd, psr

cond为条件码。

Rd为目标寄存器,Rd不允许为R15。

psr为程序状态寄存器CPSR,APSR或者SPSR。

MRS指令的示例代码如下所示:

# 将CPSR寄存器的值读取到R0中
MRS R0, CPSR

# 将SPSR寄存器的值读取到R1中
MRS R1, SPSR

# 将APSR寄存器的值读取到R2中
MRS R2, APSR

MSR指令可以用来写程序状态寄存器CPSR,APSR和SPSR的全部或者部分域。MSR指令操作程序状态寄存器的语法如下:

MSR{cond} psr, #constant
MSR{cond} psr, Rm
MSR{cond} psr_fields, #constant
MSR{cond} psr_fields, Rm

cond为条件码。

psr为程序状态寄存器CPSR或者SPSR。

constant是一个8位立即数。ARM文档对于constant的介绍如下:

constant is an 8-bit pattern rotated by an even number of bits within a 32-bit word. (Not available in Thumb.)

Rm是源寄存器。

fields由下面的一个或者多个组合而成:

  • c:xPSR[7:0],控制位域;
  • x:xPSR[15:8],扩展位域;
  • s:xPSR[23:16],状态位域;
  • f:xPSR[31:24],标志位域;

MSR指令的示例代码如下所示:

# 切换到SYS模式
MRS R0, CPSR
ORR R0, R0, #0x1f
MSR CPSR, R0

# 切换到SYS模式
MSR CPSR_c, #0xDF

只有在除用户模式外的其他模式下才能够修改状态寄存器

MRC和MCR指令

ARMv7-A体系结构的处理器提供了MRCMCR指令用于对协处理器进行读写操作。MRC指令用于将协处理器中的寄存器数据读取到ARM通用寄存器中。MCR指令用于将ARM通用寄存器中的数据写入到协处理器的寄存器中。

MRC

MRC指令的语法如下所示:

MRC{cond} coproc, opc1, Rt, CRn, CRm{, opc2}

cond为条件码。

coproc为协处理器名称,CP0CP15协处理器分别对应名称p0p15。

opc1为协处理器要执行的操作码,取指范围为0~7。

Rt为ARM通用寄存器,用于存储读取到的协处理器寄存器数据。

CRn为协处理器寄存器,对于CP15协处理器来说,CRn取值范围为c0~c15。

CRm为协处理器寄存器,对于CP15协处理器来说,通过CRmopc2一起来确定CRn对应的具体寄存器。

opc2为可选的协处理器执行操作码,取指范围为0~7,当不需要的时候要设置为0。

MRC指令使用示例如下:

# 读取主ID寄存器 MIDR 的数据到 R0 中.
MRC p15, 0, R0, c0, c0, 0

MCR

MCR指令的语法如下所示:

MCR{cond} coproc, opc1, Rt, CRn, CRm{, opc2}

cond为条件码。

coproc为协处理器名称,CP0CP15协处理器分别对应名称p0p15。

opc1为协处理器要执行的操作码,取指范围为0~7。

Rt为ARM通用寄存器,用于存储要写入到协处理器寄存器中的数据。

CRn为协处理器寄存器,对于CP15协处理器来说,CRn取值范围为c0~c15。

CRm为协处理器寄存器,对于CP15协处理器来说,通过CRmopc2一起来确定CRn对应的具体寄存器。

opc2为可选的协处理器执行操作码,取指范围为0~7,当不需要的时候要设置为0。

MCR指令使用示例如下:

# 将 R0 中的配置数据写入到 SCTLR
MCR p15, 0, R0, c1, c0, 0

欢迎关注博主的公众号(微信搜索公众号:嵌入式那些事),可以扫描下面的公众号二维码:

在这里插入图片描述
如果文中有什么问题欢迎指正,毕竟博主的水平有限。

如果这篇文章对你有帮助,记得点赞和关注博主就行了^_^。

排版更好的内容见我博客的地址:http://www.only2fire.com/archives/158.html

注:转载请注明出处,谢谢!^_^

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1066581.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【二叉树练习题】

欢迎来到我的&#xff1a;世界 希望作者的文章对你有所帮助&#xff0c;有不足的地方还请指正&#xff0c;大家一起学习交流 ! 目录 前言初阶题二叉树的节点个数二叉树的叶子节点个数二叉树第k层节点个数二叉树查找值为x的节点 进阶题完全二叉树的节点个数翻转二叉树检验两个树…

修炼k8s+flink+hdfs+dlink(一:安装dlink)

一&#xff1a;mysql初始化。 mysql -uroot -p123456 create database dinky; grant all privileges on dinky.* to dinky% identified by dinky with grant option; flush privileges;二&#xff1a;上传dinky。 上传至目录/opt/app/dlink tar -zxvf dlink-release-0.7.4.t…

医学访问学者面试技巧

医学访问学者面试是一个非常重要的环节&#xff0c;它决定了你是否能够获得这个宝贵的机会去国外的大学或研究机构学习和研究。在这篇文章中&#xff0c;知识人网小编将分享一些关于医学访问学者面试的技巧&#xff0c;帮助你在面试中表现出色。 1. 准备充分 在参加医学访问学…

Multisim:JFET混频器设计(含完整程序)

目录 前言实验内容一、先看作业题目要求二、作业正文IntroductionPre-lab work3.13.2 Experiment Work4.1(2)circuit setup4.1(3)add 12V DC4.1(4)set input x1 and x24.1(5)4.1(6)4.1(7)4.2(1)(2)4.2(3)4.2(4)4.3(1)(2)4.3(3) Conclusion 三、资源包内容 前言 花了好大心血完成…

【线性代数及其应用 —— 第一章 线性代数中的线性方程组】-1.线性方程组

所有笔记请看&#xff1a; 博客学习目录_Howe_xixi的博客-CSDN博客https://blog.csdn.net/weixin_44362628/article/details/126020573?spm1001.2014.3001.5502思维导图如下&#xff1a; 内容笔记如下&#xff1a;

中国高清行政、地形、旅游、人文地图全集(地理干货,覆盖34个省市自治区)

中国高清行政、地形、旅游、人文地图全集&#xff08;地理干货&#xff0c;覆盖34个省市自治区&#xff09;&#xff1a; 中国的高原、平原、盆地和丘陵 四大高原&#xff1a;青藏高原位于中国西南部&#xff0c;平均海拔在4000米以上&#xff0c;是中国最大、世界最高的大高原…

安卓手机如何下载谷歌应用商店(play.google.com)里的app,无需下载google play

不需要梯子&#xff01; 不需要下载google play&#xff01; 不需要考虑机型&#xff01; 1、首先使用电脑打开网站 https://apps.evozi.com/ 点击 apk downloader 进入一个新的界面 2、电脑打开谷歌商店 https://play.google.com/store/apps 搜索任意软件&#xff0c;比如 …

300元开放式耳机推荐哪款好用一点、最便宜的开放式耳机

对于音乐爱好者来说&#xff0c;一款出色的耳机是必不可少的&#xff0c;开放式耳机以其独特的音场表现和舒适的佩戴感受&#xff0c;成为许多人钟爱的选择。如果你正在寻找一个300元价位好用的开放式耳机&#xff0c;今天就给大家推荐几款&#xff0c;希望能帮助到你~ 1、西圣…

python入门篇07-数据容器(序列 集合 字典,json初识)基础(下)

全文目录,一步到位 1.前言简介1.1 专栏传送门1.1.1 上文传送门 2. python基础使用2.1 序列2.1.1 序列定义2.1.2 序列参数解释2.1.3 列表list切片2.1.4 元组tuple切片2.1.5 字符串str切片 2.2 集合定义2.2.1 set集合-基本语法2.2.2 set集合-添加元素.add()2.2.3 set集合- 移除元…

bochs 对 Linux0.11 进行调试 (TODO: 后面可以考虑集成 vscode+gdb+qemu)

我在阅读 Linux0.11 源码时&#xff0c;对一个指令 LDS 感到困惑。 看了下 intel 指令集手册&#xff0c;能猜到 LDS 的功能&#xff0c;但不确定。 于是决定搭建调试环境&#xff0c;看看 LDS 的功能是否真如自己猜测。 首先 make debug 运行 qemu-Linux0.11&#xff0c;命…

死磕CMS垃圾回收器

为什么会有这篇文章&#xff1f; **校招垃圾回收面试重灾区。**本人秋招面试过大大小小的公司&#xff0c;发现几乎所有公司在面试的时候&#xff0c;一旦涉及到JVM只是&#xff0c;CMS和G1是常问点&#xff0c;而且CMS问的尤其多。所以本文会对根据网上常见的资料做一个整合并…

Qt扫盲-QTreeView 理论总结

QTreeView 理论使用总结 一、概述二、快捷键绑定三、提高性能四、简单实例1. 设计与概念2. TreeItem类定义3. TreeItem类的实现4. TreeModel类定义5. TreeModel类实现6. 在模型中设置数据 一、概述 QTreeView实现了 model 中item的树形表示。这个类用于提供标准的层次列表&…

Python3.x安装Pandas教程

python3.x 安装pandas总是会出现一些乱七八糟的问题&#xff0c;那现在就给你们讲述一种超级简单的安装方法&#xff0c;非常简单。 1&#xff0c;检查自己的python版本&#xff0c;我的是python3.4 32位的 2&#xff0c;https://www.lfd.uci.edu/~gohlke/pythonlibs/ 进入此网…

IIS部署Flask

启用 CGI 安装wfastcgi pip install wfastcgi 启用 wfastcgi 首先以管理员身份运行wfastcgi-enable来在IIS上启用wfastcgi&#xff0c;这个命令位于c:\python_dir\scripts&#xff0c;也就是你需要确保此目录在系统的PATH里&#xff0c;或者你需要cd到这个目录后再执行。 #…

np.clip()函数用法

代码&#xff1a; import numpy as npdelta np.clip(1.2, a_min0, a_max1)print(delta) 结果&#xff1a;

防御安全第五次作业

1. 什么是数据认证&#xff0c;有什么作用&#xff0c;有哪些实现的技术手段&#xff1f; 数据认证是指保证数据的真实性、完整性和可信度&#xff0c;以确保数据不被篡改或伪造。其作用包括但不限于&#xff1a; 保护关键数据不被恶意篡改或损坏 提供数据来源的可靠性和安全性…

ToBeWritten之记录狩猎过程

也许每个人出生的时候都以为这世界都是为他一个人而存在的&#xff0c;当他发现自己错的时候&#xff0c;他便开始长大 少走了弯路&#xff0c;也就错过了风景&#xff0c;无论如何&#xff0c;感谢经历 转移发布平台通知&#xff1a;将不再在CSDN博客发布新文章&#xff0c;敬…

nodeJs 图片下载功能实现

const cheerio require("cheerio"); const axios require("axios"); const fs require("fs"); const request require("request"); const path require(path); // 图片存储位置 const fileImgUrl "./images/"; // 获取…

外部中断的基本操作

题目背景 定义一个 Working() 函数&#xff0c;使L1指示灯不断闪烁。将P32引脚定义成外部中断功能&#xff0c;按下S5按键就会产生外部中断触发信号&#xff0c;在中断响应函数中&#xff0c;点亮L8指示灯&#xff0c;延时较长一段时间后熄灭&#xff0c;该功能用两种方法实现…

ToBeWritten之评估数据质量

也许每个人出生的时候都以为这世界都是为他一个人而存在的&#xff0c;当他发现自己错的时候&#xff0c;他便开始长大 少走了弯路&#xff0c;也就错过了风景&#xff0c;无论如何&#xff0c;感谢经历 转移发布平台通知&#xff1a;将不再在CSDN博客发布新文章&#xff0c;敬…