| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 移动开发 -> 汇编分析Swift中的String -> 正文阅读 |
|
[移动开发]汇编分析Swift中的String |
?关于String的思考?1、1个String变量占用多少内存? 2、下面2个String变量,底层存储有什么不同?
意思就是这两个字符串在内存中分别是存储在哪个区域的。
3、如果对String进行拼接操作,String变量的存储会发生什么变化?
4、ASCII码表:https://www.ascii-code.com/ 汇编分析String? str1最少是有16个字节的,从8、9行就可以看出,通过MemoryLayout.stride()打印也可以看出来。 在第10行处打断点,进行打印可以获取str1变量16个字节存储的东西:
rip的地址加上0x409f,也就是0x100003f71 +??0x409f =?0x100008010,这个就是str1的内存地址,通过以下命令可以获取该地址存储的内容:
发现和上面打印出来的内容是相同的,所以我们从各个方面证明了str1变量存储的内容就是?0x3736353433323130 0xea00000000003938,占16个字节。 ? 以上是ASCII码值表,0对应16进制是0x30,1对应0x31,对应着看str1存储的内容,可以发现是从30一直到39的,相当于字符串的内容就直接放到了str1的内存当中了。 我们换种打印方式可以看的更加清晰:
?0xea又代表什么内容呢? 我们把9删掉:
根据同样的方式获取到str1存储的内容:
可以发现0xea变成了0xe9,所以a\9这一位是用来存储字符串长度的,0xe表示的是字符串的存储方式,a\9这一位最大是f,f的时候就是刚刚好填满15个字节,也就是最多存储15个字符。 我们可以来测试一下:
?再看一下ASCII码表: 发现确实是和我们的结论一致的。 小于等于15位的时候,是直接存储在字符串变量的内存中的,类似于OC的tagger pointer。 如果再多一位会发生什么事情呢?
我们可以再次尝试,从而找到规律:
两次存储内容可以对比一下,其实变化很小,也可以间接证明,字符串内容不是存储在这16个字节里面的。 那到底存储在什么地方呢??我们再来分析汇编: ? ? ?rax和rdx是str2存储内容,rax和rdx是callq返回的内容,超过八个字节放到rdx里面,我们可以跟进callq方法里面去看一下做了哪些事情。 通过si我们可以进到Swift.String.init方法里面,第12行cmpq ? $0xf, %rsi,就是将rsi和15进行比较,rsi就是要初始化的字符串的长度,第13行jle? ? 0x7ff825d89c47,是根据比较结果进行跳转,如果小于就跳转到别的方法,其他情况就继续往下走。 第20行movabsq $0x7fffffffffffffe0, %rdx,将0x7fffffffffffffe0放到rdx中,第21行addq ? %rdx, %rdi,rdi就是字符串的真实地址,rdi加上rdx的值再放到rdx中。 现在str2中的16个字节存储的是:
字符串的真正内容是和0x8000000100003f60这8个字节相关的,通过汇编代码我们可以知道, 字符串的真实地址 +?0x7fffffffffffffe0 =?0x8000000100003f60,那么可以推导出 字符串的真实地址 =?0x8000000100003f60 -?0x7fffffffffffffe0。 经过计算0x100003F80就是字符串的真实地址。我们打印一下这个地址存储的内容:
发现确实是字符串的内容。 rsi和rdi是如何确定是位数和真实地址的?再来一次汇编: ? 第5行leaq ? 0x1f1(%rip), %rdi,将0x1f1(%rip)地址值赋值给rdi,可以通过注释看出0x1f1(%rip)地址值就是字符串的真实地址值,rip +?0x1f1 =?0x100003d8f +?0x1f1 =?0x100003F80,所以现在rdi就存放这字符串的真实地址,第6行movl ? $0x10, %esi,%esi就是%rsi,存放的就是字符串的长度0x10,也就是16,接下来就是第8行的callq? 0x100003f06,调用String.init方法,rdi和rsi就是这个方法的参数。 ?第20行movabsq $0x7fffffffffffffe0, %rdx,将0x7fffffffffffffe0放到rdx中,第21行addq ? %rdx, %rdi,rdi就是字符串的真实地址,rdi加上rdx的值再放到rdx中。 所以一旦字符串的内容长度超过15,就不会将字符串的内容存储在字符串变量的16个字节里面,而是放到其他地方,然后将地址值存起来,最终我们可以根据地址值找到字符串的真实内容。 那么字符串内容的真实地址值是在内存哪块区域呢?我们可以再看一下这里的汇编代码,0x1f1(%rip)就是真实地址值,一般这样的就是在全局区,所以是有可能在全局区内存里面的,先算出真实地址值0x1f1 +?0x100003d8f =??0x100003F80。 从编码到启动APPOC、Swift源码 -----(编译、链接)-----> Mach-O可执行文件 ------(启动)------> 内存 (内存地址从低到高,Mach-O、动态库) 代码区、全局区、常量区全部都在Mach-O里面。一般编译后的可执行文件载入内存后都会有一个偏移量,但是Mach-O文件的偏移量可以忽略,我们可以直接看Mach-O文件,看看字符串是在内存中的哪个区域。 Mach-O格式的可执行文件。 用MachOView打开Mach-O文件: 如果00 00 00 00 00 00 00 00这8个字节在Mach-O里面是00008030的偏移量,那么他在内存中的地址就是0x100000000 +??0x8030,这个就是VM Address,虚拟内存地址。 我们想找0x100003F80,实际上在Mach-O里面就是00003F80。 可以在cstring里面找到,这里就是常量区,_TEXT整个可以叫代码区,__cstring就是常量区。 如果找不到products文件夹可以通过这个方式查找:Xcode13 新建项目 Products 目录显示方法_蓝清水的博客-CSDN博客 超过15长度的字符串变量前8个字节表示什么:
我们可以多写一些内容看一下:?
?可以看出rax表示的是字符串的长度。 思考题,拼接后内存会有什么变化呢?
我们可以用汇编看一下 看str1拼接前后的变化,
?append后长度不超过15就还在16个字节内存储字符串内容,超过后需要开辟新的内存,并且是动态变化的。 我们看下str2的情况: 开辟堆空间的话最终都会调用malloc方法, 刚开始是放在常量区,常量区是不能进行修改的,所以append需要另外在堆空间开辟内存,堆空间地址值在str2变量的后8个字节,堆空间中的内存前32个字节是存放和对象相关的内容,之后就是字符串的真实内容了。 总结:字符串初始化时长度小于等于15的,字符串内容直接存放在str变量的内存中; 字符串初始化时长度大于15的,字符串内容存放在__TEXT, __cstring中(常量区),字符串的地址值信息存放在str变量的后8个字节中,但是需要通过计算才能得出真实的地址值; append后如果字符串长度小于等于15,字符串内容依然存放在str变量内存中; ?append后如果字符串长度大于15,会开辟堆空间,因为常量区是不可以进行更改的。 dyld_stub_binder1、符号的延迟绑定通过dyld_stub_binder完成,callq指令只是调用的占位的地址,最终会通过符号绑定找到动态库里面的地址调用; 2、jmpq *0xb31(%rip)格式的汇编指令 ? ? ? ? 占用6个字节 |
|
移动开发 最新文章 |
Vue3装载axios和element-ui |
android adb cmd |
【xcode】Xcode常用快捷键与技巧 |
Android开发中的线程池使用 |
Java 和 Android 的 Base64 |
Android 测试文字编码格式 |
微信小程序支付 |
安卓权限记录 |
知乎之自动养号 |
【Android Jetpack】DataStore |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/25 4:27:12- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |