汇编学习——iOS开发对arm64汇编的初步了解
汇编学习——iOS开发对arm64汇编的初步了解
文章目录
- 汇编学习——iOS开发对arm64汇编的初步了解
- 前言
- 栈 指令 寄存器
- 寄存器
- 指令
- 运算指令
- 寻址指令
- 前变基 与 后变基
- 栈
- 堆(Heap)内存机制
- 三、栈(Stack)内存机制
- 3. 多级调用示例
- 例子
- ARM64 栈结构示意图(从高地址向低地址生长)
- 关键说明:
- 示例验证(小端序存储):
- 参考文章
前言
最近也是开始每天都在看源码,其中在阅读源码的过程之中,无论是属性关键字还是消息转发的内容,都多多少少涉及到了关于汇编的内容,看着真是令人头大,本着看了就要看全的精神,于是开始对arm64的汇编进行简单的学习。这篇文章就是对汇编浅尝则止的学习记录
栈 指令 寄存器
汇编最重要的就是三个部分就是栈 指令 寄存器,我们从较为复杂的寄存器说起
寄存器
寄存器是 CPU 中的高速存储单元,存取速度比内存快很多。
寄存器 | 职责 |
---|---|
X0 | 返回值、第一个参数(self ) |
X1-X7 | 第 2~8 个参数、临时变量(如 Objective-C 方法的选择器 _cmd 通常通过 X1 传递) |
X8 | 间接返回地址、全局变量偏移、系统调用号(在 Objective-C 中可能用于计算全局变量或类对象的偏移地址) |
X9-X15 | 调用者保存的临时变量 |
X19-X28 | 被调用者保存的长期变量 |
X29 (FP) | 栈帧管理、调试支持 |
X30 (LR) | 保存函数调用后的返回地址(如 bl 指令跳转时写入) |
XZR | 清零操作,用于快速清零其他寄存器(如 mov x0, xzr 等价于 x0 = 0 ) |
注:
x0 - x7 :用于子程序调用时的参数传递,超过八个会放到栈上传递
x0 和 w0 是同一个寄存器的不同尺寸的区别,x0 为 8 字节,w0 为 4 字节(x0 寄存器的低4字节), x0/w0 还用于返回值的传递
指令
需要提前知道的就是:在ARM64架构中,栈是向下生长的,换句话来说,栈内存从高地址向低地址方向扩展。具体来说,当数据被压入栈时,栈指针(SP)会减小(指向更低的内存地址);当数据弹出时,SP会增大(指向更高的内存地址)。这是ARM64与其他架构(如x86)共有的特性。
- 压栈操作会导致SP减小(如sp = sp - 16),栈顶向低地址方向移动
- 出栈操作则会使SP增大(如
sp = sp + 16
),栈顶恢复高地址。
这部分可能有点乱,我们在后面用一个例子的展示一下栈具体的存储结构
运算指令
mov x1,x0 ;将寄存器x0值 赋值 给x1
add x0,x1,x2 ;x0 = x1 + x2
sub x0,x1,x2 ;x0 = x1 - x2
mul x0,x1,x2 ;x0 = x1 * x2
sdiv x0,x1,x2 ;x0 = x1 / x2;and x0,x0,#0xF ;x0 = x0 & #0xF (与操作)
orr x0,x0,#9 ;x0 = x0 | #9 (或操作)
eor x0,x0,#0xF ;x0 = x0 ^ #0xF (异或操作)
寻址指令
寻址指令简单的可以分为 存和取
L开头的就是取: LDR(Load Register)、LDP(Load Pair)
S开头的就是存: STR(Store Register)、STP(Store Pair)
ldr x0,[x1] ;从 x1 指向的地址里面取出一个64位大小的数存入x0
ldp x1,x2,[x10, #0x10] ;从 x10+0x10 指向的地址里面取出2个64位的数,分别存入x1、x2
str x5,[sp, #24] ;往内存中写数据(偏移值为正), 把 x5 的值(64位的数值)存到 sp+24 指向的地址内存上
stur w0,[x29, #0x8] ;往内存中写数据(偏移值为负),将 w0 的值存储到 x29 - 0x8 这个地址里
stp x29,x30,[sp, #-16]! ;把 x29、x30 的值存到 sp-16 的地址上,并且把sp-=16 后面有个感叹号表示前变基模式
ldp x29,x30,[sp],#16 ;从 sp 地址取出16 byte数据,分别存入x29、x30,然后 sp+=16
寻址指令的格式
mov x0
[x10, #0x10] ;从 x10+0x10 的地址取值
[sp, #-16]! ;从 sp-16 地址取值,取完后再把 sp-16 writeback 回 sp
[sp], #16 v从 sp 地址取值,取完后把 sp+16 writeback 回 sp
前变基 与 后变基
模式 | 操作顺序 | 语法示例 | 应用场景 |
---|---|---|---|
前变基 | 1. 先更新基址寄存器 2. 再访问内存 | LDR X0, [X1, #8]! | 函数调用时预留栈空间 |
后变基 | 1. 先访问内存 2. 再更新基址寄存器 | LDR X0, [X1], #8 | 函数返回时恢复栈指针 |
栈
关于栈的内容,需要我们复习一下之前学习过的相关内容,就是计算机的内存结构
程序运行的时候,操作系统会给它分配一段内存,用来存储程序和运行产生的数据。这段内存有起始地址和结束地址,比如从 0x1000 到 0x8000,起始地址是较小的那个地址,结束地址是较大的那个地址。
堆(Heap)内存机制
- 核心特征
- 分配方式:动态申请(
malloc
/new
等) - 地址增长:从低位地址向高位地址扩展
- 生命周期:需手动释放或依赖垃圾回收
- 分配实例
// 内存起始地址 0x1000
void* p1 = malloc(10); // 分配 0x1000-0x100A
void* p2 = malloc(22); // 分配 0x100B-0x1020
三、栈(Stack)内存机制
- 核心特征
- 分配方式:函数调用自动创建帧(Frame)
- 地址增长:从高位地址向低位地址扩展
- 生命周期:函数结束时自动释放
简单来说,栈是由于函数运行而临时占用的内存区域
- 函数帧结构
int main() {int a = 2; // ↘ 主函数帧int b = 3; // │ 变量存储区
} // ↖ 栈顶地址 0x8000
上面的代码中,系统开始执行 main 函数的时,会为它在内存里面建立一个帧(frame),所有 main 的内部变量(比如a和b)都保存在这个帧里面。main 函数执行结束后,该帧就会被回收,释放所有的内部变量,不再占用空间。
3. 多级调用示例
int test(int x, int y) { // ↘ 子帧return x + y; // │ 参数/变量存储区
} // ↖ 新栈顶 0x7FF0int main() { // ↘ 主帧test(2, 3); // │ 返回地址保存区
} // ↖ 初始栈顶 0x8000
当我们在main函数之中调用了test函数时,当我们执行这一步,系统就会为了这个test函数创建一个帧,现在栈区就有了两个函数帧,一般调用了多少层的函数就有多少个帧
等到test函数运行结束,它的帧就会被系统自动回收,实现了函数的层层调用。
前面我们说到,arm64架构下的栈时从高位(地址)向低位(地址)分配的,,内存区域的结束地址是 0x8000,第一帧假定是16字节,那么下一次分配的地址就会从0x7FF0开始;第二帧假定需要64字节,那么地址就会移动到0x7FB0。
操作 | 栈地址范围 | 剩余空间 |
---|---|---|
主帧分配(16字节) | 0x8000 - 0x7FF0 | 0x7FF0 |
子帧分配(64字节) | 0x7FF0 - 0x7FB0 | 0x7FB0 |
例子
// hello.c
#include <stdio.h>
int test(int a, int b) {int res = a + b;return res;
}
int main() {int res = test(1, 2);return 0;
}
使用clang指令把以上内容编译为arn64代码
.section __TEXT,__text,regular,pure_instructions
.build_version ios, 13, 2 sdk_version 13, 2
.globl _test ; -- Begin function test
.p2align 2
_test: ; @test
.cfi_startproc
; %bb.0:
sub sp, sp, #16 ; =16
.cfi_def_cfa_offset 16
str w0, [sp, #12]
str w1, [sp, #8]
ldr w0, [sp, #12]
ldr w1, [sp, #8]
add w0, w0, w1
str w0, [sp, #4]
ldr w0, [sp, #4]
add sp, sp, #16 ; =16
ret
.cfi_endproc; -- End function
.globl _main ; -- Begin function main
.p2align 2
_main: ; @main
.cfi_startproc
; %bb.0:
sub sp, sp, #32 ; =32
stp x29, x30, [sp, #16] ; 16-byte Folded Spill
add x29, sp, #16 ; =16
.cfi_def_cfa w29, 16
.cfi_offset w30, -8
.cfi_offset w29, -16
stur wzr, [x29, #-4]
orr w0, wzr, #0x1
orr w1, wzr, #0x2
bl _test
str w0, [sp, #8]
mov w0, #0
ldp x29, x30, [sp, #16] ; 16-byte Folded Reload
add sp, sp, #32 ; =32
ret
.cfi_endproc; -- End function
.subsections_via_symbols
完整如上
.p2align 2 用于指定程序的对齐方式,这类似于结构体的字节对齐,为的是加速程序的执行速度,p2align 的单位是指数,即按照 2 的 n 次方对齐,这里的 .p2align 2 表示按照 2^2 = 4 字节对齐,如果单行指令数据长度不足4字节,将用 0 补全,超过 4 但不是 4 的倍数,则按照最小倍数补全
.cfi_startproc ;定义函数开始
.cfi_endproc ;定义函数结束
汇编中的如下部分被称为方法头(prologue),用于保存上一个方法调用栈帧的帧头,以及预留部分用于局部变量的栈空间。
sub sp, sp, #32 ; =32
stp x29, x30, [sp, #16] ; 16-byte Folded Spill
add x29, sp, #16 ; =16
汇编中的如下部分被称为方法尾(epilogue),用于取出方法头中栈帧信息及方法的返回地址,并将栈恢复到调用前的位置
ldp x29, x30, [sp, #16] ; 16-byte Folded Reload
add sp, sp, #32 ; =32
ret
我们先来看看Test函数
//源代码int test(int a, int b) {int res = a + b;return res;}//汇编sub sp, sp, #16 ; =16.cfi_def_cfa_offset 16str w0, [sp, #12]str w1, [sp, #8]ldr w0, [sp, #12]ldr w1, [sp, #8]add w0, w0, w1str w0, [sp, #4]ldr w0, [sp, #4]add sp, sp, #16 ; =16ret
在编译器生成汇编时,会首先计算需要的栈空间大小,并利用 sp (stack pointer)指针指向低地址开辟相应的空间。从 test 函数可以看到这里涉及了3个变量,分别是 a、b、res,int变量占据4个字节,因此需要12个字节,但 ARM64 汇编为了提高访问效率要求按照16字节进行对齐,因此需要16 byte 的空间,也就是需要在栈上开辟16字节的空间
代码的大致意思如下
sub sp, sp, #16 ; =16
将栈顶指针下移,即为函数的栈帧扩充空间
str w0, [sp, #12]
str w1, [sp, #8]
这2句的意思是,将 w0 存储在 sp+12 的地址指向的空间,w1 存储在 sp+8 存储的空间里,寄存器x0~x7用于子程序调用时的参数传递,按顺序入参。 x0 和 w0 是同一个寄存器的不同尺寸形式,x0为8字节,w0为x0的前4个字节,因此w0是函数的第一个入参a,w1是函数的第二个入参b
接下来 test 函数内部将 a 和 b 进行相加,需要注意的是,只有寄存器才能参与运算,因此接下来的汇编代码又将变量的值从内存中读出来,再进行相加运算。
ldr w0, [sp, #12]
ldr w1, [sp, #8]
add w0, w0, w1
为什么需要先存取后取出再操作,这个操作确实多余,是因为汇编没有进行优化的结果,把这个操作体现出来更有利于
ARM64 栈结构示意图(从高地址向低地址生长)
内存地址 | 存储内容(示例值) | 用途说明 | 备注 |
---|---|---|---|
0xFFFFFFC0 | (未分配,原栈顶) | 父函数栈帧 | 栈初始位置,SP 初始指向此处(高地址) |
0xFFFFFFBC | w0 (参数 a = 0x12345678) | 参数存储区(sp + 12) | 32 位参数,按 小端序 存储:0x78 0x56 0x34 `0x12 |
0xFFFFFFB8 | w1 (参数 b) | 参数存储区(sp + 8) | 第二个参数,通过 w1 传递 |
0xFFFFFFB4 | w0 (计算结果 c) | 临时结果存储(sp + 4) | 计算后的 32 位结果,通过 w0 返回 |
0xFFFFFFB0 | (填充区,未使用) | 16 字节对齐填充 | 因栈分配需按 16 字节对齐(48 字节或 16 的倍数) |
↓ SP 新位置 | SP = 0xFFFFFFB0 | 当前函数栈顶(低地址) | 通过 sub sp, sp, #16 分配空间,栈向低地址生长 |
关键说明:
-
栈生长方向:
- 栈从 高地址(0xFFFFFFC0)向低地址(0xFFFFFFB0) 扩展,符合 ARM64 的 满减栈(FD)。
- 每次函数调用会通过
sub sp, sp, #N
分配栈空间,N
必须是 16 的倍数。
-
数据读写规则:
- 存储指令(
str
):写入时从 低地址向高地址 填充字节(如0xFFFFFFB4
→0xFFFFFFB7
)。 - 加载指令(
ldr
):读取时从起始地址(如sp + 4
)连续读取 4 字节,按小端序组合为 32 位值。
- 存储指令(
-
对齐与填充:
- 若存储 64 位数据(如
x0
),需占用 8 字节且起始地址按 8 字节对齐(如0xFFFFFFB4
对齐到0xFFFFFFB0
)。 - 未使用的填充区域(如
0xFFFFFFB0
)确保栈帧按 16 字节对齐,避免内存访问错误。
- 若存储 64 位数据(如
示例验证(小端序存储):
假设 w0 = 0x12345678
,存储到 0xFFFFFFB4
后的内存布局:
地址 | 字节值 | 说明 |
---|---|---|
0xFFFFFFB4 | 0x78 | 最低有效字节 (LSB) |
0xFFFFFFB5 | 0x56 | |
0xFFFFFFB6 | 0x34 | |
0xFFFFFFB7 | 0x12 | 最高有效字节 (MSB) |
参考文章
iOS 汇编入门 - arm64基础
相关文章:
汇编学习——iOS开发对arm64汇编的初步了解
汇编学习——iOS开发对arm64汇编的初步了解 文章目录 汇编学习——iOS开发对arm64汇编的初步了解前言栈 指令 寄存器寄存器指令运算指令寻址指令前变基 与 后变基 栈堆(Heap)内存机制三、栈(Stack)内存机制 3. 多级调用示例 例子A…...
前端代理问题
在前后端联调的时候,有一次因为前端项目代理配置有问题,导致请求接口对不上, transpileDependencies: true,devServer: {hot: true,port: 8081,proxy: {/api: {target: http://localhost:8080,changeOrigin: true,ws: true,pathRewrite: {^/a…...
E+H流量计通过Profibus DP主站转Modbus TCP网关与上位机轻松通讯
EH流量计通过Profibus DP主站转Modbus TCP网关与上位机轻松通讯 在现代工业自动化的广阔舞台上,Profibus DP与Modbus TCP这两种通信协议各领风骚,它们在不同的应用场景中发挥着举足轻重的作用。但工业生产的复杂性往往要求不同设备、系统之间能够顺畅沟…...
TCP/IP 模型每层的封装格式
TCP/IP 模型是一个四层网络架构,每一层在数据传输时都会对数据进行封装,添加相应的头部(和尾部)信息。以下是各层的封装格式及关键字段说明: 1. 应用层(Application Layer) 封装格式:…...
openjdk底层汇编指令调用(一)——汇编指令及指令编码基础
汇编指令 计算机在执行过程时只识别代表0或者1的电信号。因此为了让计算机能够执行则须向计算机输入一系列01构成的指令。 例如在x64平台下,0x53,二进制为01010011,表示将rbx寄存器中的值压栈。 但是,对于程序员而言,…...
5G-A来了!5G信号多个A带来哪些改变?
5G-A来了!5G信号多个A带来哪些改变? 随着科技不断进步,通信网络的迭代升级也在加速。自4G、5G的推出以来,我们见证了通信技术的飞跃式发展。最近,越来越多的用户发现自己手机屏幕右上角的5G标识已经变成了“5G-A”。那…...
探索虚拟化:云计算时代的资源优化之道
前言 如果您想知道云提供商如何在全球范围内运行无数应用程序,而每个应用程序都没有机架服务器,那么答案就在于虚拟化。 它是为云提供支持的核心技术之一,在幕后悄悄工作,使现代计算高效、可扩展且具有成本效益。 在本文中&#x…...
用户登录构件示例
目录 一、登录构件概述 二、构件内部结构 1. 构件组成元素(表格形式) 2. 组件连接件设计...
【软件测试】基于项目驱动的功能测试报告
目录 一、项目的介绍 1.1 项目背景 二、测试目标 2.1 用户服务模块 2.1.1 用户注册模块 2.1.1.1 测试点 2.1.1.2 边界值分析法(等价类+边界值) 2.1.1.2.1 有效等价类 2.1.1.2.2 无效等价类 2.1.1.2.3 边界值 2.1.1.2.4 测试用例设计 2.2 文章标签模块 2.3 文章模…...
【QT】UDP通讯本地调试
qt已经写好了udp通讯代码,现在要进行测试。 1、终端输入ipconfig查看本机网卡的ipv4地址 2、 用udpBind函数,绑定到此ip和自定义的端口号。 3、 打开网络调试助手,自动检测到本机的ip地址,输入任意一个和程序里不一样的端口号。 …...
web animation API 锋利的css动画控制器 (更新中)
什么是web animation api 以及为什么要使用web animation api? web animation API 是web页面中控制DOM元素动画效果的javascript原生API。 它能够逐个关键帧控制动画效果,具有Timeline 机制能通过javascript来实现动画的暂停,播放&#x…...
Nginx的增强与可视化!OpenResty Manager - 现代化UI+高性能反向代理+安全防护
以下是对OpenResty Manager的简要介绍: OpenResty Manager (Nginx 增强版),是一款容易使用、功能强大且美观的反向代理工具 ,可以作为OpenResty Edge 的开源替代品基于 OpenResty 开发,支持并继承 OpenRes…...
Spring Boot 中的重试机制
Retryable 注解简介 Retryable 注解是 Spring Retry 模块提供的,用于自动重试可能会失败的方法。在微服务架构和分布式系统中,服务之间的调用可能会因为网络问题、服务繁忙等原因失败。使用 Retryable 可以提高应用的稳定性和容错能力 1。 使用步骤 &…...
[Java实战]Spring Boot 整合 Freemarker (十一)
[Java实战]Spring Boot 整合 Freemarker (十一) 引言 Apache FreeMarker 作为一款高性能的模板引擎,凭借其简洁语法、卓越性能和灵活扩展性,在 Java Web 开发中占据重要地位。结合 Spring Boot 的自动化配置能力,开发者能快速构建动态页面、…...
现有预测式外呼系统如何接入AI系统,使用AI辅助,判断出意向客户再转人工
很多用户还在使用老旧的预测式外呼系统,只能外呼接通后播放一个提示音,播放完提示音后在转给人工坐席, 如果重新部署一套AI外呼系统,涉及到业务系统的迁移,非常不方便。 现在我就做一个如何让现有外呼系统,…...
实战项目3(04)
目录 任务场景一 【r1配置】 【sw1配置】 任务场景二 【r1配置】 【sw1配置】 【sw2配置】 任务场景一 某公司网络为了减少广播包对网络的影响,网络管理员对网络进行了VLAN划分,完成VLAN划分后,为了不影响VL…...
[Java实战]Spring Boot 静态资源配置(十三)
[Java实战]Spring Boot 静态资源配置(十三) 引言 静态资源(如 HTML、CSS、JavaScript、图片等)是 Web 应用的基石。Spring Boot 通过自动化配置简化了静态资源管理,但面对复杂场景(如多模块项目、CDN 集成…...
ESP-ADF wifi_service子模块wifi_ssid_manager凭证管理函数详解
目录 ESP-ADF wifi_service子模块wifi_ssid_manager凭证管理函数详解WiFi凭证管理函数分析wifi_ssid_manager_savewifi_ssid_manager_erase_all 内部实现机制存储策略分析内部数据流向关键辅助函数分析重要的内部辅助函数详解get_stored_id_by_ssidnvs_get_write_idnvs_set_cou…...
数据分析预备篇---NumPy数组
NumPy是数据分析时常用的库,全称为Numerical Python,是很多数据或科学相关Python包的基础,包括pandas,scipy等等,常常被用于科学及工程领域。NumPy最核心的数据结构是ND array,意思是N维数组。 #以下是一个普通列表的操作示例:arr = [5,17,3,26,31]#打印第一个元素 prin…...
解决VirtualBox中虚拟机(ubuntu)与主机(windows)之间互相复制粘贴(文本)
一.开始的设置 1.在VirtualBox中打开设置,常规中修改主机与虚拟机交互设置 2.虚拟机关闭状态下,存储中选中控制器SATA,勾选‘使用主机输入输出’ 3.选中操作系统对应的虚拟文件,.vdi文件,勾选右边的固态驱动器。 4.启…...
单细胞RNA测序数据分析与可视化:从基础原理到高级应用
引言 单细胞RNA测序(scRNA-seq)技术的出现彻底改变了我们研究复杂生物系统的方式,使科学家能够在前所未有的精细水平上解析细胞异质性。传统的bulk RNA测序只能捕获细胞群体的平均表达特征,而单细胞转录组测序允许我们检测每个细…...
嵌入式硬件篇---UART
文章目录 前言1. UART协议基础1.1 物理层特性两根信号线无时钟信号电平标准TTL UARTRS-232 1.2 数据帧格式1.3 波特率计算波特率 2. STM32F103RCT6的UART配置2.1 硬件连接2.2 CubeMX配置启用USART1引脚分配中断启用(可选) 3. HAL库代码实现3.1 UART初始化…...
C# 通过ConfigurationManager读写配置文件App.Config
目录 简述代码描述一、构建App.config二、调用代码1、代码步骤说明2、输出结果说明 简述 App.config 是 C#中最常用的配置文件类型。 通常位于项目的根目录中,以 XML 格式存储配置信息。App.config 文件可以包含多个配置节,如 appSettings、connectionS…...
Python3安装HTMLTestRunner
1.下载HTMLTestRunner地址:http://tungwaiyip.info/software/HTMLTestRunner.html 2.下载的HTMLTestRunner.py是针对python2写的,所以需要改成python3适合的内容: 问题1:No module named StringIO, 原因:py…...
图形化编程革命:iVX携手AI 原生开发范式
一、技术核心:图形化编程的底层架构解析 1. 图形化开发的效率优势:代码量减少 72% 的秘密 传统文本编程存在显著的信息密度瓶颈。以 "按钮点击→条件判断→调用接口→弹窗反馈" 流程为例,Python 实现需定义函数、处理缩进并编写 …...
GC垃圾回收
Gc是语言提供的自动的内存管理机制,自动释放不需要的内存对象,让出存储器资源。 Go语言变革: V1.5的三色并发标记法 V1.5的三色并发标记为什么需要STW V1.5的三色标记为什么需要屏障机制(“强-弱”,三色不变式、插入屏障、删除屏障…...
“多端多接口多向传导”空战数据链体系——从异构融合架构到抗毁弹性网络的系统性设计
“多端多接口多向传导”空战数据链体系——从异构融合架构到抗毁弹性网络的系统性设计 文章目录 “多端多接口多向传导”空战数据链体系——从异构融合架构到抗毁弹性网络的系统性设计第一章 引言:空战数据链体系的范式革新1.1 空战数据链的演进逻辑1.2 新架构的核心理论价值1…...
Unity3D仿星露谷物语开发42之粒子系统
1、目标 使用例子系统,实现割草后草掉落的特效。 通过PoolManager获取特效预制体,通过VFXManager来触发特效。 2、配置例子特效 在Hierarchy -> PersistentScene下创建新物体命名为Reaping。 给该物体添加Particle System组件。 配置例子系统参数…...
python打卡训练营打卡记录day22
复习日 仔细回顾一下之前21天的内容,没跟上进度的同学补一下进度。 作业: 自行学习参考如何使用kaggle平台,写下使用注意点,并对下述比赛提交代码 kaggle泰坦尼克号人员生还预测 导入数据 # 导入所需库 import pandas as pd impor…...
网络编程(一)网络编程入门
本节课学习TCP客户端和服务器端编程架构,其分为分为C/S(客户端/服务器模式)和B/S(浏览器/服务器架构模式)两种模式。接下来我们分别了解这两种模式 C/S模式 C/S模式:服务器首先先启动,并根据客…...
华为IP(6)
VLAN聚合 VLAN聚合产生的技术背景 在一般是三层交换机中,通常采用一个VLAN接口的方式实现广播域之间的互通,这在某些情况下导致了IP地址的浪费 因为一个VLAN对应的子网中,子网号、子网广播地址、子网网关地址不能用作VLAN内的主机IP地址&a…...
初探机器学习与深度学习
本文以水果摊销量预测为例,揭示机器学习通过数据训练模型的核心逻辑,对比传统编程规则驱动模式。解析分类(疾病诊断)与回归(房价预测)两大任务的技术本质,类比前端开发中的类型定义与图表拟合。…...
3. 仓颉 CEF 库封装
文章目录 1. capi 使用说明2. Cangjie CEF2. 1实现目标 3. 实现示例 1. capi 使用说明 根据上一节 https://blog.csdn.net/qq_51355375/article/details/147880718?spm1011.2415.3001.5331 所述, cefcapi 是libcef 共享库导出一个 C API, 而以源代码形式分发的 li…...
Linux-TCP套接字编程简易实践:实现EchoServer与远程命令执行及自定义协议(反)序列化
一.TCP Socket常用API 1.1socket() NAMEsocket - create an endpoint for communicationSYNOPSIS#include <sys/types.h> /* See NOTES */#include <sys/socket.h>int socket(int domain, int type, int protocol); socket()打开一个网络通讯端口,如果…...
缓存(3):本地缓存作用 及 数据一致性 实现策略
概述 CAP 什么是CAP CAP理论,指的是在一个分布式系统中, Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可得兼。 三者关系如…...
【leetcode】《BFS扫荡术:如何用广度优搜索征服岛屿问题》
前言 🌟🌟本期讲解关于力扣的几篇题解的详细介绍~~~ 🌈感兴趣的小伙伴看一看小编主页:GGBondlctrl-CSDN博客 🔥 你的点赞就是小编不断更新的最大动力 🎆那么废话不…...
vue中理解MVVM
理解 在 Vue 中,MVVM(Model-View-ViewModel) 是其核心设计思想之一,它帮助实现了数据驱动的视图更新和良好的代码结构分离。我们来具体解析 Vue 是如何实现 MVVM 模式的。 🌐 MVVM 是什么? 角色含义Vue…...
[工具]B站缓存工具箱 (By 郭逍遥)
📌 项目简介 B站缓存工具箱是一个多功能的B站缓存工具,包含视频下载、缓存重载、文件合并及系统设置四大核心功能。基于yutto开发,采用图形化界面操作,极大简化B站资源获取与管理流程。 工具可以直接将原本缓存的视频读取&#…...
Docker Compose 完全指南:从入门到生产实践
Docker Compose 完全指南:从入门到生产实践 1. Docker Compose 简介与核心价值 Docker Compose 是一个用于定义和运行多容器 Docker 应用程序的工具。通过一个 YAML 文件来配置应用的服务,只需简单命令就能创建和启动所有服务。 核心优势:…...
《Redis应用实例》学习笔记,第二章:缓存二进制数据
前言 最近在学习《Redis应用实例》,这本书并没有讲任何底层,而是聚焦实战用法,梳理了 32 种 Redis 的常见用法。我的笔记在 Github 上,用 Jupyter 记录,会有更好的阅读体验,作者的源码在这里:h…...
ARM GIC(七)亲和路由:GICD_IROUTER寄存器具体如何与MPIDR配合使用?
ARM GIC(一) GIC V3架构基础学习笔记 完善亲和路由章节。 一、MPIDR MPIDR(Multiprocessor Affinity Register)寄存器在ARM架构中用于标识处理器的亲和性信息,这对于中断处理非常重要,特别是在多处理器系…...
stm32之SPI
目录 1.SPI通信协议1.1 简介1.2 硬件电路1.3 移位示意图1.4 SPI时序基本单元1.5 SPI时序 2.W25Q642.1 简介2.2 硬件电路2.3 框图2.3.1 结构介绍2.3.2 混淆 2.4 Flash操作注意事项2.4.1 写操作2.4.2 读取操作 2.5 芯片手册补充2.5.1 状态寄存器2.5.2 指令集 3.软件操作W25Q644.S…...
数据库事务以及JDBC实现事务
一、数据库事务 数据库事务(Database Transaction)是数据库管理系统中的一个核心概念,它代表一组操作的集合,这些操作要么全部执行成功,要么全部不执行,即操作数据的最小执行单元,保证数据库的…...
C语言_函数调用栈的汇编分析
在 C 语言的底层实现中,函数调用栈是程序运行时内存管理的核心机制。它不仅负责函数间的控制转移,还管理局部变量、参数传递和返回值。本文将结合 C 语言代码和 x86-64 汇编指令,深入解析函数调用栈的工作原理。 一、函数调用栈的基本概念 …...
单片机调用printf概率性跑飞解决方法
最近移植软件到不同平台的单片机上时,遇到了软件概率性跑飞的问题,分析后原因均指向和printf相关的库函数(包括sprintf, vsnsprinft),在任务里调用这些函数就有概率在ucos切换任务时跑飞(中断)。…...
无人机空中物流优化:用 Python 打造高效配送模型
友友们好! 我是Echo_Wish,我的的新专栏《Python进阶》以及《Python!实战!》正式启动啦!这是专为那些渴望提升Python技能的朋友们量身打造的专栏,无论你是已经有一定基础的开发者,还是希望深入挖掘Python潜力的爱好者,这里都将是你不可错过的宝藏。 在这个专栏中,你将会…...
【RP2350】香瓜树莓派RP2350之低功耗
本文最后修改时间:2025年05月10日 01:57 一、本节简介 本节以树莓派pico2开发板为例,举例如何写一个低功耗驱动。 二、实验平台 1、硬件平台 1)树莓派pico2开发板 ①树莓派pico2开发板(作为仿真器) ②micro usb数…...
招行数字金融挑战赛数据赛道赛题一
赛题描述:根据提供的用户行为数据,选手需要分析用户行为特征与广告内容的匹配关系,准确预测用户对测试集广告的点击情况,通过AUC计算得分。 得分0.6120,排名60。 尝试了很多模型都没有能够提升效果,好奇大…...
仿真生成激光干涉包裹相位数据-用于深度学习训练!
该MATLAB/Octave代码实现了论文[1]中提出的相位提取算法,用于从灰度条纹图案中提取包裹相位图(相位值在-π到+π之间)。代码首先生成模拟的条纹图案,包含背景光、调制光和相位分布,并加入高斯噪声。随后,通过N步相移算法估计背景光和调制光,并计算包裹相位。结果显示包括…...
命令行解释器中shell、bash和zsh的区别
命令行解释器(Command Line Interpreter)是一个程序,它的主要作用是接收用户输入的命令,并执行相应的操作。它充当了用户与操作系统内核之间的桥梁。 一、什么是 Shell? Shell 是一个通用术语,指的是 命令…...