- 作者: 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/3gw
0x0000010
(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 - 基礎語法