Swift5.x入门15--汇编分析String与Array

首先定义一个字符串,如下所示:

var str1 = "0123456789"
print(MemoryLayout.stride(ofValue: str1)) //16
  • 易知str1字符串在内存中占用16个字节;
  • 下断点,进入汇编代码:
Snip20210803_111.png
  • movq %rax, 0x40ac(%rip)movq %rdx, 0x40ad(%rip)是分别向字符串变量str1的前后8个字节分别写入rax与rdx寄存器中的内容,刚好16个字节的内容;
  • 0x40ac(%rip)是字符串变量str1的首地址 = (rip+ 0x40ac)= (0x100003f64+ 0x40ac)=0x100008010
  • x/4gx 0x100008010 就是读取字符串中内容,发现与寄存器写入字符串变量str1内存地址中的内容完全相同;
  • 0x3736353433323130 0xea00000000003938,由ASCII表可知
    30代表1,31代表2,以此类推,如下所示:
    Snip20210803_112.png
  • 每一个字节存储一个字符串字符,至于最后一个字节中存储的是ea,其中a表示字符串的长度为10,e表示字符串类型 ,此类型为将字符串内存存储在字符串变量的内存地址中;
  • 为了验证上面的结论,将str1 = "0123456789ABCDE",然后汇编分析如下:
Snip20210803_113.png
  • 结果与上面的类似,最后一个字节内容ef,其中f表示字符串长度为15,因为字符串本身只占16个字节,最后一个字节用来存储字符串的长度与类型信息,所以此种类型的字符串最大长度为15个字符,超过15个字符,其类型就会发生变化了;

现将str1 = "0123456789ABCDEFGHJKL",长度超过15个字符;汇编分析如下:

Snip20210803_117.png
  • leaq 0x61(%rip), %raxmovq %rax, %rdi :将字符串0123456789ABCDEFGHJKL的内存地址写入rax寄存器,然后再写入rdi寄存器;
  • movl $0x15, %eaxmovq %rax, %rsi:将字符串的长度21写入eax(rdx)寄存器,然后再写入rsi寄存器;
  • rdi与rsi中的内容分别为字符串的内存地址和字符串的长度;
  • callq 0x100003f64,调用初始化字符串的函数,传入上述的两个参数;
  • 进入到初始化字符串的函数的汇编实现:
Snip20210803_119.png
  • cmpq $0xf, %rsi:将字符串的长度与立即数15进行比较,然后执行不同的逻辑,这也就证明了字符串长度是否大于15,其在内存中分配方式是不同的;
  • movabsq $0x7fffffffffffffe0, %rdx:将0x7fffffffffffffe0写入rdx寄存器;
  • addq %rdx, %rdi:rdx = rdx + rdi = 0x7fffffffffffffe0+字符串的内存地址;
  • 字符串初始化函数执行完成之后:
  • 执行movq %rdx, 0x40bd(%rip)即将(0x7fffffffffffffe0+字符串的内存地址)存入字符串内存地址的后8个字节中;即0x7fffffffffffffe0+字符串的内存地址 = 0x8000000100003f70,所以
    字符串的内存地址 = 0x8000000100003f70 - 0x7fffffffffffffe0 = 0x100003F90,这与上面的LLDB调试的字符串的内存地址完全吻合;
  • 字符串内存地址前8个字节的内容为0xd000000000000015,其实存储的是字符串的长度为21;

总结:

Snip20210803_121.png
  • 当字符串的长度小于等于15时,字符串内容直接存放在字符串变量的内存地址中;
  • 当字符串的长度大于15时,字符串内容存放在__TEXT.cstring中,即常量区中;字符串的地址值信息存放在字符串变量的后8个字节中,前8个字节存放字符串的长度信息;

str1.append("G") 字符串拼接操作

  • 当字符串的长度小于等于15时,进行字符串拼接操作后,若字符串的长度依然小于等于15时,字符串内容直接依然存放在字符串变量的内存地址中;
  • 当字符串的长度小于等于15时,进行字符串拼接操作后,若字符串的长度大于15时,会开辟堆空间;
  • 当字符串的长度大于15时,进行字符串拼接操作后,会开辟堆空间;
  • append函数,开辟堆空间,实例化创建拼接后的字符串,然后将拼接后的字符串的堆内存地址,存放入字符串变量的后8个字节中,前8个字节存放字符串的长度信息;

dyld_stub_binder

  • 符号的延迟绑定是通过dyld_stub_binder完成;

Array数组

var arr = [1,2,3,4]
print(MemoryLayout.stride(ofValue: arr)) //8
  • arr变量占用8个字节,但数组中存放了4个Int数据,至少占32个字节,所以可大胆猜测, arr变量的内存地址中存放着数组的地址信息;
  • 首先来获取 arr变量的内存地址,如下所示:
Snip20210803_123.png
  • 0x100008058就是arr变量的内存地址;
  • 0x000000010065a2f0是数组对象的真实内存地址;
  • 总结如下:
Snip20210803_124.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,544评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,430评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,764评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,193评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,216评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,182评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,063评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,917评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,329评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,543评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,722评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,425评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,019评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,671评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,825评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,729评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,614评论 2 353

推荐阅读更多精彩内容