swift开发知识收集

汇编窥探Swift底层(五):字符串

2020-02-29  本文已影响0人  冰风v落叶

窥探字符串的内存

var str1 = "0123456789"
print(MemoryLayout.stride(ofValue: str1)) 打印出来是16个字节,也就是说str1占用了16字节
TestSwift`main:
    0x100001390 <+0>:  pushq  %rbp
    0x100001391 <+1>:  movq   %rsp, %rbp
    0x100001394 <+4>:  subq   $0x10, %rsp
->  0x100001398 <+8>:  leaq   0x4361(%rip), %rax        ; "0123456789"
    0x10000139f <+15>: movl   %edi, -0x4(%rbp)
    0x1000013a2 <+18>: movq   %rax, %rdi
    0x1000013a5 <+21>: movl   $0xa, %eax
    0x1000013aa <+26>: movq   %rsi, -0x10(%rbp)
    0x1000013ae <+30>: movq   %rax, %rsi
    0x1000013b1 <+33>: movl   $0x1, %edx
    0x1000013b6 <+38>: callq  0x100005402               ; symbol stub for: Swift.String.init(_builtinStringLiteral: Builtin.RawPointer, utf8CodeUnitCount: Builtin.Word, isASCII: Builtin.Int1) -> Swift.String
    0x1000013bb <+43>: xorl   %ecx, %ecx
    0x1000013bd <+45>: movq   %rax, 0x5e24(%rip)        ; TestSwift.str1 : Swift.String
    0x1000013c4 <+52>: movq   %rdx, 0x5e25(%rip)        ; TestSwift.str1 : Swift.String + 8
    0x1000013cb <+59>: movl   %ecx, %eax
    0x1000013cd <+61>: addq   $0x10, %rsp
    0x1000013d1 <+65>: popq   %rbp
    0x1000013d2 <+66>: retq   

0x1000013bd <+45>: movq   %rax, 0x5e24(%rip)        ; TestSwift.str1 : Swift.String
0x1000013c4 <+52>: movq   %rdx, 0x5e25(%rip)        ; TestSwift.str1 : Swift.String + 8
(lldb) x/2xg 0x1000071E8
0x1000071e8: 0x3736353433323130 0xea00000000003938

上面是小端模式读取的,不好看,现在用另一种模式读取,就很容易看出来
(lldb) x 0x1000071E8
0x1000071e8: 30 31 32 33 34 35 36 37 38 39 00 00 00 00 00 ea  0123456789......
0x1000071f8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................

var str1 = "0123456789"时,      str1的内存是:0x3736353433323130 0xea00000000003938

var str1 = "0123456789A"时,     str1的内存是:0x3736353433323130 0xeb00000000413938

var str1 = "0123456789AB"时,    str1的内存是:0x3736353433323130 0xec00000042413938

var str1 = "0123456789ABC"时,   str1的内存是:0x3736353433323130 0xed00004342413938

var str1 = "0123456789ABCD"时,  str1的内存是:0x3736353433323130 0xee00444342413938

var str1 = "0123456789ABCDE"时, str1的内存是:0x3736353433323130 0xef45444342413938

var str1 = "0123456789ABCDEF"时,str1的内存是:0xd000000000000010 0x80000001000056d0
TestSwift`main:
    0x100001380 <+0>:  pushq  %rbp
    0x100001381 <+1>:  movq   %rsp, %rbp
    0x100001384 <+4>:  subq   $0x10, %rsp
->  0x100001388 <+8>:  leaq   0x4361(%rip), %rax        ; "0123456789ABCDEF"
    0x10000138f <+15>: movl   %edi, -0x4(%rbp)
    0x100001392 <+18>: movq   %rax, %rdi
    0x100001395 <+21>: movl   $0x10, %eax
    0x10000139a <+26>: movq   %rsi, -0x10(%rbp)
    0x10000139e <+30>: movq   %rax, %rsi
    0x1000013a1 <+33>: movl   $0x1, %edx
    0x1000013a6 <+38>: callq  0x1000053f2               ; symbol stub for: Swift.String.init(_builtinStringLiteral: Builtin.RawPointer, utf8CodeUnitCount: Builtin.Word, isASCII: Builtin.Int1) -> Swift.String
    0x1000013ab <+43>: xorl   %ecx, %ecx
    0x1000013ad <+45>: movq   %rax, 0x5e34(%rip)        ; TestSwift.str1 : Swift.String
    0x1000013b4 <+52>: movq   %rdx, 0x5e35(%rip)        ; TestSwift.str1 : Swift.String + 8
    0x1000013bb <+59>: movl   %ecx, %eax
    0x1000013bd <+61>: addq   $0x10, %rsp
    0x1000013c1 <+65>: popq   %rbp
    0x1000013c2 <+66>: retq   

    leaq指令是直接赋值地址,从注释可以看出来是把"0123456789ABCDEF"的真实地址给了rax寄存器
    通过rip+0x4361,可以算出字符串的真实地址是:0x1000056F0
    0x100001388 <+8>:  leaq   0x4361(%rip), %rax        ; "0123456789ABCDEF"

    又把rax寄存器的值给了rdi寄存器,也就是说rdi寄存器里存放着字符串的真实地址
    0x100001392 <+18>: movq   %rax, %rdi

    把0x10给了eax寄存器,eax寄存器就是rax寄存器,也就是说rax寄存器里存储着字符串的长度(十六进制0x10就是十进制的16)
    0x100001395 <+21>: movl   $0x10, %eax

    又把rax寄存器的值给了rsi寄存器,也就是说rsi寄存器里的值就是字符串的长度
    0x10000139e <+30>: movq   %rax, %rsi

    调用了函数String.init(),把rdi寄存器和rsi寄存器作为了参数,也就说把字符串的真实地址和字符串长度作为参数,调用了String.init()
    0x1000013a6 <+38>: callq  0x1000053f2               ; symbol stub for: Swift.String.init(_builtinStringLiteral: Builtin.RawPointer, utf8CodeUnitCount: Builtin.Word, isASCII: Builtin.Int1) -> Swift.String

    把rax寄存器的值给了str1变量的前8个字节
    0x1000013ad <+45>: movq   %rax, 0x5e34(%rip)        ; TestSwift.str1 : Swift.String

    把rdx寄存器的值给了str1变量的后8个字节
    0x1000013b4 <+52>: movq   %rdx, 0x5e35(%rip)        ; TestSwift.str1 : Swift.String + 8
 
libswiftCore.dylib`Swift.String.init(_builtinStringLiteral: Builtin.RawPointer, utf8CodeUnitCount: Builtin.Word, isASCII: Builtin.Int1) -> Swift.String:
->  0x7fff722e9c40 <+0>:   pushq  %rbp
    0x7fff722e9c41 <+1>:   movq   %rsp, %rbp
    0x7fff722e9c44 <+4>:   pushq  %r14
    0x7fff722e9c46 <+6>:   pushq  %rbx
    0x7fff722e9c47 <+7>:   subq   $0x10, %rsp
    0x7fff722e9c4b <+11>:  testq  %rsi, %rsi
    0x7fff722e9c4e <+14>:  js     0x7fff722e9e31            ; <+497>
    0x7fff722e9c54 <+20>:  movl   %edx, %eax
    0x7fff722e9c56 <+22>:  movabsq $-0x2000000000000000, %rdx ; imm = 0xE000000000000000 
    0x7fff722e9c60 <+32>:  testq  %rsi, %rsi
    0x7fff722e9c63 <+35>:  je     0x7fff722e9ca4            ; <+100>
    0x7fff722e9c65 <+37>:  cmpq   $0xf, %rsi
    0x7fff722e9c69 <+41>:  jle    0x7fff722e9cab            ; <+107>
    0x7fff722e9c6b <+43>:  movabsq $-0x4000000000000000, %rcx ; imm = 0xC000000000000000 
    0x7fff722e9c75 <+53>:  orq    %rsi, %rcx
    0x7fff722e9c78 <+56>:  testb  $0x1, %al
    0x7fff722e9c7a <+58>:  cmoveq %rsi, %rcx
    0x7fff722e9c7e <+62>:  movabsq $0x1000000000000000, %rax ; imm = 0x1000000000000000 
    0x7fff722e9c88 <+72>:  orq    %rcx, %rax
    0x7fff722e9c8b <+75>:  movabsq $0x7fffffffffffffe0, %rdx ; imm = 0x7FFFFFFFFFFFFFE0 
    0x7fff722e9c95 <+85>:  addq   %rdx, %rdi
    0x7fff722e9c98 <+88>:  addq   $0x20, %rdx
    比较0xf与rsi寄存器值的大小,前面说过rsi寄存器中存放着字符串的长度
    0x7fff722e9c65 <+37>:  cmpq   $0xf, %rsi

    将立即数$0x7fffffffffffffe0放到rdx寄存器中
    0x7fff722e9c8b <+75>:  movabsq $0x7fffffffffffffe0, %rdx ; imm = 0x7FFFFFFFFFFFFFE0 

    将rdx寄存器中的值与rdi寄存器相加,并且放到rdx寄存器中,前面说过rdi寄存器放着字符串的真实地址  
    所以现在rdx寄存器中放着字符串的真实地址+$0x7fffffffffffffe0
    0x7fff722e9c95 <+85>:  addq   %rdx, %rdi
   通过rip+0x4361,可以算出字符串的真实地址是:0x1000056F0
   0x100001388 <+8>:  leaq   0x4361(%rip), %rax        ; "0123456789ABCDEF"

   也可以通过str1后8个字节的数据  - 0x7fffffffffffffe0 算出来,字符串的真实地址是0x1000056F0
   var str1 = "0123456789ABCDEF"时,str1的内存是:0xd000000000000010 0x80000001000056d0
var str1 = "0123456789ABCDEF"
str1.append("G")
TestSwift`main:
    0x100001300 <+0>:   pushq  %rbp
    0x100001301 <+1>:   movq   %rsp, %rbp
    0x100001304 <+4>:   pushq  %r13
    0x100001306 <+6>:   subq   $0x38, %rsp
->  0x10000130a <+10>:  leaq   0x43df(%rip), %rax        ; "0123456789ABCDEF"
    0x100001311 <+17>:  movl   %edi, -0x24(%rbp)
    0x100001314 <+20>:  movq   %rax, %rdi
    0x100001317 <+23>:  movl   $0x10, %eax
    0x10000131c <+28>:  movq   %rsi, -0x30(%rbp)
    0x100001320 <+32>:  movq   %rax, %rsi
    0x100001323 <+35>:  movl   $0x1, %edx
    0x100001328 <+40>:  callq  0x1000053d2               ; symbol stub for: Swift.String.init(_builtinStringLiteral: Builtin.RawPointer, utf8CodeUnitCount: Builtin.Word, isASCII: Builtin.Int1) -> Swift.String
    0x10000132d <+45>:  movq   %rax, 0x5ec4(%rip)        ; TestSwift.str1 : Swift.String
    0x100001334 <+52>:  movq   %rdx, 0x5ec5(%rip)        ; TestSwift.str1 : Swift.String + 8
    0x10000133b <+59>:  leaq   0x43bf(%rip), %rdi        ; "'G'"
    0x100001342 <+66>:  movl   $0x1, %esi
    0x100001347 <+71>:  movl   $0x1, %edx
    0x10000134c <+76>:  callq  0x1000053d2               ; symbol stub for: Swift.String.init(_builtinStringLiteral: Builtin.RawPointer, utf8CodeUnitCount: Builtin.Word, isASCII: Builtin.Int1) -> Swift.String
    0x100001351 <+81>:  leaq   0x5ea0(%rip), %rsi        ; TestEnumMemory.str1 : Swift.String
    0x100001358 <+88>:  xorl   %ecx, %ecx
    0x10000135a <+90>:  movq   %rsi, %rdi
    0x10000135d <+93>:  leaq   -0x20(%rbp), %rsi
    0x100001361 <+97>:  movl   $0x21, %r8d
    0x100001367 <+103>: movq   %rdx, -0x38(%rbp)
    0x10000136b <+107>: movq   %r8, %rdx
    0x10000136e <+110>: movq   %rax, -0x40(%rbp)
    0x100001372 <+114>: callq  0x10000547a               ; symbol stub for: swift_beginAccess
    0x100001377 <+119>: movq   -0x40(%rbp), %rdi
    0x10000137b <+123>: movq   -0x38(%rbp), %rsi
    0x10000137f <+127>: leaq   0x5e72(%rip), %r13        ; TestSwift.str1 : Swift.String
    0x100001386 <+134>: callq  0x1000053d8               ; symbol stub for: Swift.String.append(Swift.String) -> ()
    0x10000138b <+139>: leaq   -0x20(%rbp), %rdi
    0x10000138f <+143>: callq  0x100005498               ; symbol stub for: swift_endAccess
    0x100001394 <+148>: movq   -0x38(%rbp), %rdi
    0x100001398 <+152>: callq  0x100005480               ; symbol stub for: swift_bridgeObjectRelease
    0x10000139d <+157>: xorl   %eax, %eax
    0x10000139f <+159>: addq   $0x38, %rsp
    0x1000013a3 <+163>: popq   %r13
    0x1000013a5 <+165>: popq   %rbp
    0x1000013a6 <+166>: retq   
str1变量的地址从0x00000001000071f8开始的
(lldb) register read r13
r13 = 0x00000001000071f8  TestEnumMemory`TestEnumMemory.str1 : Swift.String

从0x00000001000071f8开始,读取16个字节
(lldb) x/2xg  0x00000001000071f8
0x1000071f8: 0xf000000000000011 0x000000010070ac40

读取 str1变量的后8个字节
(lldb) x/10xg 0x000000010070ac40
0x10070ac40: 0x00007fff9cc0fca8 0x0000000000000002
0x10070ac50: 0x0000000000000018 0xf000000000000011
0x10070ac60: 0x3736353433323130 0x4645444342413938
0x10070ac70: 0x00007fff93e30047 0x0000000000000000
0x10070ac80: 0x0000000000000000 0x0000000000000000
上一篇下一篇

猜你喜欢

热点阅读