- 作者: Liwx
- 邮箱: 1032282633@qq.com
- 源码: 需要
源码的同学, 可以在评论区留下您的邮箱
iOS Swift 语法
底层原理与内存管理分析 专题:【iOS Swift5语法】00 - 汇编
01 - 基础语法
02 - 流程控制
03 - 函数
04 - 枚举
05 - 可选项
06 - 结构体和类
07 - 闭包
08 - 属性
09 - 方法
10 - 下标
11 - 继承
12 - 初始化器init
13 - 可选项
目录
- 01-程序的本质
- 01-软件/程序执行过程
- 02-寄存器和内存
- 03-编程语言的发展
- 04-编程语言的发展
- 05-汇编语言的种类
- 06-常用汇编指令
- 07-寄存器
- 08-寄存器兼容
- 09-lldb常用指令
- 10-lldb常用指令(断点调试)
- 11-规律
01-程序的本质
Xcode调试中
显示汇编代码:Debug -> Debug Workflow -> Always Show Disassembly
01-软件/程序执行过程
- 程序运行时,
程序/软件是存储在硬盘中,当程序开始执行是,从硬盘装载到内存,CPU再对内存进行读写,并控制
,话筒等其他设备. - CPU中包含几个部分,其中包含
寄存器(信息存储),运算器(信息处理),控制器.
02-寄存器和内存
- 通常CPU会先将
内存中的数据存储到寄存器中,然后再对寄存器的数据进行运算 - 假设内存中有块内存空间1的值是3,现在想将它的值加1,并将结果存储到内存空间2
- CPU首先会将内存空间1的值放到rax寄存器中:
movq 内存空间1 %rax - 然后让rax寄存器与1相加:
addq $0x1 %rax - 最后将值赋值给内存空间2:
movq %rax 内存空间2
03-编程语言的发展
- 机器语言
- 由
0和1组成 - 汇编语言
- 用
符号代替了0和1,比机器语言更便于阅读和记忆 - 高级语言
- C/C++/Java/JavaScript/Python等,更接近人类自然语言
- 操作: 将寄存器BX内容送入寄存器AX
- 机器语言:
1000100111011000 - 汇编语言:
movw %bx %ax - 高级语言:
ax = bx
04-编程语言的发展
- 高级语言
编译-> 汇编语言 编译-> 机器语言 运行-> 计算机 - 反编译:
机器语言 反编译-> 汇编语言 - 汇编语言与机器语言一对应 ,每一条机器指令都有与之对应的汇编指令
-
汇编语言可以通过编译得到机器语言,机器语言可以通过反汇编得到汇编语言 -
高级语言可以通过编译得到汇编语言\机器语言,但汇编语言机器语言几乎不可能还原成高级语言
05-汇编语言的种类
- 汇编语言的种类
- 8086汇编(16bit)
- x86汇编(32bit)
- x64汇编(64bit)
- ARM汇编(嵌入式、移动设备)
- ......
-
x86、x64汇编根据编译器的不同,有2种书写格式 -
Intel: Windows派系 -
AT&T: Unix派系. - 作为iOS开发工程师,最主要的汇编语言是
-
AT&T汇编->iOS模拟器 -
ARM汇编->iOS真机设备
06-常用汇编指令
注意:
小括号()通常表示存放内存地址。
在AT&T指令中
$是立即数的前称。
| 项目 | AT&T | Intel | 说明 |
|---|---|---|---|
| 寄存器名称 | %rax | rax | |
| 操作数顺序 | movq %rax, %rdx | mov rdx, rax | 将rax的值赋值给rdx |
| 常数/立即数 | movq $0x3, %rax | mov rax, 0x3 | 将3赋值给rax |
| 内存赋值 | movq $0xa, 0x1ff7(%rip) | mov qword ptr [rip+0x1ff7], 0xa | 将0xa赋值给地址为rip+0x1ff7的内存空间 |
| 取内存地址 | leaq -0x18(%rbp), %rax | lea rax, [rbp-0x18] | 将rbp-0x18这个地址值赋值给rax |
| jmp跳转指令 | jmp *%rdx 或 jmp 0x4001002 或 jmp *(%rax) | jmp rdx 或 jmp 0x4001002 或 je=mp [rax] | call和jmp写法类似 |
| 操作数长度 | movl %eax, %edx 或 movb $0x10, %al 或 leaw 0x10(%dx), %ax | mov edx, eax 或 mob al, 0x10 或 lea ax, [dx+0x10] | 参考操作数长度说明 |
- 操作数长度说明
b= byte(8-bit)s= short(16-bit integer or 32-bit floating point)w= word(16-bit)l= long(32-bit integer or 63-bit floating pointq= quad(64-bit))t= ten bytes(80-bit floating point)
07-寄存器
-
有16个常用寄存器
- rax、rbx、 rcx、 rdx、 rsi、 rdi、 rbp、 rsp
- r8、r9、 r10、 r11、r12、 r13、 r14、
r15
-
寄存器的具体用途
-rax、rdx常作为函数返回值使用-
rdi、rsi、rdx、rcx、r8、r9等寄存器常用于存放函数参数 -
rsp、rbp用于栈操作 -
rip作为指令指针- 存储着CPU
下一条要执行的指令的地址 - 一旦CPU读取一条指令,
rip会自动指向下一 条指令(存储下一条指令的地址)
- 存储着CPU
-
08-寄存器兼容
为兼容不同位数, 取
64位rax寄存器低32位作为eax寄存器使用,低16位作为ax寄存器使用,ah作为高8位使用,al作为低8位使用
- 寄存器说明
r开头:64-bite开头:32-bita, b, c, d开头:16-bitah, al, bh, bl...l和h结尾:8-bit,h: 高八位,l: 低八位

image.png
09-lldb常用指令
-
格式
-
x是16进制,f是浮点,d是十进制
-
-
字节大小
-
b- byte 1字节 -
h- half word 2字节 -
w- word 4字节 -
g- giant word 8字节
-
- 读取寄存器的值
register read/格式 寄存器名称register read/x
// 读取rax寄存器的值
(lldb) register read rax
rax = 0x0000000100709e40
// 读取rax寄存器的值
(lldb) register read/x rax
rax = 0x0000000100709e40
// 读取所有寄存器的值
(lldb) register read
General Purpose Registers:
rax = 0x0000000100709e40
rbx = 0x0000000000000000
rcx = 0x00007fff81c908f8 libswiftCore.dylib`type metadata for Swift.Int
rdx = 0x0000000100709e60
rdi = 0x0000000100709e48
rsi = 0x00007fff81c96588 libswiftCore.dylib`type metadata for Any + 8
rbp = 0x00007ffeefbff4d0
rsp = 0x00007ffeefbff4b0
r8 = 0x00000000000005dd
r9 = 0x00000000000005e2
r10 = 0x00000000fffffffc
r11 = 0x0000000000000000
r12 = 0x0000000000000000
r13 = 0x0000000000000000
r14 = 0x0000000000000000
r15 = 0x0000000000000000
rip = 0x0000000100000bd2 00-汇编`_0_汇编.test() -> () + 50 at main.swift:13:14
rflags = 0x0000000000000206
cs = 0x000000000000002b
fs = 0x0000000000000000
gs = 0x0000000000000000
- 读取内存中的值
x/数量-格式-字节大小 内存地址-
x/3gw0x0000010
(lldb) x/3xg 0x00007fff81c908f8
0x7fff81c908f8: 0x0000000000000200 0x00007fff683e58ec
0x7fff81c90908: 0x0000000000000000
- 修改内存中的值
- memory write 内存地址 数值
- memory write 0x0000010 10
lldb) memory write 0x00007fff81c908f8 0x10
(lldb) x/xg 0x00007fff81c908f8
0x7fff81c908f8: 0x0000000000000210
(lldb) memory write 0x00007fff81c908f8 0x20
(lldb) x/xg 0x00007fff81c908f8
0x7fff81c908f8: 0x0000000000000220
-
expression表达式- 可以简写:
expr高级语言表达式 - expression $rax // 验证不通过
- expression $rax = 1 // 验证不通过
- expr unsigned int $foo = 5
- 可以简写:
-
po表达式- print 表达式
- po/x $rax // 验证不通过
- po (int)$rax // 验证不通过
10-lldb常用指令(断点调试)
- thread step-over、 next、
n- 单步运行,把子函数当做整体-步执行(
源码级别)
- 单步运行,把子函数当做整体-步执行(
- thread step-in、step、
s- 单步运行,遇到子函数会进入子函数(
源码级别)
- 单步运行,遇到子函数会进入子函数(
- thread step inst over、 nexti、
ni- 单步运行,把子函数当做整体-步执行 (
汇编级别)
- 单步运行,把子函数当做整体-步执行 (
- thread step-inst、 stepi、
si- 单步运行,遇到子函数会进入子函数(
汇编级别)
- 单步运行,遇到子函数会进入子函数(
- thread step-out、
finish-
直接执行完当前函数的所有代码,返回到上一个函数(遇到断点会卡住)
-
11-规律
- 内存地址格式为:
0x4bdc(%rip),一般是全局变量 ,全局区(数据段) - 内存地址格式为:
-0x78(%rbp), 一般是局部变量,栈空间 - 内存地址格式为:
0x10(%rax), 一般是堆空间
iOS Swift 语法
底层原理与内存管理分析 专题:【iOS Swift5语法】下一篇: 01 - 基础语法