彙編高手帶你玩轉字串,快上車!

2021-09-29 11:44:18 字數 3532 閱讀 5690

字串(string)是由數字、字母、下劃線組成的一串字元,一般記為 s=「a1a2···an」(n>=0)。字串主要用於程式設計,概念說明、函式解釋,它是程式語言中表示文字的資料型別。在程式設計中,字串(string)為符號或數值的乙個連續序列,如符號串(一串字元)或二進位制數字串(一串二進位制數字)。

一、思考

在 swift 開發使用字串的過程中,你是否有思考過以下問題?

- 1 個字串變數占用多少記憶體?

- 字串 str1、str2 的底層儲存有什麼不同?

- 如果對 str1、str2 進行拼接操作,str1、str2 的底層儲存又會發生什麼變化?

如果你能準確地回答以上問題,那說明對 swift 字串的底層儲存機制還是比較了解的。

二、1 個字串變數占用多少記憶體?

方法 1:memorylayout

首先,可以借助 swift 自帶的 memorylayout 來測試一下

方法 2:彙編

另外,我們也可以借助乙個強有力的底層分析助手—組合語言,來窺探一下 string 的底層儲存

- 實際上分析其他語法、系統庫的底層,都可以借助組合語言

- 比如多型的原理、泛型的原理、array 的底層、列舉的底層等等

-另外,不僅僅是 swift,c、c++、oc 的底層分析,依然可以借助組合語言

- 畢竟你寫的每一行有效**,最終都是要轉成機器指令(0 和 1)

- 而機器指令是跟彙編指令一一對應的,每一條機器指令都能翻譯成與之對應的彙編指令

- 能讀懂彙編指令,就相當於能讀懂機器指令,知道 cpu 具體在幹嘛(操作了什麼暫存器,操作了哪塊記憶體)

- 本教程的**是直接跑在 mac 的命令列(commandlinetools)專案上

- 因此展示的彙編**是基於 x64 的 at&t 格式彙編,並非 ios 真機裝置的 arm 彙編

- 其實不同種類的彙編之間有極大的相似性,只是有些指令的叫法不一樣

跟微軟的 visual studio 一樣,xcode 也內建了非常方便的反彙編功能,可以輕鬆檢視每一句**對應的彙編指令,開啟反彙編介面的步驟如下

- 在某一行需要除錯的**打上斷點(反彙編介面會在斷點除錯狀態下顯示出來)

- 選單:`debug` > `debug workflow` > `always show disassembly`

- `assembly` 譯為彙編, `disassembly` 譯為反彙編

-   執行程式,看到反彙編介面

如果你的反彙編經驗十足,根據第 16、17 行的彙編就可以推敲出來,string 是占用 16 個位元組

- 因為它用了 rax、rdx 暫存器存放字串 str 的內容,而 rax、rdx 都是 8 位元組的

三、字串的底層儲存

窺探記憶體

此前我寫了個可以窺探 swift 變數記憶體的小工具:

- 現在用它來窺探下字串的 16 位元組裡面,究竟儲存著什麼資料

- `mems.memstr(ofval:)` 預設情況下按照 8 個位元組一組來顯示記憶體資料

- 傳遞引數 `alignment: .one` 是按照 1 個位元組一組來顯示記憶體資料

字元 '0'~'9' 的 ascii 值是 0x30~0x39,認真觀察最初 str1 的 16 個位元組資料,你發現了什麼?

- 它直接將所有字元的 ascii 值儲存在 str1 的 16 位元組中

- 最後 1 個位元組 0xea 中的 0xa 就是字元的數量,也是共 10 個字元

拼接

可以發現,當對 str1 進行拼接 "abcde" 的時候

- 它最終是將 "0123456789abcde"十五個字元的 ascii 值都儲存在了 str1 的 16 位元組中

- 最後 1 個位元組 0xef 中的 0xf 就是字元的數量,也是共 15 個字元

- 可以看得出來,目前 16 個位元組已經存滿了,那如果再拼接 1 個字元呢?

可以看到,str1 裡面儲存的資料發生了非常大的變化,每乙個字元的 ascii 值不見了,

- 那裡面的 16 位元組具體是什麼含義呢?

- 所有字元('0'~'9'、'a' 到 'f')的 ascii 值又存到哪去了呢?

其他情況

如果一開始初始化的時候(未拼接之前),字串的內容就是超過 15 個字元呢?

相信你能猜到是這個結果

- 這 16 個位元組裡面並沒有出現任何乙個字元的 ascii 值

- 而且這 16 個位元組跟 `第27行的str1` 還是有所區別

- 雖然它們的字串內容都是"0123456789abcdef"

如果對 str2 進行拼接操作

不難發現:這時 str2 的 16 位元組又發生了變化,跟 `第27行的str1` 是有點相似的

如何解決上述疑問?

- 提取碼:kzrk

四、最後

人們經常認為組合語言的應用範圍很小,而忽視它的重要性。其實組合語言對每乙個希望學習電腦科學與技術的人來說都是非常重要的,是不能不學習的語言。

彙編能給你帶來的價值遠遠不止這篇文章所說的窺探字串的底層,對你的程式生涯影響絕對是終生受益的(資料結構與演算法功底也是如此)。學會彙編後,你在用高階語言程式設計時會更了解機器到底做了什麼,可以通過修改高階語言的**來提高演算法所不能提高的效率。

不僅如此,你還能玩轉軟體破解、遊戲外掛程式等,這是我此前用【彙編\c++】編寫的乙個遊戲外掛程式:

it技術的發展日新月異,新技術層出不窮,具有良好的學習能力,能及時獲取新知識、隨時補充和豐富自己,已成為程式設計師職業發展的核心競爭力。

作為一名程式設計師,更需要不斷豐富自己的知識庫。我們所知道的東西,就像乙個白色的圓圈,圈外則是黑暗的未知的世界。當圓圈越大,所接觸到的黑暗部分就越多。我們只有不停地學習,才能打破更多的黑暗,找到更多光明。

彙編高手帶你玩轉字串,快上車!

字串 string 是由數字 字母 下劃線組成的一串字元,一般記為 s a1a2 an n 0 字串主要用於程式設計,概念說明 函式解釋,它是程式語言中表示文字的資料型別。在程式設計中,字串 string 為符號或數值的乙個連續序列,如符號串 一串字元 或二進位制數字串 一串二進位制數字 一 思考 ...

彙編高手帶你玩轉字串,快上車!

字串 string 是由數字 字母 下劃線組成的一串字元,一般記為 s a1a2 an n 0 字串主要用於程式設計,概念說明 函式解釋,它是程式語言中表示文字的資料型別。在程式設計中,字串 string 為符號或數值的乙個連續序列,如符號串 一串字元 或二進位制數字串 一串二進位制數字 一 思考 ...

指標玩轉字串

作 者 霍雨佳 完成日期 2013 年12月17日 版 本 號 v1.0 問題描述 利用指標。樣例輸入 樣例輸出 問題分析 用陣列名作引數,利用函式把str1和str2連線起來。include 字串連線函式實現和測試 using namespace std void astrcat char str...