x86系列CPU寄存器和汇编指令总结

文章目录

    • 概要
    • 一、寄存器
        • 1.1、8086寄存器
        • 1.2、通用寄存器
        • 1.3、扩展寄存器
    • 二、指令集
    • 三、x86指令集常见指令使用说明
    • 四、汇编
        • 4.1、汇编语法
        • 4.2、nsam汇编
    • 五、参考

概要

在对学习Go的过程中,涉及到了汇编,因此对X86系列CPU的背景、寄存器、汇编指令做了一番了解,仅以本文作为总结,便于后续查看。

x86架构始于Intel在1978年推出的8086 CPU(典中典),它是从Intel 8008处理器中发展而来的,而8008则是发展自Intel 4004的。8086在三年后为IBM PC所选用,之后x86便成为了电脑的标配(当然,现在有些电脑采用ARM架构的CPU,比如mac m1),成为了非常成功的CPU架构。

除了Intel公司,其他公司也有制造x86架构的CPU,比如IBM、IDT以及Transmeta,但Intel以外最成功的制造商要数AMD了,其早先产品Athlon系列处理器的市场份额仅次于Intel的Pentium。

值得注意的是8086是16位处理器,直到1985年32位的80386(IA-32)才被开发,接着推出了一系列针对32位架构细微改进的CPU型号,直到2003年AMD对于这个架构进行了64位的扩展,并命名为AMD64,后来英特尔也推出了与之兼容的处理器,并命名为Intel 64。两者一般被统称为x86-64或x64,开创了x86的64位时代。

一、寄存器

正如概要中所说,x86系列发展从16、32到64位,寄存器也随之发展。

1.1、8086寄存器

8086结构图
8086中寄存器总共为 14 个,且均为 16 位。

  • 通用寄存器
寄存器含义
AX、BX、CX、DX
也称为数据寄存器
AX (Accumulator):累加寄存器,也称之为累加器;
BX (Base):基地址寄存器;
CX (Count):计数器寄存器;
DX (Data):数据寄存器;
SP、BP
也称为指针寄存器
SP (Stack Pointer):堆栈指针寄存器,存放栈顶偏移地址,与SS配合使用,即栈顶地址=SS给出的栈段首地址+SP中偏移地址;
BP (Base Pointer):基指针寄存器,一般存放函数栈帧起始指针;
SI、DI
也称为变址寄存器
SI (Source Index):源变址寄存器;
DI (Destination Index):目的变址寄存器;

ps:AX可以通过AH操作其高8位,AL操作其低8位(这样可以当做两个8位寄存器使用了),BX、CX、DX同理。

  • 控制寄存器
寄存器含义
IPIP (Instruction Pointer):指令指针寄存器;存放下一条指令的偏移地址,搭配CS使用,即下一条指令的地址=CS给出代码段基址<<4+IP中偏移地址
FLAG标志寄存器

ps:偏移地址也称偏移量,就是计算机里的内存分段后,在段内某一地址相对于段首地址(段地址)的偏移量。

  • 段寄存器
寄存器含义
CSCS (Code Segment):代码段寄存器;
DSDS (Data Segment):数据段寄存器;
SSSS (Stack Segment):堆栈段寄存器;
ESES (Extra Segment):附加段寄存器;

8086寄存器示意图

DS 寄存器和 ES 寄存器都属于段寄存器,其实它们和 CS 寄存器以及 SS 寄存器用起来区别不大,既然是段寄存器的话,自然它们存放的就是某个段地址了 。我们已经知道,如果 CPU 要访问一个内存单元时,我们必须要提供一个指向这个内存单元的物理地址给 CPU ,而我们也知道在 8086 CPU 中,物理地址是由段地址左移 4 位,然后加上偏移地址形成的,所以,我们也就只需要提供段地址和偏移地址即 OK 。8086 CPU 呢,提供了一个 DS 寄存器,并且通常都是通过这个 DS 段寄存器来存放要访问的数据的段地址 。DS(Data Segment):很显然,DS 中存放的是数据段的段地址 。但是这里不得不再点一下,那就是我们对段的支持是在 CPU 上体现的,而不是在内存中实现了段,所以事实上我们使用的段其实是一个逻辑概念,即是我们自己定义的,再说白了,我定义一个段,我说它是数据段那它就是数据段,我说它是代码段那么它就是代码段,它们其实都是一块连续的内存而已,我们只要能定位不同段即可,至于为什么要区分为数据段和代码段,很明显,是用来给我们编程提供方便的,即我们在自己的思想上或者说是编码习惯上规定,数据放数据段中,代码放代码段中 。而我们在使用数据段的时候,为了方便或者说是代码的编写方便起见,我们一般把数据段的段地址放在 DS 寄存器中,当然,如果你硬要觉得 DS 不顺眼,那你可以换个 ES 也是一样的,至于 ES(Extra Segment) 段寄存器的话,自然,是一个附加段寄存器,如果再说得过分点,就当它是个扩展吧,当你发现,你几个段寄存器不够用的时候,你可以考虑使用 ES 段寄存器,在使用方式上,则和其他的段寄存器没什么区别 。

1.2、通用寄存器

通用寄存器在汇编指令中是最多用到了,所以这里多说一嘴。

最初的8086有8个16位通用寄存器从%ax~%sp,等开发出32位时,这8个寄存器也被扩展成32位寄存器,标号命名以%e(Extense)开头从%eax ~ %esp,后来又了64位的,这8个寄存器也被扩展成64位寄存器,标号命名以%r(Register)开头从%rax ~ %rsp,另外还增加了8个寄存器,它们的标号命名规则为%r8 ~%r15。

x64通用寄存器:

64位寄存器操作低32位操作低16位操作低8位
raxeaxaxal
rax与rsp之间的寄存器同理
rspespspspl
r8r8dr8wr8b
r8与r15之间的同理
r15r15dr15wr15b

另外rax、rbx、rcx 和 rdx 的高 8 位仍可通过 ah、bh、ch、dh访问。

1.3、扩展寄存器

Intel为了增强CPU对多媒体信息的处理能力,提高CPU处理3D图形、视频和音频信息的能力,在1996年推出了多媒体扩展指令集MMX(Multi-Media Extension),为了支持该指令集,增加了[MM0,MM7]8个64位的寄存器。

由于MMX指令集只局限于整数的运算,反响并不好。在1999年Intel推出SSE指令集(Streaming SIMD Extension),支持整数和浮点数运算,从此多了[XMM0,XMM15]共16个128位的寄存器。后续又接连推出了SSE2到SSE4.2作为补充的SSE家族,还有AVX、AVX-512、AMX等指令指令集家族,相应的也增加了[YMM0,YMM15]16个256位的寄存器和[ZMM0,ZMM31]32个512位的寄存器

ps:当然,x86系列寄存器肯定不止这些,本文只介绍了相对常用的,有兴趣的可到Intel官网了解传送门

二、指令集

指令集,就是CPU中用来计算和控制计算机系统的一套指令的集合,而每一种新型的CPU在设计时就规定了一系列与其他硬件电路相配合的指令系统。而指令集的先进与否,也关系到CPU的性能发挥,它也是CPU性能体现的一个重要标志。

通俗的理解,指令集就是CPU能认识的语言,指令集运行于一定的微架构之上,不同的微架构可以支持相同的指令集,比如Intel和AMD的CPU的微架构是不同的,但是同样支持X86指令集,这很容易理解,指令集只是一套指令集合,一套指令规范,具体的实现,仍然依赖于CPU的翻译和执行。

指令集一般分为RISC(精简指令集 Reduced Instruction Set Computer)和CISC(复杂指令集Complex Instruction Set Computer)。Intel X86的第一个CPU定义了第一套指令集,后来一些公司发现很多指令并不常用,所以决定设计一套简洁高效的指令集,称之为RICS指令集(ARM指令集),从而将原来的Intel X86指令集定义为CISC指令集。两者的使用场合不一样,对于复杂的系统,CISC更合适,否则,RICS更合适,且低功耗。

  1. X86指令集
    X86指令集是Intel为其第一块16位CPU(i8086)专门开发的,IBM1981年推出的世界第一台PC机中的CPU—i8088(i8086简化版)使用的也是X86指令,同时电脑中为提高浮点数据处理能力而增加的X87芯片系列数学协处理器则另外使用X87指令,以后就将X86指令集和X87指令集统称为X86指令集。常见的如mov、add、sub、pop、push等.

  2. MMX指令集
    1996年Intel的MMX(AMD认为这是矩阵数学扩展Matrix Math Extensions的缩写,但大多数时候都被当成Multi-Media Extension,而Intel从来没有官方宣布过词源)技术出现。尽管这项新的科技得到广泛宣传,但它的精髓是非常简单的:MMX定义了八个64位SIMD寄存器,与Intel Pentium处理器的FPU堆栈有相重叠。不幸的是,这些指令无法非常简单地对应到由原来C编译器所产生的脚本中。MMX也只局限于整数的运算。这项技术的缺点导致MMX在它早期的存在有轻微的影响。现今,MMX通常是用在某些2D影片应用程序中。

  3. SSE指令集
    由于MMX指令并没有带来3D游戏性能的显著提升,所以,1999年Inter公司在Pentium III CPU产品中推出了数据流单指令序列扩展指令(SSE),兼容MMX指令。SSE为Streaming SIMD Extensions的缩写,如同其名称所表示的,是一种SSE指令包括了四个主要的部份:单精确度浮点数运算指令、整数运算指令(此为MMX之延伸,并和MMX使用同样的寄存器)、Cache控制指令、和状态控制指令。
    在Pentium 4 CPU中,Inter公司开发了新指令集SSE2。SSE2指令一共144条,包括浮点SIMD指令、整形SIMD指令、SIMD浮点和整形数据之间转换、数据在MMX寄存器中转换等几大部分。其中重要的改进包括引入新的数据格式,如:128位SIMD整数运算和64位双精度浮点运算等。相对于SSE2,SSE3又新增加了13条新指令,此前它们被统称为pni(prescott new instructions)。13条指令中,一条用于视频解码,两条用于线程同步,其余用于复杂的数学运算、浮点到整数转换和SIMD浮点运算。SSE4增加了50条新的增加性能的指令,这些指令有助于编译、媒体、字符/文本处理和程序指向加速。

这里说下 SIMD(Single Instruction Multiple Data),单指令多数据,其不是指令集,而是一种思想,MMX、SSE、AVX等指令集就是这种思想的具体实现。它的精髓就是要通过一条指令,实现对寄存器上多组数据并行操作。比如arr:=[]int64{1,2,3,4},计算下标1与下标3之和,下标2与下标4之和,如果使用x86指令集,就要执行add rax,rbx两次,而SSE指令直接addpd xmm0,xmm1就搞定了。

ps:AVX、AVX-512、AMX等指令集,就不一一介绍了。传送门

三、x86指令集常见指令使用说明

x86指令大全传送门。

本章节最好结合实战文章来看1和2。

汇编语法有很多,主流如Intel 语法(源操作数在后,目标操作数在前)、AT&T 语法(源操作数在前,目标操作数在后)、本节解释指令示例用Intel 语法,x86-64环境

  • mov
    mov指令将源操作数(可以是寄存器的内容、内存中的内容或立即数)复制到目的操作数(寄存器中或内存上)。mov不能用于直接从内存复制到内存。

语法如下:
mov <reg>,<reg>
mov <reg>,<mem>
mov <mem>,<reg>
mov <reg>,<const>
mov <mem>,<const>
示例如下:
mov rax, rbx; 将rbx的值拷贝到rax
mov rax, 0x5; 将立即数5加载到rax寄存器
mov qword ptr [rsp+0x18], 0x1;将立即数1(qword ptr表示占8字节)加载到地址rsp+0x18到rsp+0x20之间的内存区域
mov qword ptr [rsp+0x18], rax; 将rax寄存器的内容(qword ptr表示大小为8字节)加载到地址rsp+0x18到rsp+0x20之间的内存区域

  • lea - Load effective address
    lea是一个载入有效地址的指令,将源操作数表示的地址载入到目的操作数(寄存器)中。

语法如下:
lea <reg>,<mem>
示例如下:
lea rbp, ptr [rsp-0x10]; 将地址rsp-0x10到rsp-0x8之间内存区域存储的8字节地址(指针)加载到rbp寄存器

  • push
    push指令扩栈后将操作数压入栈顶。通过第一章寄存器可知,一般栈顶由rsp寄存器确定。栈一般从高地址向低地址扩张。

语法如下:
push <reg>
push <mem>
push <const>
示例如下:
push rbp; 将rbp寄存器的内容压入栈,x86-64下等价于sub rsp 0x8; mov rsp, rbp,也就是说push指令改变栈大小,减8字节

  • pop
    pop指令与push指令相反,将栈顶内容弹出,并缩栈。

语法如下:
pop <reg>
pop <mem>
示例如下:
pop rbp; 将栈顶内容写入rbp寄存器,x86-64下等价于 mov rbp,rsp; add rsp 0x8 也就是说pop指令改变栈大小,增8字节

  • call
    call指令跳转到标签处,其主要工作是扩栈(字节数为指针大小)后将call下一条指令地址写入栈顶(下一条指令由rip寄存器会自动装载的),并跳转到标签。

语法如下:
call <label>
示例如下:
call $main.sub; 调用sub函数,等价于push rip,jmp <label>; 也就是说call指令也会改变栈大小,x86-64下减8字节

  • ret
    ret指令指令实现子程序的返回机制, 其主要工作是将栈顶内容写入rip寄存器,并缩栈,后续cpu继续执行rip的指令。这样就和call实现的函数的调用与返回。

ret; 等价于pop rip;也就是说ret指令也会改变栈大小,x86-64下增加8字节

  • cmp
    cmp指令比较源操作数与目的操作数大小,比较结果设置到FLAG寄存器中。
  • jxx条件跳转,根据FLAG寄存器特定标志位来决定是否跳转

je或jz 如果相等(等于零)跳转;
jne或jnz 如果不相等(等于零)跳转;
js 如果为负值跳转;
jns 如果不为负值跳转;
jg 如果大于跳转;
jge 如果大于等于跳转;
jl 如果小于跳转;
jle 如果小于等于跳转;

运算指令

add rax,rbx;加法,rbx+rax,并将结果保存到rax中。
sub rax,rbx;减法,rbx-rax并将结果保存到rax中。
inc rax; 自增,rax=rax+1;
dex rax;自减,rax=rax-1
imul rax,rbx;乘法
idiv rax,rbx;除法
and、or、xor、not、neg 都是位运算,依次是与、或、异或、非、求补

四、汇编

提到汇编,不得不说汇编器和汇编语法。

4.1、汇编语法
汇编器默认语法典型应用场景‌
NASMIntelWindows/Linux 跨平台
GNU Assembler(GAS、AS)AT&TLinux 内核及 GCC 工具链
MASMIntelWindows 平台开发
YASMIntel跨平台优化
go tool asm‌plan9go编译过渡阶段

汇编语法也各有特色,简单说下其核心差异:

差异\语法IntelAT&Tplan9
操作数顺序‌目标在前,源在后源在前,目标在后源在前,目标在后
寄存器前缀无前缀前缀 %,如%eax无前缀
立即数前缀无前缀前缀 $,如$0x5前缀 $,如$0x5
指令后缀‌无,但通过byte ptr(1字节)、word ptr(2字节)、
dword ptr(4字节)、qword ptr(8字节)修饰符表示多少字节,
如mov qword ptr [rsp+0x10], 0x2
b(1字节)、w(2字节)、l(4字节)、q(8字节)
如movq $0x2 %rax
同AT&T,如SUBQ $48, SP
寻址方式[]作为修饰符,如[rsp+0x8],定位栈偏移 0x8 处的内存地址()作为修饰符,如8(%ebp),定位栈偏移 0x8 处的内存地址同AT&T
寄存器抽象不支持不支持支持,也叫伪寄存器,如SB、SP、FP、PC,用于简化内存寻址
函数声明无专用指令,通过标签和栈操作实现无专用指令,通过标签和栈操作实现TEXT func(SB), flags, $size
4.2、nsam汇编

汇编语言程序由三种类型的语句组成:

  • 可执行指令:直接告诉处理器要执行的操作,如mov、add等;
  • 汇编器指令:指导汇编器如何处理源代码及其生成的输出,如section、global _start、db、dw、resb等;
  • 宏:在源代码级别进行文本替换。
  • 汇编程序一般分成3个区域:
  • data section: 用于声明初始化的数据或者常量,运行时不会更改;
  • bss section: 用于声明全局变量;
  • text section: 用于保存实际的代码。这个部分必须以声明global _start开始,它告诉内核程序从哪里开始执行。
    这里着重说下section汇编指令。

section 指令用于定义或切换段;
section .my_data progbits alloc write ; 定义可读写的初始化数据段
section .my_code progbits alloc exec ; 定义可执行的代码段
section .my_rodata progbits alloc ; 定义只读数据段(不可写)

section .my_data progbits alloc writemy_var: dd 0x12345678  ; 定义可写数据section .text
global _start
_start:mov eax, [my_var]      ; 正常读取mov dword [my_var], 0  ; 允许写入

我们一般给程序内存分为代码段、数据段、堆、栈等、其中代码段和数据段的内容在汇编中就由section 指令定义:

section .data 存放已初始化全局变量
section .bss 存放未初始化全局变量
section .text 存放可执行代码,特别注意。这个部分必须以声明global _start开始,它告诉内核程序从哪里开始执行。
section .rodata 存放只读数据(如字符串,常量等)
这几种段无需设置读写权限,nsam汇编器会自动追加上,比如还会在.bss后追加nobits alloc write,表示未初始化且可写,因为一般程序会这么分,约定俗成了。

一个输出hello world的汇编程序:

#hello.asm 文件
section .datahello db 'Hello, World!',0xA  ; 定义字符串并以换行符结束len equ $ - hello             ; 计算字符串长度section .textglobal _start                 ; 指定入口点_start:; 写字符串到标准输出mov eax, 4                    ; 系统调用号 (sys_write)mov ebx, 1                    ; 文件描述符 (stdout)mov ecx, hello                ; 要写入的缓冲区地址mov edx, len                  ; 缓冲区长度int 0x80                      ; 触发中断; 退出程序mov eax, 1                    ; 系统调用号 (sys_exit)xor ebx, ebx                  ; 返回状态码 0int 0x80                      ; 触发中断

x86-64下yum安装下nasm汇编器

nasm -f elf64 hello.asm -o hello.o
ld hello.o -o hello
./hello  # Hello, World!

五、参考

1]:维基百科Intel_8086
2]:维基百科x86发展
3]:x86汇编指令
4]:Intel官网SSE
5]:x64 体系结构
6]:nasm官网

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

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

相关文章

戴维斯双击选股公式如何编写?

戴维斯双击&#xff0c;指的是营收增长和净利润增长同步&#xff0c;并有超预期的财务状况。 戴维斯双击是指在低市盈率&#xff08;P/E&#xff09;时买入股票&#xff0c;待公司盈利增长和市盈率提升后卖出&#xff0c;以获取双重收益。以下是一个简单的通达信选股模型示例&…

前端面试宝典---vue原理

vue的Observer简化版 class Observer {constructor(value) {if (!value || typeof value ! object) returnthis.walk(value) // 对对象的所有属性进行遍历并定义响应式}walk (obj) {Object.keys(obj).forEach(key > defineReactive(obj, key, obj[key]))} } // 定义核心方法…

从“聋哑设备“到超级工厂:EtherCAT转Modbus协议网关正在重构工业未来

当全球工厂加速迈向工业4.0&#xff0c;您的生产线是否因Modbus设备“拖后腿”而被迫降速&#xff1f;无需百万改造&#xff01;无需淘汰设备&#xff01;一套EtherCAT从站转Modbus协议网关&#xff0c;让30年老机床与智能工厂实时对话&#xff0c;效率飙升300%&#xff01; 一…

Tauri文件系统操作:桌面应用的核心能力(入门系列四)

今天我们来聊聊Tauri中一个超级重要的功能 - 文件系统操作。这可是Web应用和桌面应用最大的区别之一。在浏览器里&#xff0c;出于安全考虑&#xff0c;我们对文件系统的访问被限制得死死的。但在Tauri桌面应用中&#xff0c;我们可以安全地访问用户的文件系统&#xff0c;这简…

Python解析地址中省市区街道

Python解析地址中省市区街道 1、效果 输入&#xff1a;海珠区沙园街道西基村 输出&#xff1a; 2、导入库 pip install jionlp3、示例代码 import jionlp as jiotext 海珠区沙园街道西基村 res jio.parse_location(text, town_villageTrue) print(res)

基于Node+HeadlessBrowser的浏览器自动化方案

基于NodeHeadlessBrowser的浏览器自动化方案 什么是无头浏览器(Headless Browser)&#xff1f; 无头浏览器&#xff0c;就像是一个没有用户界面的浏览器程序。你可以想象它就是一个“隐形”的浏览器&#xff0c;只不过它没有图形界面&#xff0c;但能做我们用普通浏览器所能做…

AEB法规升级后的市场预测与分析:技术迭代、政策驱动与产业变革

文章目录 一、政策驱动&#xff1a;全球法规升级倒逼市场扩容二、技术迭代&#xff1a;从“基础防护”到“场景全覆盖”三、市场格局&#xff1a;竞争加剧与生态重构四、挑战与未来展望五、投资建议结语 近年来&#xff0c;全球汽车安全法规的加速升级正深刻重塑AEB&#xff08…

【Docker项目实战】使用Docker部署Caddy+vaultwarden密码管理工具(详细教程)

【Docker项目实战】使用Docker部署vaultwarden密码管理工具 前言一、vaultwarden介绍1.1 vaultwarden简介1.2 主要特点二、本次实践规划2.1 本地环境规划2.2 本次实践介绍三、本地环境检查3.1 检查Docker服务状态3.2 检查Docker版本3.3 检查docker compose 版本四、拉取镜像五、…

第十六届蓝桥杯大赛软件赛省赛第二场

第十六届蓝桥杯大赛软件赛省赛第二场 大家好。最近参加了第十六届蓝桥杯大赛软件赛省赛第二场 Python 大学 B 组的比赛&#xff0c;现在来和大家分享一下我的解题思路和代码实现。以下内容是我自己写的&#xff0c;可能对也可能错&#xff0c;欢迎大家交流讨论。 试题 A&…

硬件须知的基本问题2

目录 1、典型电路 1. DC5V 转 DC3.3V 电路 2. 通信电路 2、STM32F103RCT6 最小系统如何设计搭建电路 1. 电源电路 2. 复位电路 3. 时钟电路 4. 下载电路 5. 单片机连接连接 3、请列举你所知道的二极管型号&#xff1f; 1. 整流二极管 2. 小信号二极管 3. 肖特基二极管 4. 超…

力扣HOT100——102.二叉树层序遍历

给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;[[3],[9,20],[15,7]] /*** Definition for a bi…

CSS 定位学习笔记

一、定位概述 CSS 定位是控制 HTML 元素在页面中位置的核心技术&#xff0c;允许元素脱离正常文档流&#xff0c;实现复杂布局效果。 二、定位类型对比 定位类型属性值参考基准是否脱离文档流常用场景静态定位static无否默认布局相对定位relative自身原位置否元素微调绝对定…

Threejs中顶视图截图

Threejs中顶视图截图 一般项目中的每个模型&#xff0c;都需要有一张对应的图片&#xff0c;一般是顶视图&#xff0c;在对应的2D场景场景中展示。以下分享一个实现方式&#xff0c;先将清空模型材质的纹理&#xff0c;把颜色设置为白色&#xff0c;使用正交相机截取顶视图&am…

深度探索:DeepSeek赋能WPS图表绘制

一、研究背景 在当今数字化信息爆炸的时代&#xff0c;数据处理与可视化分析已成为众多领域研究和决策的关键环节。随着数据量的急剧增长和数据维度的不断丰富&#xff0c;传统的数据可视化工具在应对复杂数据时逐渐显露出局限性。Excel作为广泛应用的电子表格软件&#xff0c;…

第11章 面向分类任务的表示模型微调

​​​​​​第1章 对大型语言模型的介绍第2章 分词和嵌入第3章 解析大型语言模型的内部机制第4章 文本分类第5章 文本聚类与主题建模第6章 提示工程第7章 高级文本生成技术与工具第8章 语义搜索与检索增强生成第9章 多模态大语言模型第10章 构建文本嵌入模型第12章 微调生成模…

4.换行和续写

一.FileOutputStream写出数据的两个小问题&#xff1a; 问题一&#xff1a;换行 假设在本地文件中要输出数据aweihaoshuai 666&#xff0c;在输出这个数据时要换行写出&#xff0c;如下图&#xff1a; 问题二&#xff1a;续写 假设在一个文本文件中已经存在数据aweihaoshuai…

联易融受邀参加上海审计局金融审计处专题交流座谈

近日&#xff0c;联易融科技集团受邀出席了由上海市审计局金融审计处组织的专题交流座谈&#xff0c;凭借其在供应链金融领域的深厚积累和创新实践&#xff0c;联易融为与会人员带来了精彩的分享&#xff0c;进一步加深现场对供应链金融等金融发展前沿领域的理解。 在交流座谈…

SOC估算:开路电压修正的安时积分法

SOC估算&#xff1a;开路电压修正的安时积分法 基本概念 开路电压修正的安时积分法是一种结合了两种SOC估算方法的混合技术&#xff1a; 安时积分法&#xff08;库仑计数法&#xff09; - 通过电流积分计算SOC变化 开路电压法 - 通过电池电压与SOC的关系曲线进行校准 方法原…

代码随想录打卡|Day27(合并区间、单调递增的数字、监控二叉树)

贪心算法 Part05 合并区间 力扣题目链接 代码随想录链接 视频讲解链接 题目描述&#xff1a; 以数组 intervals 表示若干个区间的集合&#xff0c;其中单个区间为 intervals[i] [starti, endi] 。请你合并所有重叠的区间&#xff0c;并返回 一个不重叠的区间数组&#xff0…

PostgreSQL的扩展 pg_cron

PostgreSQL的扩展 pg_cron pg_cron 是 PostgreSQL 的一个开源扩展&#xff0c;它允许在数据库内部使用 cron 语法调度定期任务&#xff0c;是最接近 Oracle DBMS_SCHEDULER 的解决方案。 一 安装与配置 1 安装方法 下载路径&#xff1a; https://github.com/citusdata/pg_…