FreeRTOS工程创建,创建多任务程序,基于汇编对ARM架构的简单理解
FreeRTOS工程创建
下载STM32CubeMX尽量找网盘下载(只是建议,没有说官网不行)
1.创建 STM32CubeMX 工程


2.配置时钟


3.配置 FreeRTOS



4.生成 Keil MDK 的工程

(2)随后去同界面的“Code Generator”设置、生成工程:
5.问题
由于不同的STM32CubeMX,软件的版本可能不同,我在配置之后,打开Keil发现按照以上方法配置会报错,这可能是你所使用STM32CubeMX 版本不匹配所导致的,只要打开如图
找见Firmware Package Name and Version,之后尝试修改版本即可
创建多任务程序
(1)系统默认线程理解
- 在FreeRTOS微型操作系统中文件FreeRTOS.c存放着默认的线程代码
- FreeRTOS与RT-Thread都属于微型实时操作系统,但是他们的代码不通用,所以有一个对实时操作系统的一个进行分装的文件cmsis_os2.c进行分装他们,类似也有,例如oled有不同型号,所以也要有文件对他们进行封装,lcd.c文件
在FreeRTOS.c中
这段代码就是创建了一个默认的Thread
osThreadNew方法属于cmsis_os2.c的一个基于FreeRTOS的方法
osThreadId_t osThreadNew (osThreadFunc_t func, void *argument, const osThreadAttr_t *attr)
函数简介
osThreadNew 是一个用于创建新线程并将其添加到活动线程列表中的函数。
参数解析
func:线程函数的指针,这是线程启动后要执行的函数。(就是这个线程启动要执行的代码的函数的名字)
/* USER CODE END Header_StartDefaultTask */ void StartDefaultTask(void *argument) {/* USER CODE BEGIN StartDefaultTask *//* Infinite loop */LCD_Init();LCD_Clear();for(;;){//Led_Test();LCD_Test();//MPU6050_Test(); //DS18B20_Test();//DHT11_Test();//ActiveBuzzer_Test();//PassiveBuzzer_Test();//ColorLED_Test();//IRReceiver_Test();//IRSender_Test();//LightSensor_Test();//IRObstacle_Test();//SR04_Test();//W25Q64_Test();//RotaryEncoder_Test();//Motor_Test();//Key_Test();//UART_Test();}/* USER CODE END StartDefaultTask */ }/* Private application code --------------------------------------------------*/ /* USER CODE BEGIN Application *//* USER CODE END Application */
argument:传递给线程函数的参数,可以是任何类型的指针,这个指针将在线程启动时作为参数传入(一般看需求)
attr:线程属性的指针。如果设置为 NULL,则会使用默认值创建线程。这些属性可能包括线程的优先级、栈大小等设置。
defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);
osThreadNew函数的返回值实际上是一个osThreadId_t类型的值
&defaultTask_attributes返回的是结构体值
/* Definitions for defaultTask */ osThreadId_t defaultTaskHandle; const osThreadAttr_t defaultTask_attributes = {.name = "defaultTask",.stack_size = 128 * 4,.priority = (osPriority_t) osPriorityNormal, };
返回值
osThreadId_t:返回新创建线程的 ID,以便其他函数可以引用这个线程。
如果创建失败,返回值将是 NULL,表示发生了错误。
总结
这个函数的目的是方便开发者创建多线程应用,允许用户指定线程的功能和参数,同时支持自定义线程属性
(2)自己创建一个线程
找见如图所示位置
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */const configSTACK_DEPTH_TYPE usStackDepth,void * const pvParameters,UBaseType_t uxPriority,TaskHandle_t * const pxCreatedTask )
参数解释
pxTaskCode:
- 类型:
TaskFunction_t
- 描述:指向任务函数的指针,该函数包含任务的代码逻辑。
pcName:
- 类型:
const char * const
- 描述:任务的名称,用于调试和识别任务。可以是任意字符串,但最好简短且有意义。
usStackDepth:
- 类型:
const configSTACK_DEPTH_TYPE
- 描述:任务堆栈的深度,通常以堆栈大小(字)为单位。这个参数定义了任务可以使用的内存量。
pvParameters:
- 类型:
void * const
- 描述:传递给任务的参数,可以是任何类型的指针。任务内可以通过这个参数获取相关数据。
uxPriority:
- 类型:
UBaseType_t
- 描述:任务的优先级,数值越大,优先级越高。FreeRTOS 支持多个优先级。
pxCreatedTask:
- 类型:
TaskHandle_t * const
- 描述:用于接收创建的任务的句柄,便于后续管理(如删除、挂起等)。
返回值
- 返回值类型:
BaseType_t
- 描述:函数调用成功时返回
pdPASS
,失败时返回errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY
等错误码。总结
这个函数的主要作用是创建一个新的任务,并为其分配堆栈空间和其他资源,以便在 FreeRTOS 环境中并发执行多个任务。
书写你的线程代码,找见位置
基于汇编对ARM架构的简单理解
1.汇编的简单学习
PUSH
在汇编语言中,PUSH
指令用于将数据压入栈中。这是一个非常重要的操作,特别是在函数调用、保存寄存器值以及处理局部变量时。下面是关于PUSH
指令的一些基本内容:
基本概念
- 栈:栈是一种后进先出(LIFO)的数据结构,通常用于临时存储数据。
- PUSH指令:将指定的值压入栈顶,并自动调整栈指针。
表示将r4到r7以及LR压入栈中,SP寄存器自动调整栈顶内容
MOV
- 基本功能:
MOV
指令用于将数据从一个位置复制到另一个位置,可以是寄存器、内存或立即数。 - 语法:
MOV destination, source
- 操作数类型:
- 可以是寄存器与寄存器之间的复制。
- 可以是寄存器与内存之间的复制。
- 可以是立即数与寄存器或内存之间的复制。
- 示例
-
MOV AX, 5 ; 将立即数5加载到AX寄存器 MOV BX, AX ; 将AX寄存器的值复制到BX寄存器
MOVS
- 基本功能:
MOVS
指令用于在处理字符串时,将源地址指向的数据移动到目标地址。它通常用于复制字节、字或双字,常与ESI
和EDI
寄存器配合使用。 - 语法:
MOVSB
,MOVSW
,MOVSD
- 操作数类型:
MOVSB
:移动字节(8位)。MOVSW
:移动字(16位)。MOVSD
:移动双字(32位)。
- 自动更新指针:执行后,
ESI
和EDI
指针会自动增加,以准备下一个数据项的复制。 -
MOVSB ; 将ESI指向的字节复制到EDI指向的字节,并自动更新指针 MOVSW ; 将ESI指向的字复制到EDI指向的字 MOVSD ; 将ESI指向的双字复制到EDI指向的双字
MOV与MOVS区别
总结
-
用途不同:
MOV
用于通用的数据传输。MOVS
系列用于字符串或块数据的复制。
-
指针更新:
MOV
不会自动更新任何指针。MOVS
在操作后会自动更新ESI
和EDI
寄存器。
-
操作数类型:
MOV
可以处理多种数据类型和操作数。MOVS
专注于字节、字和双字的移动。
SUB
在汇编语言中,SUB
指令用于执行减法操作。它从一个操作数中减去另一个操作数,并将结果存储在第一个操作数中。以下是关于 SUB
指令的一些详细信息:
基本概念
- 功能:
SUB
指令用于从第一个操作数中减去第二个操作数。 - 语法:
SUB destination, source
destination
:要进行减法运算的目标位置(通常是寄存器或内存)。source
:要减去的值(可以是寄存器、立即数或内存)。-
SUB AX, BX ; 将BX寄存器的值从AX寄存器中减去,结果存储在AX中
LDRD
LDRD
是一种汇编指令,通常用于 ARM 体系结构中。它的功能是从内存中加载双字(通常是 64 位或 32 位)到寄存器中。以下是关于 LDRD
指令的一些详细信息:
基本概念
- 功能:
LDRD
从内存中加载两个连续的数据项到两个寄存器中。 - 语法:
LDRD destination1, destination2, [address]
destination1
和destination2
是要加载数据的寄存器。[address]
是内存地址,指向要加载的数据的起始位置。
LDRD R0, R1, [R2] ; 从R2指向的内存地址加载数据,R0加载低地址的数据,R1加载高地址的数据
ADD
ADD
是一种基本的汇编指令,用于执行加法操作。它通常用于将两个操作数相加,并将结果存储在指定的目标寄存器中。以下是关于 ADD
指令的一些详细信息:
基本概念
- 功能:
ADD
将两个操作数相加,并将结果存储在第一个操作数中。 - 语法:
ADD destination, source1, source2
destination
:用于存储结果的寄存器或内存位置。source1
和source2
:要相加的两个操作数,可以是寄存器、立即数或内存。
ADD R0, R1, R2 ; 将R1和R2的值相加,结果存储在R0中
STR
STR
是一种汇编指令,主要用于将寄存器中的数据存储到内存中。以下是关于 STR
指令的一些详细信息:
基本概念
- 功能:
STR
将一个寄存器的值存储到指定的内存地址。 - 语法:
STR source, [address]
source
:要存储的寄存器。[address]
:目标内存地址,可以是直接地址或通过基址加偏移量计算得出。
STR R2, [R3, #4] ; 将寄存器R2中的值存储到R3指向的内存地址加上4的偏移量
POP
POP
是一种汇编指令,用于从栈中弹出数据并将其存储到指定的寄存器或内存位置。以下是关于 POP
指令的一些详细信息:
基本概念
- 功能:
POP
从栈顶弹出一个值,并将其存储到指定的目标寄存器或内存地址中。 - 语法:
POP destination
destination
:要接收弹出值的寄存器或内存位置
POP {R1, R2, R3} ; 同时从栈中弹出值到寄存器 R1, R2 和 R3
2.volatile
volatile 关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改,比如:操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。声明时语法:int volatile vInt; 当要求使用 volatile 声明的变量的值的时候,系统总是重新从它所在的内存读取数据,即使它前面的指令刚刚从该处读取过数据。而且读取的数据立刻被保存。
底层栈区细节请看
3.ARM内部架构简单理解
执行的是以下代码
cnt = add(cnt, 1);
执行的是以下代码
int add(volatile int a, volatile int b) {volatile int sum;sum = a + b;return sum; }
这个是地址码
这个是地址码对应的数据(在Flash中)
这个是为人类设计的汇编代码
add函数代码汇编解析
int add(volatile int a, volatile int b)
{volatile int sum;sum = a + b;return sum;
}
(1)PUSH {r0,r1,1r}
在栈区分配三个长度为4的内存空间分别为r0,r1,LR
sp这个地址在的栈区减12
(2)SUB sp,sp,#4
再分配一个空间用来存放sum
(3)LDRD r0,r1,[sp,#4]
读取(sp+4)地址以上的r0,r1的值
(4)ADD r0,r0,r1
r0=r0+r1;
(5)STR r0,[sp,#0]
将r0赋值给[sp+0]地址下的值sum
(6)POP {r1-r3,pc}
将LR寄存器指向的值给pc寄存器,返回r1,r2,r3
4.PC寄存器
程序计数器(PC,Program Counter)是CPU中的一个特殊寄存器,它的主要功能是存储下一条要执行的指令的地址。这样,CPU就能够知道接下来需要执行哪一条指令,从而保证程序的连续执行。在程序开始执行前,程序的首地址(即第一条指令所在的内存单元地址)会被送入PC。当执行指令时,CPU会自动修改PC的内容,使其始终指向将要执行的下一条指令的地址。大多数情况下,指令是顺序执行的,所以PC的值通常会自动递增,递增的量等于指令所含的字节数。当遇到转移指令时,下一条指令的地址将由转移指令的地址码字段来指定,而不是简单地通过递增PC的值来获取 。
在ARM架构中,程序计数器PC(R15)是唯一的,并且被所有模式共用。ARM处理器中使用R15作为PC,它总是指向取指单元。ARM处理器可以寻址4GB的地址空间,这是因为R15有32位宽度。在ARM状态下,R15的值总是能被4整除,也就是R15寄存器的最低2位总是0;而在Thumb状态下,R15的值总是能被2整除,也就是R15寄存器的最低位总是0 。
PC寄存器在计算机系统中扮演着重要的角色,它是CPU内部的重要组成部分,能够直接与CPU进行数据交换,提高数据的处理速度。同时,PC寄存器还可以协助CPU完成各种复杂的运算和控制操作,使得计算机系统能够高效、稳定地运行 。
在JVM(Java虚拟机)中,PC寄存器是对物理PC寄存器的一种抽象模拟。它用来存储指向下一条指令的地址,也即将要执行的指令代码。JVM中的PC寄存器是线程私有的,每个线程都有自己的程序计数器,它的生命周期与线程的生命周期保持一致。PC寄存器是程序控制流的指示灯,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成 。
5.LR寄存器
在ARM架构中,LR(Link Register)是一个特殊的寄存器,其主要作用是存储子程序调用的返回地址。当执行函数调用指令(如BL,Branch and Link)时,LR寄存器会被自动设置为当前指令的下一条指令地址,即返回地址。这样,在函数执行完毕后,可以通过将LR寄存器的值复制到程序计数器PC来实现函数的返回,通常使用的指令是 MOV PC, LR 或者 BX LR 。
LR寄存器在异常处理中也扮演着重要角色。当异常发生时,异常模式的LR用来保存异常返回地址,即将当前的PC值保存到LR中,以便在异常处理程序结束后,能够通过LR寄存器恢复执行流,回到异常发生前的状态。
ARM处理器针对不同的模式,共有6个链接寄存器资源,其中用户模式和系统模式共用一个LR,每种异常模式都有各自专用的R14寄存器(LR)。这些链接寄存器分别为R14、R14_svc、R14_abt、R14_und、R14_irq、R14_fiq。程序设计者需要清晰地了解处理器的模式与相应寄存器的对应关系,因为不同模式下的R14不是同一个物理资源,其内容可能截然不同。
在ARMv8架构中,LR寄存器的功能被X30寄存器所取代。在ARM64模式下,X30用作链接寄存器,存储子程序调用的返回地址。
相关文章:

FreeRTOS工程创建,创建多任务程序,基于汇编对ARM架构的简单理解
FreeRTOS工程创建 下载STM32CubeMX尽量找网盘下载(只是建议,没有说官网不行) 1.创建 STM32CubeMX 工程 (1)双击运行 STM32CubeMX,在首页面选择“Access to MCU Selector”,如下图所示࿱…...

C++STL--------list
文章目录 一、list链表的使用1、迭代器2、头插、头删3、insert任意位置插入4、erase任意位置删除5、push_back 和 pop_back()6、emplace_back尾插7、swap交换链表8、reverse逆置9、merge归并10、unique去重11、remove删除指定的值12、splice把一个链表的结点转移个另一个链表13…...
M1 Mac打开Jupyter notebook
当我成功安装了Jupyter之后,发现无法通过 jupyter notebook 开始工作。 最初的问题是 zsh command not found 该问题是个路径问题,通过添加PATH环境变量就行了,设置环境变量时需要注意,zshrc和bash_profile中都可以设置&…...
docker 仓库之harbor详解
Harbor 是一个开源的企业级容器镜像仓库,由 VMware 提供。它基于 Docker 分布式应用程序框架构建,旨在解决企业对容器镜像存储、安全性和可管理性的需求。Harbor 提供了丰富的功能,包括用户权限管理、镜像复制、审计日志、漏洞扫描等…...
【环境变量】windons的Path
在 Windows 操作系统中,“Path” 是一个重要的环境变量,它定义了操作系统在执行命令时搜索可执行文件的目录。简而言之,当你在命令行(例如 cmd 或 PowerShell)中输入一个命令时,Windows 会查看 “Path” 环…...
go语言里的切片
package mainimport "fmt"func main() {// 创建一个长度为3,容量为5的整数切片var numbers make([]int, 3, 8)// 打印初始状态printSlice(numbers) // 输出: len3 cap5 slice[0 0 0]// 向切片添加元素numbers append(numbers, 1, 2)// 再次打印…...
革新你的智能体验:AIStarter 3.1.1正式版现已上线【安全认证】ai应用市场,数字人,ai绘画,ai视频,大模型,工作流因有尽有
在这个日新月异的技术时代里,人工智能(AI)正以前所未有的速度改变着我们的生活与工作方式。作为行业内的先锋之一,我们非常高兴地宣布:经过团队不懈努力以及严格的测试与优化后,AIStarter 3.1.1新版现已震撼…...

【练习17】数组中的最长连续子序列
数组中的最长连续子序列_牛客题霸_牛客网 (nowcoder.com) 题目分析:排序双指针 排序后,判断是否连续:后一个数-前一个数1 排序后,判断是否重复:后一个数-前一个数0 public class Solution {public int MLS (int[] arr)…...

2024 最适合 Web 开发者的 9 款 Chrome 扩展
随着 2024 年的进展,Chrome 扩展程序已成为 Web 开发人员工具包中不可或缺的一部分,在浏览器中提供强大的功能。在这篇文章中,我们将探讨今年在 Web 开发社区掀起波澜的 9 大 Chrome 扩展程序。 1.Lighthouse https://chromewebstore.google…...

React综合指南(二)
https://activity.csdn.net/creatActivity?id10787 #1024程序员节|征文# 21、 React中的状态是什么?它是如何使用的?? 状态是 React 组件的核心,是数据的来源,必须尽可能简单。基本上状态是确定组件呈现…...

XML\XXE漏洞基本原理
前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 本文整理XXE漏洞的相应信息 XML与XXE漏洞 这个东西有许多叫法,XML漏洞与XXE漏洞差不多都是一个东西。 这个漏洞是出现在XMl上的,然后可以叫他XXE注入漏洞。 XML简介 XML是一种数据的传输…...

uniapp小程序自定义聚合点
注: 1.默认的聚合点可以点击自动展示子级点位,但是自定义的聚合点在ios上无法触发markerClusterClick的监听,至今未解决,不知啥原因 2.ios和安卓展示的点位样式还有有差别 源码附上 <template><view class"marke…...

Spring Boot在线考试系统:JavaWeb技术的应用案例
2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统,它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等,非常…...
Linux在服务器多节点下面如何快速查找日志
背景:最近在查找一个核心服务的后台日志,发现竟然部署了十几个节点,而且没使用ELK来做日志处理,所以查找日志非常不方便,不可能一个服务节点一个服务地找,所以通过同事间互相沟通找到一个方法,通…...

模数转换ADC0804的应用
【实验目的】 学习如何用单片机控制ADC0804芯片进行数模转换,掌握数码管动态扫描显示的原理。 【实验现象】 拧动AD旁边的电位器,会在数码管的前三位显示0-255之间的数值。 【实验说明】 动态扫描:就六位数码管显示123456举例说明如下&#x…...

CBAM中关于碳关税抵销
碳关税是欧盟为应对气候变化、防止 “碳泄漏” 而推出的一种边境调节机制。该机制的目的就是拉平进口产品与欧盟产品的碳成本,迫使其他国家建立碳市场或征收碳税,提高碳价,以达到和欧盟相同的水平,同时也有助于欧盟实现其气候目标…...
2.5 windows xp,ReactOS系统快速系统调用的实现
windows xp,ReactOS系统快速系统调用的实现 windows xp,ReactOS系统快速系统调用的实现 文章目录 **windows xp,ReactOS系统快速系统调用的实现**快速系统调用进入R0我们看MSR寄存器中的内容到底是啥子快速系统调用返回PspLookupKernelUserE…...

AI助力广交会,人工智能在制造业有哪些应用场景?
随着科技的飞速发展,人工智能(AI)正以前所未有的速度渗透到传统制造业中,为中国传统制造业注入了新的活力与变革,也为中国外贸的持续增长增添了更多底气。 在10月15日—19日举办的第136届中国进出口商品交易会上&…...
ElementPlus-Table表格-单选--TypeScript进阶篇
今天看个例子,这个例子是ElementPlus的组件Table表格下面的单选 <template> <el-table ref"singleTableRef" :data"tableData" highlight-current-row style"width: 100%" current-change"hand…...
三大智能体平台深度对比:字节Coze、百度AppBuilder、智谱智能体优劣解析
字节Coze智能体是一个多功能平台,具备丰富的功能和技能扩展能力。以下是它的一些核心功能和特性: 功能与技能 1. 插件功能 Coze智能体可以通过插件调用外部API,扩展智能体的能力。例如,它可以执行以下操作: 搜索信…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度
一、引言:多云环境的技术复杂性本质 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时,基础设施的技术债呈现指数级积累。网络连接、身份认证、成本管理这三大核心挑战相互嵌套:跨云网络构建数据…...

ESP32读取DHT11温湿度数据
芯片:ESP32 环境:Arduino 一、安装DHT11传感器库 红框的库,别安装错了 二、代码 注意,DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。
1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj,再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...
管理学院权限管理系统开发总结
文章目录 🎓 管理学院权限管理系统开发总结 - 现代化Web应用实践之路📝 项目概述🏗️ 技术架构设计后端技术栈前端技术栈 💡 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 🗄️ 数据库设…...

push [特殊字符] present
push 🆚 present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中,push 和 present 是两种不同的视图控制器切换方式,它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...
LOOI机器人的技术实现解析:从手势识别到边缘检测
LOOI机器人作为一款创新的AI硬件产品,通过将智能手机转变为具有情感交互能力的桌面机器人,展示了前沿AI技术与传统硬件设计的完美结合。作为AI与玩具领域的专家,我将全面解析LOOI的技术实现架构,特别是其手势识别、物体识别和环境…...

在Zenodo下载文件 用到googlecolab googledrive
方法:Figshare/Zenodo上的数据/文件下载不下来?尝试利用Google Colab :https://zhuanlan.zhihu.com/p/1898503078782674027 参考: 通过Colab&谷歌云下载Figshare数据,超级实用!!࿰…...

如何做好一份技术文档?从规划到实践的完整指南
如何做好一份技术文档?从规划到实践的完整指南 🌟 嗨,我是IRpickstars! 🌌 总有一行代码,能点亮万千星辰。 🔍 在技术的宇宙中,我愿做永不停歇的探索者。 ✨ 用代码丈量世界&…...