嵌入式学习——硬件(ARM内核汇编指令)——day52

news2024/11/18 1:26:00

ARM汇编指令

学习arm汇编的主要目的是为了编写arm启动代码,启动代码启动以后,引导程序到c语言环境下运行。换句话说启动代码的目的是为了在处理器复位以后搭建c语言最基本的需求。因此启动代码的主要任务有:

  1. 初始化异常向量表;
  2. 初始化各工作模式的栈指针寄存器;
  3. 开启arm内核中断允许;
  4. 将工作模式设置为user模式;
  5. 完成上述工作后,引导程序进入c语言主函数执行;

因此汇编指令的学习主要是围绕这几个目的展开,主要学习跟上述目的相关的指令。

  1. mov指令:加载12位立即数到寄存器或转移一个寄存器的值到另外一个寄存器

mov r0, #2 ;加载立即数2到寄存器r0,MOV{S}<c> <Rd>, #<const>

mov r1, r0 ;将r0寄存器的值加载到r1,MOV{S}<c> <Rd>, <Rm>

    1. 大多数指令的格式为opcode rd, rn ,rm,其中,rd是目标寄存器,rn是第一操作数寄存器。同理:
  1. add指令常用的两种方式

ADD{S}<c> <Rd>, <Rn>, #<const>

ADDS}<c> <Rd>, <Rn>, <Rm>{, <shift>}

类似的还有

  1. sub指令

SUB{S}<c> <Rd>, <Rn>, #<const>

SUB{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}

以上四条指令都有立即数作为第二操作数的情况,那么是什么立即数呢?准确的说这里所指的是12位立即数imm12。先说怎么判断某数是不是12位立即数,12位立即数的条件是:

  1. 如果某个数的数值范围是0~255之间,那么这个数一定是立即数;
  2. 把某个数展开成2进制,这个数的最高位1至最低位1之间的二进制数序列的位数不能超过8位;
  3. 这个数的二进制序列的右边必须为偶数个连续的 0

例如:0x234 = 0000 0000 0000 0000 0000 0010 0011 0100

最高位1至最低位1之间的二进制数序列:1000 1101没有超过8位

末尾1的右边有2个0,所以0x234是立即数

0x3f4 = 0000 0000 0000 0000 0000 0011 1111 0100

最高位1至最低位1之间的二进制数序列:1111 1101 从第一个1开始到最后一个1之间没有超过8位

末尾1的右边有2个0,所以0x3f4是立即数

0x132 = 0000 0000 0000 0000 0000 0001 0011 0010

最高位1至最低位1之间的二进制数序列:1001 1001 从第一个1开始到最后一个1之间没有超过8位

末尾1的右边有1个0,不满足第二条,所以0x132不是立即数

0x7f8 = 0000 0000 0000 0000 0000 0111 1111 1000

最高位1至最低位1之间的二进制数序列:1111 1111从第一个1开始到最后一个1之间没有超过8位

末尾1的右边有3个0,不满足第二条,所以0x7f8不是立即数

0xfab4 = 0000 0000 0000 0000 1111 1010 1011 0100

最高位1至最低位1之间的二进制数序列:0011 1110 1010 1101 从第一个1开始到最后一个1之间超过8位,不满足条件1,所以这个数不是立即数

这是因为ARM中将这 12bits 分为 8bit 常数(0~255)和 4bit 循环右移位值(0~15)

8bit 常数范围(0~255),位移的步进值是以2为单位(即实际位移 2 * rotate 位),可以表示循环有以(0~30)偶数位: 0、2、4、6、8、10、12、14、16、18、20、22、24、26、28、30。在实际存储这个数值的时候,要想办法把这个数压缩到这12位中去。压缩的方法就是找一个数,这个数必须是一个8bit数,之后循环右移2 * rotate位。如果能找打这个数,那么待保存的数就是立即数,否则就不是。

那么如果我们就是希望把一个非立即数存进rn,又该怎么做呢?

  1. ldr寄存器加载指令:

LDR{<c>}{<q>} <Rt>, <label> ;如ldr r0, =0x2FAB4

ldr指令多用于从ram中将一个32位的字数据传送到目的寄存器中

LDR<c> <Rt>, [<Rn>{, #+/-<imm12>}] 如:

LDR   R0,[R1,#8]             ;将内存地址为R1+8的字数据读入寄存器R0,这里的#8作为12位立即数是可以省略的

LDR<c> <Rt>, [<Rn>], #+/-<imm12> 如:

ldr r0, [r1], #8 ;将内存地址R1的字数据读入r0,之后r1+8

LDR<c> <Rt>, [<Rn>, #+/-<imm12>]! 如:

LDR   R0,[R1,#8] !          ;将存储器地址为R1+8的字数据读入寄存器R0,并将新地址R1+8写入R1。

  1. bic指定位清零指令:

BIC{S}<c> <Rd>, <Rn>, #<const>;将rn中的字数据const为1的比特清零,把结果放入rd

  1. orr指定位置位(置1)指令:

ORR{S}<c> <Rd>, <Rn>, #<const>

  1. 汇编指令的s后缀,几乎所有的汇编指令都可以在指令后面加上s后缀,s后缀的含义是在指令执行过程中会更新cpsr寄存器的N,V,C,Z位

N:在结果是有符号的二进制补码情况下,如果结果为负数,则N=1;如果结果为非负数,则N=0

Z:如果结果为0,则Z=1;如果结果为非零,否则Z=0

C(无符号溢出):是针对无符号数最高有效位向更高位进位时C=1;减法中运算结果的最高有效位从更高位借位时C=0

V(有符号溢出):该位是针对有符号数的操作,会在下面两种情形变为1,两个最高有效位均为0的数相加,得到的结果最高有效位为1;两个最高有效位均为1的数相加,得到的结果最高有效位为0;除了这两种情况以外V位为0

       例如:

              mov r0, #0xFFFFFFFF

              adds r1, r0, #1

              上面的操作会导致Z,C置位,这是因为结果为0,并且从无符号数角度来看,已经从最高位向更高位进位了

              而

              mov r0. #0x7FFFFFFF

              adds r1, r0, #1

              会造成N位和C位置位,这是因为计算结果0x80000000最为位为1,代表负数,并且 从有符号角度来看,把一个整数加成了负数。

  1. 更新N,V,C,Z位有什么用呢?几乎所有的arm指令都可以在指令之后可选地增加执行条件

例如:movcs r0, #100;表示只有在C位置位的情况下才能把100加载入r0,这样的话就可以非常方便地实现指令的有条件执行。

例如:实现两个unsigned long long类型变量的求和,

unsigned long long l1 = 0x00000000FFFFFFFF;

unsigned long long l2 = 0x000000000000003;

很明显结果为0x0000000100000002

我们用r0装l1的高4字节,r1装l1的低四字节:

用r2装l2的高4字节,r3装l2的低四字节

用r4装结果的高4字节,r5装结果的低四字节

第6~7行:装入被加数

第8~9行:装入加数

第10~11行:清空装结果的变量

第12行:先加低四字节,这里因为考虑到进位问题,所以要更新N,V,C,Z位

第13行:之前的进位导致更高位数据的丢失,必须把这一位补回来,要不要补就看之前时候进位,进位标志是cs

练习:从r0, r1代表的两个有符号数中找到较大值放入r2寄存器

  1. CMP比较指令用于比较两个寄存器的值或者比较一个寄存器和立即数的值,其原理是对待比较的两个数求差,看结果是否为0,这个指令会无条件修改N,V,C,Z位。

如:

mov r0, #100

cmp r0, #100

会导致Z置位,从条件码表可知,只要Z置位就是两数相等。

  1. 跳转指令b

b指令类似c语言的goto语句,能够实现无条件跳转。跳转时需要一个lable,表示要跳转到什么地方去

配合之前的条件码,就可以实现一些较为复杂的操作,例如实现从0加到100的和

这就是循环实现的机制

  1. 事实上,程序跳转工作更多的是为了实现类似函数的功能,此时lable就是函数的函数名,其实lable本身代表的就是待跳转那一行指令的地址,b指令本质上就是把待跳转那行的地址装入pc寄存器,但是函数在调用完毕之后要回到调用处的下一行指令处执行,为了能够回到调用的下一行,需要使用bl指令。bl和b之间的区别就在于bl会在lr寄存器中保存回来的地址。如:

以上代码虽然实现了函数调用的程序流程,但是还存在两个问题:一是调用完毕以后r0, r1寄存器的值被max_of_two_numbers函数修改了,二是如果出现了函数的嵌套调用,那么lr寄存器的值就会被修改,而无法回到最开始的地方。要解决这个问题,就必须在每次函数调用前保护现场,在函数调用完毕以后恢复现场。而实现这个功能就需要使用栈这个数据结构。

  1. 栈的实现类型:

2440实现保护和恢复现场使用的栈是数组栈,即用一段连续的内存空间为栈提供空间。从数组栈的具体实现来看入栈的方式有四种做法:

  1. 空增:先写入数据,再让栈指针自增;
  2. 空减:先写入数据,再让栈指针自减;
  3. 满增:先让栈指针自增,再写入数据;
  4. 满减:先让栈指针自减,再写入数据。

arm体系采用的方案是满减,但是在进行操作之前,我们必须告诉2440栈底的位置,这里我们把栈底设置为0x40001000,从地址0x40000000开始的0x1000这段内存空间对应的是2440内部的一段ram,总共4k。实际能够使用的内存空间为[0x40000000~0x40000FFF],设置栈底指针寄存器: ldr sp =0x40001000

  1. 入栈保护指令stmfd(STMDB)

STMFD<c> <Rn>{!}, <registers>

其中Rn表示栈底指针寄存器,< registers >表示需要入栈保护的寄存器,!表示入栈之后sp自动自减。如:

stmfd sp!, {r0, r1, r2, r3-r12, lr}

  1. 出栈恢复指令ldmfd(LDM/LDMIA/)

LDMFD<c> <Rn>{!}, <registers>

中Rn表示栈底指针寄存器,< registers >表示需要入栈保护的寄存器,!表示出栈之后sp自动自增。如:

ldmfd sp!, {r0, r1, r2, r3-r12, lr}

  1. 在汇编中调用c语言编写的函数

设有c语言定义的函数void func_c(void);在汇编代码中调用该函数,只需用import声明函数名即可,之后就可以使用bl指令调用该函数,注意,既然是调函数,就一定要保护现场

  1. 向c函数传参

向c函数传参的方法很简单,如果参数个数小于等于4个,就直接用r0~r3传参,c函数返回值通过r0寄存器返回:

设有c函数:

int add_c(int a, int b, int c, int d)

{

return a + b + c + d;

}

如果参数个数大于4个,从第五个参数开始就需要通过栈来传参

  1. 在c语言中调用汇编编写的函数类似,不过在汇编中用export声明函数,同时需要在c语言中用extern声明函数,按照标准,调用者负责保护现场和恢复现场

传参方法于此类似

  1. 切换arm内核的工作模式

切换工作方式的思路很简单,由于内核的工作模式是由cpsr寄存器的低5位来设置的,那么就可以先把cpsr读出来,更改低5位之后再设置进去。这里读取cpsr使用mrs指令,写cpsr寄存器用msr指令,需要注意的是在keil环境下写cpsr需要写成:   msr cpsr_c r0;将r0的值写入到cpsr寄存器

学习了这些指令,最终就可以编写我们自己的启动代码了

       preserve8

       area reset, code, readonly

       code32

       entry

       b start

       nop

       nop

       nop

       nop

       nop

       b do_interrput

       nop

start

       ldr sp, =0x40001000

       mrs r0, cpsr

       bic r0, r0, #0x1F

       orr r0, r0, #0x12

       bic r0, r0, #(0x01 << 7)

       msr cpsr_c, r0

       ldr sp, =0x40001000

       sub sp, sp, #1024

       mrs r0, cpsr

       bic r0, r0, #0x1F

       orr r0, r0, #0x10

       msr cpsr_c, r0

       ldr sp, =0x40001000

       sub sp, sp, #2048

       import main

       b main

do_interrput

       sub lr, lr, #4

       stmfd sp!, {r0-r12, lr}

       import interrupt_handle

       bl interrupt_handle

       ldmfd sp!, {r0-r12, pc}^

       end

代码

1. start.s

	preserve8
	area reset, code, readonly
	code32
	entry

	;ldr r0, =0x40000fff;装立即数

	
;	mov r0, #0xffffffff
;	bic r0, r0, #1;将最后一位清零
;	bic r0, r0, #(1 << 5);将第5位清零
;	bic r0, r0, #(1 << 7);将第7位清零


;	mov r0, #0x0			
;	orr r0, r0, #1;将最后一位置1
;	orr r0, r0, #(1 << 5);将第5位置1
;	orr r0, r0, #(1 << 7);将第7位置1


;	mov r0, #10	;两个数比较大小
;	mov r1, #20
;	cmp r0, r1
;	movge r2, r0 ;大的给r2
;	movle r2, r1 ;小的给r2


;	mov r0, #10	;三个数比较大小
;	mov r1, #20
;	mov r2, #30	

;	cmp r0, r1
;	movge r3, r0
;	movle r3, r1

;	cmp r3, r2
;	movle r3, r2	


;	mov r0, #1;对无符号longlong进行相加操作判断溢出
;	mov r1, #0
;	mov r2, #0xffffffff
;	mov r3, #0
;
;	adds r4, r0, r2
;	mov r5, #0
;	addcs r5, #1;cs为判断低四字节是否溢出


;	mov r0, #1;实现b
;	mov r1, #0
;	b foo
;	mov r2, #0xffffffff
;	mov r3, #0
;foo
;	adds r4, r0, r2	  ;add后加s,影响CPSR寄存器中的NZCV位,之后指令可加不同的条件分支
;	mov r5, #0
;	addcs r5, #1;cs为判断低四字节是否溢出	

;	mov r0, #0x10;两个数字比大小
;	mov r1, #0x20
;	cmp r0, r1
;	bge great
;	ble less
 ;
;great
;	mov r2, r0
;	b finished
;less
;	mov r2, r1


;	mov r0, #0x10	;判断三个数的最大值
;	mov r1, #0x20
;	mov r2, #0x30
 ;
;	cmp r0, r1
;	bge tmpgreat
;	ble tmpless
;tmpgreat
;	mov r3, r0
;	b continue
;tmpless
;	mov r3, r1

;continue
;	cmp r3, r2
;	bge finished
;	mov r3, r2

;	mov r0, #0	;1到100求和
;	mov r1, #0
 ;
;loop
;	cmp r1, #100
;	bgt finished
;	add r0, r0, r1
;	add r1, #1
;	b loop

;	ldr sp, =0x40001000;初始化满减栈
;	mov r0, #0	 
;	mov r1, #0
;	stmfd sp!, {r0-r12};保存现场,入栈保护,防止数据被修改
;	bl foo	;bl会在b指令跳转时,将下一行要执行指令的地址放入lr
;	ldmfd sp!, {r0-r12}; 恢复现场,出栈
 ;
;loop
;	cmp r1, #100
;	bgt finished
;	add r0, r0, r1
;	add r1, #1
;	b loop
;
;foo
;	mov r0, #1
;	mov r1, #2
;	add r2, r0, r1
;	bx lr  ;(跳转回原函数)mov pc, lr



;	ldr sp, =0x40001000	 ;入栈保护,嵌套调用汇编函数
;	mov r0, #1
;	mov r1, #2
;	stmfd sp!, {r0-r12, lr}
;	bl max_of_two_numbers
;	ldmfd sp!, {r0-r12, lr}
 ;
;foo
;	mov r0, #1
;	mov r1, #2
;	add r2, r0, r1
;	bx lr  ;(跳转回原函数)mov pc, lr
 ;
;max_of_two_numbers
 ;	mov r0, #3
;	mov r1, #4
;	stmfd sp!, {r0-r12, lr};不加lr,第二次lr会将第一次lr的值覆盖
;	bl foo
;	ldmfd sp!, {r0-r12, lr}
;	cmp r0, r1
;	movge r2, r0
;	movle r2, r1
;	bx lr

;	mov r0, #1
;	mov r1, #2
;	mov r2, #3
;	stmfd sp!, {r0-r12, lr}	;汇编start.s调用main.c中的c语言函数,传参利用r0、r1、r2、r3传参 
;	import add_c			 ;汇编调c中函数用import声明c中的函数,c中调汇编函数在汇编中用export声明汇编的函数
;	bl add_c
;	ldmfd sp!, {r0-r12, lr} 


;	mov r0, #1	 ;编写函数实现求三个数中的最大值
;	mov r1, #2					  ;汇编给c中函数传参用r0-r3,其他的通过入栈出栈传参,返回值r0
;	mov r2, #3
;	stmfd sp!, {r0-r12, lr}	;汇编start.s调用main.c中的c语言函数,传参利用r0、r1、r2、r3传参 
;	import max_of_three_numbers	   ;调用函数时要入栈保护,保护现场恢复现场
;	bl max_of_three_numbers
;	ldmfd sp!, {r0-r12, lr} 


;	mov r0, #1	 ;编写函数实现传参五个数进入main.c
;	mov r1, #2
;	mov r2, #3
;	mov r3, #4
;	mov r4, #5
 ;
;	stmfd sp!, {r0-r12, lr}	;汇编start.s调用main.c中的c语言函数,传参利用r0、r1、r2、r3传参 
;	import access_five_numbers	  ;汇编调c语言函数用import
;	stmfd sp!, {r4}
;	bl access_five_numbers
;	ldmfd sp!, {r4}
;	ldmfd sp!, {r0-r12, lr} 


;	ldr sp, =0x40001000;初始化满减栈
;	import main
;	export foo
;	b main
 ;
;foo
;	add r0, r0, r1
;	bx lr  ;(跳转回原函数)mov pc, lr



;	ldr sp, =0x40001000
;	import main
;	export sum_c
;	b main
 ;
;sum_c
;	mov r2, r0	;1到100求和
;	mov r1, #0
;	mov r0, #0
 ;
;loop
;	cmp r1, r2
;	bxgt lr
;	add r0, r0, r1
;	add r1, #1
;	b loop

	ldr pc, =start
	ldr pc, =undifine_handler
	ldr pc, =swi_handler
	ldr pc, =prefetch_handler
	ldr pc, =abort_handler
	nop
	ldr pc, =IRQ_handler	 
	ldr pc, =FIQ_handler


undifine_handler
	b undifine_handler

swi_handler
	import swi_function
	stmfd sp!, {r0-r12, lr}
	ldr r0, [lr, #-4] ;取到swi中的值,当执行到swi这一行时, pc指向swi的下一行,lr放着swi下一行高四个字节的地址
	bic r0, r0, #0xff000000	;取swi中的0x80给到swi——function函数进行传参
	bl swi_function
	ldmfd sp!, {r0-r12, pc}^   ;^将spsr恢复到cpsr
	;ldmfd sp!, {r0-r12, lr}
	;bx lr
						 
prefetch_handler
	b prefetch_handler

abort_handler
	b abort_handler

IRQ_handler
	b IRQ_handler

FIQ_handler
	b FIQ_handler



start
	ldr sp, =0x40001000;初始化满减栈
	mrs r0, cpsr							;模式切换msr读取cpsr
	bic r0, r0, #0x1f;所有低五位清零
	orr r0, r0, #0x12;置位成IRQ模式10010
	msr cpsr_c, r0;转换模式为usr			;写cpsr,设置cpsr,写入m域

	ldr r0, =0x40001000;初始化满减栈
	sub r0, r0, #1024
	mov sp, r0

	mrs r0, cpsr
	bic r0, r0, #0x1f;所有低五位清零
	orr r0, r0, #0x10;置位成usr模式10000
	msr cpsr_c, r0;转换模式为usr

	ldr r0, =0x40001000
	sub r0, r0, #2048
	mov sp, r0

	swi #0x80
	import main
	b main


finished
	b finished;类似于while(1)

	end

2. main.c

//extern int add_c(int a, int b, int c);
//extern int max_of_three_numbers(int a, int b, int c);
//extern int access_five_numbers(int a, int b, int c, int d, int e);
//extern int foo(int a, int b);
//extern int sum_c(int a);
//int add_c(int a, int b, int c)
//{
//	return a + b + c;
//}
//
//int max_of_three_numbers(int a, int b, int c)
//{
//	int max = a;
//	max = a > b ? a : b;
//	max = max > c ? max : c;
//
//	return max;
//}
//
//int access_five_numbers(int a, int b, int c, int d, int e)
//{
//	return a + b + c + d + e;
//}
extern void swi_function(int n);

void swi_function(int n)
{
	while (n--)
	{
		
	}
	
}

int main(void)
{
//	int ret = foo(10, 20);
//	int sum = sum_c(100);
	while (1)
	{
		
	}
	
}


1. add(s)<c>

s : 影响CPSR寄存器中的NZCV位,之后指令可加不同的条件分支

c : 

movge >= 

movgt>

b

bl : 保存下一条指令的地址

bx

arm满减栈

函数调用者实现出栈入栈

传参:两种方法一样

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

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

相关文章

强大的资源提取工具

一、简介 1、是一款功能强大的文件提取工具&#xff0c;它可以从多种不同类型的存档文件或安装程序中提取文件&#xff0c;包括但不限于ZIP、RAR、7z、ISO等格式。这款软件的独特之处在于它不仅能够处理常规的压缩文件&#xff0c;还能处理各种软件安装程序&#xff0c;甚至是加…

TMGM外汇平台: 纽元未来走势,新西兰即将降息

2024年6月26日&#xff0c;全球金融市场对新西兰联储即将采取的货币政策持续关注。分析师普遍预估新西兰将实施降息政策&#xff0c;这一政策调整预计将对新西兰元&#xff08;纽元&#xff09;的国际交易价值产生重大影响。本文将TMGM深入探讨新西兰经济的当前状况&#xff0c…

java:spring-security的简单例子

【pom.xml】 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.3.12.RELEASE</version> </dependency> <dependency><groupId>org.springf…

java使用Graphics2D生成图片

UI图 实际图片数据库中只存了一个二维码转的base64的数组,直接导出只有一个二维码 这里使用 Graphics2D 画图 public static void main(String[] args) {// 假设你有一个Base64编码的字符串&#xff0c;它表示一张图片String base64ImageString "/9j/4AAQSkZJRgABAgAAA…

考研数学(4/9):微分方程

微分方程 微分方程是高等数学中一个重要的分支&#xff0c;也是考研数学数一中必考的内容。本章主要介绍微分方程的概念、一阶微分方程、高阶线性微分方程以及微分方程的应用。 1. 微分方程的概念 1.1 微分方程的定义 微分方程 是指包含未知函数及其导数的方程。 更准确地说&am…

【数学建模】——【python库】——【Pandas学习】

专栏&#xff1a;数学建模学习笔记 pycharm专业版免费激活教程见资源&#xff0c;私信我给你发 python相关库的安装&#xff1a;pandas,numpy,matplotlib&#xff0c;statsmodels 总篇&#xff1a;【数学建模】—【新手小白到国奖选手】—【学习路线】 第一卷&#xff1a;【数学…

老板电器 45 年的烹饪经验,浓缩在这款烹饪大模型中

在科技不断进步的时代&#xff0c;人工智能&#xff08;AI&#xff09;迅速成为推动各行各业发展的重要力量。家电行业也不例外&#xff0c;根据 Gartner 的报告预测&#xff0c;到 2024 年&#xff0c;AI 家电市场的规模将达到万亿美元级别。这一预估凸显了智能化在家电行业中…

大猫咪守护LoRA:定制你的大猫私人大猫咪宠物写真合影,某音某书流行款

&#x1f339;大家好&#xff01;我是安琪&#xff01;感谢大家的支持与鼓励。 大猫咪LoRA模型简介 今天应群里同学大猫咪宠物合影写真提议&#xff0c;为大家介绍一款来自作者 沐沐人像合成的主题为大猫咪守护的LoRAl模型&#xff1a;沐沐-大猫咪。这是一款当下在某音、某书…

python-docx 使用xml为docx不同的章节段落设置不同字体

本文目录 前言一、完整代码二、代码详细解析1、处理过程解释(1) 引入库并定义路径(2) 创建docx的备份文件(3) 定义命名空间(4) 打开并处理.docx文件(5) 分析和组织文档结构(6) 设置字体(7) 保存结果前言 本文主要解决的内容,就是为一个docx的不同章节段落设置不同的字体,因为…

【Week-G1】调用官方GAN实现MNIST数字识别,Pytorch框架

文章目录 1. 准备数据1.1 配置超参数1.2 下载数据1.3 配置数据 2. 创建模型2.1 定义鉴别器2.2 定义生成器 3. 训练模型3.1 创建实例3.2 开始训练3.3 保存模型 4. 什么是GAN&#xff08;对抗生成网络&#xff09;? &#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学…

追求准确,还是追求举一反三,聊天机器人智能程度的困境 | Chatopera

在为企业客户上线聊天机器人客服的过程中&#xff0c;总会遇到一个问题&#xff0c;这让用户和我们都感到纠结。 到底是追求让机器人能准确的回答问题&#xff0c;还是让机器人可以举一反三的回答问题。 准确的回答问题&#xff0c;就是不容许回答错了&#xff0c;但是这样机…

windows中使用anaconda管理python版本

anaconda下载 python的版本问题实在是很大,版本低了高了都会影响脚本的执行,anaconda工具为此而生,不管是在windows下还是linux下,Anaconda的命令跟操作逻辑都是相同的,窥一斑而知全豹,本文在windows下示例如何使用anaconda anaconda的逻辑就是 他是一个全局的管理者,能创建工…

在Ubuntu中使用ROS搭建PX4 Gazebo 模拟飞行 四旋翼 固定翼

综合了网上很多教程以及踩了很多坑总结下来的教程 Ubuntu安装 此处不在详细说明&#xff0c;网上可随处搜到 ROS安装 感谢鱼香ROS大佬提供一键安装脚本 wget http://fishros.com/install -O fishros && sudo bash fishros 接下来按顺序按 1 1 2 3 1 再次运行 w…

红酒哲学:品味流转时光,探寻生活之深邃奥秘

在繁华的都市中&#xff0c;我们时常被各种声音和色彩所包围&#xff0c;追求着速度与激情。然而&#xff0c;在这喧嚣之中&#xff0c;总有那么一刻&#xff0c;我们渴望静下心来&#xff0c;品味一份不同的宁静与深度。这时&#xff0c;一杯雷盛红酒便成了我们与内心对话的桥…

太赞了!SD AI绘画,热门青衫映雪写真制作,一键出片,轻松复刻!【内含相关模型及ComfyUI工作流】

hello&#xff0c;大家好我是安琪&#xff01; 今天安琪给大家带来了一篇关于写真制作&#xff0c;我通过SD WebUI进行本次青衫映雪主题的写真制作。(相关内容文末可自行扫描获取) 准备工作&#xff1a; 1.大模型准备真人写实大模型&#xff0c;我这里使用了TQing v3.4 2.…

Radxa 学习摘录

文章目录 一、参考资料二、硬件知识 一、参考资料 技术论坛&#xff08;推荐&#xff09; 官方资料下载 wiki资料 u-boot 文档 u-boot 源码 内核文档 内核源码 原理图 二、硬件知识 Radxa 3B 主板概览 MIPI接口 MIPI CSI&#xff08;Camera Serial Interface&#xff09;…

【前端】HTML+CSS复习记录【2】

文章目录 前言一、img&#xff08;图片标签&#xff09;二、a&#xff08;链接标签&#xff09;三、ul&#xff08;无序列表&#xff09;四、ol&#xff08;有序列表&#xff09;系列文章目录 前言 长时间未使用HTML编程&#xff0c;前端知识感觉忘得差不多了。通过梳理知识点…

智慧园区大数据云平台建设方案(Word原件)

第一章 项目建设背景及现状 第二章 园区创新发展趋势 第三章 工业园区大数据存在的问题 第四章 智慧工业园区大数据建设目的 第五章 智慧园区总体构架 第六章 系统核心组件 第七章 智慧工业园区大数据平台规划设计 获取方式&#xff1a;本文末个人名片直接获取。 软件资料清单…

文本生成sql模型(PipableAI/pip-sql-1.3b)

安装环境 pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118 pip install transformers 代码 question "What are the email address, town and county of the customers who are of the least common gender?"sc…

three.js - MeshStandardMaterial(标准网格材质)- 金属贴图、粗糙贴图

金属贴图、粗糙贴图 金属贴图&#xff1a;metalnessMap 和 粗糙贴图&#xff1a;roughnessMap&#xff0c;是用于模拟物体表面属性的两种重要贴图技术&#xff0c;这两种贴图&#xff0c;通常与基于物理的渲染&#xff08;PBR&#xff09;材质&#xff08;如&#xff1a;MeshSt…