最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網 會員登陸 & 注冊

口袋妖怪綠寶石——數(shù)據(jù)提取與代碼分析(5-THUMB匯編指令基礎)

2022-08-19 10:54 作者:圍巾胖頭魚  | 我要投稿

說在前面:

????前面幾期專欄主要討論的是ROM數(shù)據(jù)提取的內容,涉及到文本信息、符號表相關的數(shù)據(jù)詳情以及地圖信息。數(shù)據(jù)提取的部分并沒有說完,例如還有一類重要的數(shù)據(jù)——腳本——沒有提到,只不過要想理解ROM中的腳本數(shù)據(jù),需要先有一些代碼分析的基礎。

????本期專欄主要介紹ROM中最主要的一種代碼類型:THUMB匯編指令。為了講清楚這個專業(yè)詞匯的來源,還有許多背景知識需要交待。

代碼是什么

????代碼是讓計算機執(zhí)行操作的指令。這種命令從理論上來說,只有計算機自己才能“看得懂”,而計算機只能“看懂”0和1,也就是0/1序列。ROM是一種二進制文件,里面到處都是0/1序列,有的是數(shù)據(jù),有的是代碼,代表代碼的那一部分0/1序列正好是計算機可以“看得懂”的指令。這種0/1序列表示的代碼被稱作機器語言

????顧名思義,機器語言是給機器看的,不是給人看的(并不排除有的大佬能夠看懂機器語言)。為了讓機器語言方便人們理解,匯編語言誕生了。匯編語言采用了一系列英文單詞(術語稱為助記符,mnemonic)和特定的格式來描述計算機指令。注意,這只是描述,而不是指令本身,指令本身只能是計算機“看得懂”的機器語言。為了讓機器也能看懂匯編語言,需要借助一個“翻譯”,“翻譯”的專業(yè)術語稱作匯編(assemble),執(zhí)行“翻譯”操作的“翻譯員”就是匯編器(assembler)

????先舉一個例子,在綠寶石ROM的環(huán)境下,下面兩行的第一行是機器語言,第二行是和它等價的匯編語言:

????這里的00 20是字節(jié)序列,可以看做是0/1序列在十六進制下的表示,它只是用于節(jié)省空間的一種表示方法,并沒有改變這是0/1序列的事實(按照二進制的寫法,就是00000000 00100000),不要以為這里有個2就不是0/1序列了,2只是二進制0010的十六進制表示。

????第二行是一條匯編代碼。在匯編語言中,一行只有一條代碼。匯編器做的工作就是將第二行翻譯成第一行,這樣由人類程序員寫出的第二行代碼,在匯編器的翻譯下,就可以變成能讓計算機執(zhí)行的第一行。

????如果把這個過程反過來,例如ROM里面都是0/1序列這種機器代碼,需要某種操作把它轉化成人類能夠看懂的匯編代碼,這種操作就稱作反匯編(disassembly)?;氐缴厦婺莻€例子,反匯編的作用是把機器代碼“00 20”“翻譯”成匯編代碼“movs r0, #0”。

????很多模擬器都有反匯編的功能,例如VBA。很久之前那個介紹金手指的專欄究極綠寶石5.3——科普向,什么是金手指(二)里面,是把VBA的反匯編功能當做了變量查看器,其實變量查看器的功能交給“VBA——工具——內存查看器”更合適一些,把反匯編功能用來查看變量有些大材小用了。

????所以,我們從ROM中看到的代碼到底是什么代碼呢?如果不借助任何工具,直接打開ROM這個二進制文件的話,我們看到的就是機器代碼。如果借助模擬器或其他工具的反匯編功能,我們就可以看到匯編代碼。還能再進一步嗎?

????在機器語言和匯編語言之上,還有一種被稱作高級語言的代碼類型。綠寶石源代碼項目使用的C語言就是一種高級語言,其他類似Java、Python等編程語言也都是高級語言。但是目前還沒有任何一個工具能夠將ROM中的匯編代碼“翻譯”成高質量的C代碼。

????這里需要指出,匯編代碼“翻譯”成C代碼是存在“翻譯質量”這種說法的(機器代碼到匯編代碼就沒有“翻譯質量”這個概念,它們是一一對應的關系),最主要的原因就是C語言中的各種常量名、變量名、函數(shù)名、宏等等符號的名稱,在匯編語言中全消失了。匯編語言中沒有任何符號的名稱(雖然匯編語言本身可以有l(wèi)abel定義的標簽名,但是綠寶石ROM中找不到這種東西),有的只是各種各樣的地址。綠寶石源代碼項目里的C代碼,可以看做是原版綠寶石ROM中匯編語言的一個高質量翻譯版本,它高質量的一處重要體現(xiàn)在于從符號的名稱可以大致猜出該符號的含義。

????在面對綠寶石改版游戲的ROM時,一般是沒有用高級語言寫成的源代碼來分析的(除非是制作組成員),有的只是借助模擬器等工具通過反匯編得到的匯編語言。但是,綠寶石改版畢竟是基于原版綠寶石做出的修改,許多代碼和原版綠寶石還保持著高度的相似性,而這部分相似性就讓原版綠寶石的源代碼項目有了用武之地,讓匯編代碼的分析速度和質量有了質的飛躍,這就是我們的機會!

匯編代碼和機器代碼怎么轉換

????按理說,這種轉換的事情交給模擬器的反匯編功能就可以了,之所以這里還需要再說明一下,是因為轉換分為兩種模式:ARM模式和THUMB模式。

????由于解釋清楚這兩種模式需要很多計算機體系架構方面的知識,這和本系列專欄的關系不大。因此這里只給出一個結論:在絕大多數(shù)情況下,口袋妖怪綠寶石的ROM文件內,使用的代碼都是THUMB模式。這樣,在VBA的反匯編窗口里應該選什么就不會糾結了:

一般而言都選擇THUMB模式

?????除了使用模擬器進行匯編代碼和機器代碼之間的轉換,利用在線網址:

????https://armconverter.com/

????也很方便,以上圖為例,VBA把080003a4處的數(shù)據(jù)b5f0翻譯成“push {r4-r7,lr}”,可以在網站中驗證一下:

在線轉換工具

????填進去的時候要寫成f0?b5,因為ROM中的數(shù)據(jù)永遠需要用小端序的方式拼接。在右側的THUMB轉換結果中出現(xiàn)了“push {r4,r5,r6,r7,lr}”,這和“push {r4-r7,lr}”是等價的:r4-r7就是r4,r5,r6,r7的一種簡化寫法。

????另外還可以看到,網站右側的THUMB下面還有個THUMB Big Endian的輸出欄,這里的Big Endian就是大端序,和小端序恰好反過來。如果在左側輸入欄輸入b5 f0的話,右側那兩個THUMB和THUMB大端序的結果就會顛倒過來。

THUMB匯編指令的含義

????現(xiàn)在我們的目標明確了:利用反匯編工具獲取ROM中的THUMB匯編指令,結合原版綠寶石源代碼進行代碼分析。但在分析匯編指令之前,首先要搞清楚每條匯編指令都是什么含義。

????匯編指令的文檔在這個網址內:

????https://developer.arm.com/documentation/ddi0210/c/Introduction/Instruction-set-summary/Thumb-instruction-summary

????上面的是官方文檔,還有一個文檔解釋得也很詳細,這是一個開發(fā)GBA游戲的愛好者寫的,TA的網站上還有很多和GBA開發(fā)相關的知識:

????https://www.coranac.com/tonc/text/asm.htm

????接下來在分析匯編代碼的時候,專欄也會隨時給出匯編指令的含義,方便讀者理解。

????理解匯編指令的含義還需要了解寄存器這個概念。上面提到過,ROM的匯編語言中沒有變量名,有的只是作為暫時存放數(shù)據(jù)的容器:寄存器(在高級語言中,這種存放數(shù)據(jù)的容器就是變量)。可用的寄存器共有16個,名稱從r0到r15,其中r0到r12是通用寄存器,可以進行各種操作;剩下的3個寄存器是專用寄存器,各有各的用途:

  • r13,別名sp,保存當前程序棧的棧頂

  • r14,別名lr,保存通過BL指令調用函數(shù)的返回地址

  • r15,別名pc,保存當前要執(zhí)行的指令所在的地址

????這里提到的幾個概念:“程序棧”“調用函數(shù)”“返回地址”等等會在后面用到的時候進行解釋?,F(xiàn)在只需要知道,ROM里的THUMB指令,翻來覆去能操作的,無非就是數(shù)字(術語稱作立即數(shù))、地址和寄存器而已。

????每條匯編指令的格式基本上都是“指令助記符 操作數(shù)”的格式,這兩個概念在分析匯編指令時會反復用到。

????和一些高級語言不同,匯編語言里的字母沒有大小寫的分別,BL指令和bl指令是同一個指令。

綠寶石游戲程序的主函數(shù)

????使用過C、Java、Python或者其它編程語言的讀者們都很清楚,任何一個程序能夠運行起來都必須要有一個被稱作主函數(shù)的函數(shù)(也叫main函數(shù)),例如下面這個最簡單的C語言Hello World程序:

????這個程序可以不定義任何變量,可以不定義任何其他函數(shù),但是至少要有一個主函數(shù),這也是整個程序開始執(zhí)行的地方。

????口袋妖怪綠寶石作為一個游戲,也是一個程序,它也要有自己的主函數(shù),這個主函數(shù)在符號表內的名稱是AgbMain,地址位于080003a4處。我們先來看看源代碼項目中的AgbMain函數(shù):

主函數(shù)

????可以看到,主函數(shù)開頭的部分幾乎都是函數(shù)調用,這對于綠寶石這樣一個龐大的游戲程序來說是很正常的。我們真正感興趣的,是這段代碼如何與ROM中的匯編指令對應起來,接下來用VBA的反匯編功能查看080003a4這里的匯編代碼:

主函數(shù)的匯編代碼

? ? 下面我們詳細分析一下:

????這是主函數(shù)的前三行,做的事只有一件:將部分寄存器的值保存到程序棧中。這里可以提一下程序棧的概念。因為寄存器實在是太少了,每個函數(shù)都要用。在函數(shù)進行調用的時候,調用函數(shù)用到的一些寄存器(里的數(shù)值)需要暫時存放起來,這樣這些寄存器就可以空出來給接下來的被調用函數(shù)使用。這個暫時存放的位置就是程序棧。

????push指令執(zhí)行的操作就是把寄存器(里的數(shù)值)存放在程序棧內,與之對應的指令pop做的事正好反過來:把程序棧里的數(shù)值拿出來恢復到對應的寄存器內。有一個規(guī)律可以幫助記住這兩個指令:push指令最常出現(xiàn)在一個函數(shù)的開頭,pop指令最常出現(xiàn)在一個函數(shù)的結尾。

????中間第二行的mov指令是最常見的指令,如果把r7和r8都看做變量名的話,mov指令就是一個賦值操作:r7 := r8,將r8內的數(shù)值復制到r7內。

????這三行匯編指令在源代碼中沒有對應,這是匯編代碼給函數(shù)調用添加的額外指令。

????接下來的兩行匯編代碼對應到源代碼的第92行。源代碼的第91行和第93行被稱作預編譯指令,這種以#開頭的指令是不會體現(xiàn)到匯編代碼中的。

????源代碼第92行是一個函數(shù)調用,匯編指令bl就是函數(shù)調用功能,它的操作數(shù)082E70A8就是被調用函數(shù)所在的地址,通過符號表可以查到這個地址對應的函數(shù)名正好就是RegisterRamReset。

????那第一行把r0賦值為0xff是做什么用的呢?注意到RegisterRamReset函數(shù)有個參數(shù),叫RESET_ALL,通過VS Code的“轉到定義”功能很快可以找到RESET_ALL的定義就是0xff,這說明r0是作為參數(shù)傳遞給了函數(shù)RegisterRamReset,這里就可以引入傳遞函數(shù)參數(shù)的概念了。

????在匯編語言中,函數(shù)調用使用的bl指令只有一個操作數(shù),就是被調用函數(shù)的地址,如果需要傳遞參數(shù),需要用到寄存器;如果參數(shù)太多,還需要用到程序棧。在口袋妖怪綠寶石的ROM中,函數(shù)參數(shù)默認使用r0-r3這4個寄存器(當函數(shù)參數(shù)不超過4個的情況下),這也是為什么AgbMain這個函數(shù)在開頭的時候沒有把r0~r3這4個寄存器放到程序棧里面,因為它們默認就是要讓被調用函數(shù)使用的,因此不需要暫存起來以便之后再恢復。

????注意匯編代碼中函數(shù)調用這一行(bl $082E70A8),它使用了4個字節(jié)(e6 f2 7c fe)來表示一條指令。網上有的資料會說THUMB模式的代碼都是2個字節(jié)對應一條指令,只有在ARM模式下才是4個字節(jié)對應一條指令。事實上,綠寶石的ROM里采用的THUMB模式是一種擴展的THUMB模式(THUMB-2模式),這種模式也支持使用4字節(jié)來編碼一條THUMB指令。

????如果把函數(shù)調用這一行的4個字節(jié)放到在線轉換的網站上,會得到一個和VBA反匯編不一樣的結果:

函數(shù)調用的匯編指令

????網站上給出的結果是bl #0x2e6cfc,為什么和VBA中的bl $082E70A8不一樣呢?

????其實它們是一樣的,關鍵在于bl這條指令的操作數(shù)是相對地址,相對于這條指令本身所在的地址。這條指令位于080003AC處 ,如果進行這樣一個運算:0x080003AC+0x2E6CFC,得到的結果就是0x082E70A8。VBA模擬器自動進行了從相對地址到絕對地址的轉換,但是在線網站不知道這條指令的地址是什么,就只能給出它最原始的樣子。

????為了讓在線網站給出和VBA反匯編相同的結果,需要利用在線網站左下角Offset處的功能,把這條指令的地址填寫進去:

填入代碼地址后的轉換結果

????此時在線網站的轉換結果就和VBA反匯編一樣了。

????先來理解一下源代碼第94行的含義。BG_PLTT本身是個數(shù)字,被(vu16 *)進行強制轉換后變成了指針,外面再用一個*運算符表示取這個指針的內容。所以這行代碼的含義就是在BG_PLTT指向的位置保存RGB_WHITE。

????回到匯編代碼,第一行是把r0賦值為0xa0,第二行的lsl是邏輯左移運算,lsl是logic shift left的縮寫,和它相對的指令有兩個,lsr(logic shift right)邏輯右移和asr(arithmetic shift?right)算數(shù)右移,等到遇到右移指令的時候再進行說明。

????lsl的操作數(shù)有3個,含義是把第二個操作數(shù),左移第三個操作數(shù)那么多位,然后賦值給第一個操作數(shù)。如果按照C代碼來寫,就是

????可以用計算器算一下,0xa0左移0x13位的結果是0x5000000,這個數(shù)值正好就是BG_PLTT。

????不知道讀者有沒有疑惑,前兩行匯編代碼其實就是將0x5000000賦值給r1這個寄存器,為什么不能寫成一行:

????要解釋清楚這個問題需要了解2個字節(jié)的機器代碼是怎么“翻譯”成匯編代碼的。詳細的原因專欄就不再解釋了,可以理解為2個字節(jié)的內容有限,無法編碼0x5000000這么大的數(shù)字。

????第三行匯編指令,ldr是讀取數(shù)據(jù)的指令,從一個地址處讀取4個字節(jié)。如果是讀取2個字節(jié),指令就是ldrh,如果只讀取1個字節(jié),指令就是ldrb,這里h是half word(半字)的簡寫,b是byte(字節(jié))的簡寫。把一個數(shù)字或者寄存器用中括號括起來的含義是把操作數(shù)當做指針來使用,所以這行匯編代碼就是把08000468處的4個字節(jié)賦值給r2,相當于C語言中的:

? ? VBA模擬器的反匯編功能自動增加了一條提示,也就是(=$00007fff),這就是08000468處的4個字節(jié),免去了還需要去這個地址再查看一遍的工夫。這也是一個稍微有點“智能”的反匯編器應該具有的功能。可以驗證,RGB_WHITE的值就是0x7fff。

????和函數(shù)調用指令bl類似,如果有感興趣的讀者把這條指令對應的2個字節(jié)放到在線網站上去轉換,會發(fā)現(xiàn)它用的也是相對地址。也就是說,08000468這個地址也是VBA模擬器自動轉換的結果。

????再下一行,add指令是加法運算,等價于C語言中的

????最后一行,strh指令,它是str指令中的一個,str和ldr指令相對,ldr是讀取,str是保存,后面可以添加h或者b這種后綴表示讀取/保存的字節(jié)數(shù),什么都不加就是4個字節(jié)。strh就是保存2字節(jié),這行代碼相當于C語言中的:

????用中括號括起來的部分——[r1, #0x0] 表示以一個寄存器(的數(shù)值)為基本地址(基址),向后偏移一定數(shù)量的字節(jié)(偏移量)后形成的地址,這里的偏移量是0,所以和[r1]是一樣的。

????之前沒接觸過匯編語言的讀者可能又有了一個疑惑。前面提到的mov指令相當于C語言中的賦值,那為什么還需要ldr和str這兩條指令?換句話說,這兩條指令:

?和這兩條指令:

是不是等價的?

????這就要說到匯編語言中的寄存器和C語言中變量的區(qū)別了。在C語言中,只要定義好了一個變量(必要時還需要分配好它的空間),把它放在賦值運算的左側或者右側都是可以的。但是在匯編語言中,像mov或者數(shù)學運算這種指令只能對寄存器直接操作,而不能對內存直接操作。這里所說的內存就是用中括號括起來、用數(shù)字表示指針指向的那些區(qū)域。

????所以,后面的兩條mov指令本身就是不合法的。

????整個ROM是內存的一部分,回顧一下ROM這個名字的來源(Read-Only Memory),在匯編語言中對ROM里的數(shù)據(jù)只能讀?。╨dr指令),而不能寫入(str指令),這就是它被稱作只讀存儲器的原因。

????有了上面一些指令的知識基礎,再分析接下來的代碼就不難了,因此下面只分析還沒有提到過的匯編指令。

????這里出現(xiàn)了兩個新的指令:比較指令cmp和條件跳轉指令beq。顧名思義,這里就是比較r0和0x1的大小,如果相等(eq是英文equal的簡稱),就跳轉(b是英文branch(分支)的簡稱,在THUMB匯編指令中,所有的跳轉都被稱作“分支”,和其他匯編語言中用j來簡稱jump有所區(qū)別)。這種以b開頭的指令可以稱作分支指令家族,包含了條件跳轉指令和無條件跳轉指令。

????也就是說,如果r0和0x1是相等的,就會跳過下面兩行代碼,直接到08000414這里繼續(xù)執(zhí)行。和C代碼對比就知道,這里的r0就是gFlashMemeryPresent,0x1就是TRUE,如果相等,條件語句if里面的代碼就不會執(zhí)行。匯編語言只能通過各種以b開頭的指令來實現(xiàn)跳轉。

????除了beq,分支指令家族還有許多其他的成員,就像除了等號之外,還有許多比較大小關系的運算符那樣:有不等號,就有bne;有小于號,就有blt和blo;有小于等于號,就有ble和bls……其中比較大小還分為有符號數(shù)的比較大小,和無符號數(shù)的比較大小,這些都等到專欄用到的時候再作說明。

????上面提到的函數(shù)調用指令bl也是分支指令家族的成員,其實仔細想想就能明白,函數(shù)調用無非也就是程序跳轉到另一個地方執(zhí)行,函數(shù)調用也是一種“跳轉”。

????在源代碼AgbMain函數(shù)的第122行,出現(xiàn)了:

????并且在這個for循環(huán)代碼塊內沒有出現(xiàn)break或者return這種跳出循環(huán)的代碼,也就是說,代碼在這里陷入了死循環(huán)。

????這正是一個游戲程序應該具有的特點。試想一下,如果游戲程序也能運行結束的話,那么此時的玩家就再也無法進行游戲中的任何操作了,這只能是玩家結束游戲的時候才會做的事。而結束游戲只需要關閉模擬器就可以了,這是在“硬件上”強行終止了這個死循環(huán)的程序。在游戲還在運行的時候,無論玩家進行什么操作,游戲程序本身都要給出響應,這就注定了游戲程序要以一種死循環(huán)的方式不斷等待玩家的輸入。

????這條匯編代碼執(zhí)行了死循環(huán)的邏輯:

????這種后面沒有任何后綴的b指令就是無條件跳轉指令。它不需要經過任何判斷就會跳轉到指定的位置??梢钥吹?,這里跳轉到的位置是在當前代碼所在位置的前面。前面提到過,這些用到地址的指令采用的都是相對地址,之所以顯示出來0800042a是因為VBA模擬器做了自動轉換。前面我們看到“向后跳轉”的相對地址是什么樣子的,現(xiàn)在再來看這種“向前跳轉”的相對地址:

向前跳轉的指令

????0800042A處的兩個字節(jié)是b4 e7,在線網站轉換的結果是b #0xffffff6c。了解有符號數(shù)的讀者們可能會馬上明白,這里的0xffffff6c其實是個負數(shù),負數(shù)的相對地址才會導致“向前跳轉”的效果。

到底分析出來了什么

????分析了這么久,到底分析出來什么了?有的讀者會說,我還是不知道AgbMain函數(shù)到底要做什么,調用的什么RegisterRamReset函數(shù)又是InitGpuRegManager函數(shù)根本不知道是什么意思??!

????的確,對于主函數(shù)而言,它調用的函數(shù)一定是非常上層的函數(shù),無數(shù)的細節(jié)隱藏在被調用函數(shù)中、甚至是被調用函數(shù)的調用函數(shù)中、一層一層深入下去……要解釋清楚每個函數(shù)都是做什么的,估計可以出一本書了。

????上面的分析過程,只是想讓讀者們體會一下C語言的源代碼程序和匯編語言的相似性,這樣在面對沒有源代碼的改版ROM時,可以迅速找到改版ROM里的代碼和原版代碼的對應關系,畢竟用C語言編寫的源代碼項目是非常寶貴的資源,要盡可能充分地利用。

????可以說,分析改版的ROM,就是先找到改版ROM和原版ROM的相似之處,然后再分析改版ROM的不同之處。

改版ROM的主程序在哪兒

????原版ROM由于有符號表這個方便的工具,找到AgbMain函數(shù)的位置是非常方便的。但是改版的ROM很有可能改變了AgbMain函數(shù)的位置。如果能找到主函數(shù)的位置,無疑是在ROM這個二進制文件的“大?!敝姓业搅艘粋€“定海神針”。

????由于主函數(shù)是游戲程序運行的第一個函數(shù),找到它的難度會大大降低,在這里有必要說明一下,模擬器在把ROM加載進來之后,是怎么找到主函數(shù)在哪兒的。

????之前曾經有不止一期的專欄提到過,ROM加載到模擬器之后,位于模擬器內存地址0x08000000處,綠寶石ROM的特點在于,08000000處一定是一個匯編代碼的跳轉指令,這就是模擬器運行的第一條匯編指令(它不屬于任何一個函數(shù),因此和游戲程序運行的第一個函數(shù)是主函數(shù)并不矛盾)。

????前面提到過,ROM中絕大多數(shù)的匯編指令都是THUMB模式的,那么那些“極少數(shù)”的ARM模式指令呢?其實運行主函數(shù)之前的這些匯編指令就是那些“極少數(shù)”的ARM模式指令,可以看看VBA的反匯編里面08000000處的“第一條指令”:

第一條指令

????? ? 第一條指令是b $08000204,注意只有選擇了ARM模式才能看到VBA翻譯出來的這條指令。無論是什么樣的改版ROM,在08000000處一定是一條ARM模式的跳轉指令,它跳轉到哪里了呢?

????來到08000204,還是需要使用ARM模式查看:

跳轉后的結果

????這里也有若干行ARM匯編指令,它沒有函數(shù)調用常見的push和pop指令,因此這也不算是個函數(shù)。里面的匯編指令是ARM模式的,和THUMB模式指令有些區(qū)別,但一些關鍵指令的含義沒有變化,比如mov和ldr。這里不再一行一行去分析每條指令的含義,只是說明一下,如果把打開綠寶石ROM游戲類比到給電腦開機的話,這些指令類似于把一臺電腦打開后、但是在桌面顯示出來之前,計算機運行的代碼。

????一般來說,改版的ROM不會對這部分代碼有很大的修改,只是有些地址可能會變化。上面截圖中的最后一行是個跳轉指令,但它跳轉到的是這段代碼的開頭,也沒有跳出這個范圍。剩下的就只有一條跳轉指令:位于08000230的bx指令。

????bx也屬于分支指令家族,它和bl有些類似,是專門為了調用函數(shù)設計的指令,但是它還有一個額外的功能,就是調用這條指令會導致匯編指令的模式發(fā)生切換,現(xiàn)在是ARM模式,等運行完bx這條指令后,就切換到THUMB模式了。bx跳轉到r1保存的數(shù)值處,向上看可以找到r1從一個地址處獲得4個字節(jié)的數(shù)值080003a5,這就是主函數(shù)的位置。

還有一個重要的提示

??????有的反匯編器給出的反匯編結果可能和VBA模擬器稍微有些區(qū)別,最主要的區(qū)別在于有些指令的后面會加上一個s,比如mov變成movs,lsl變成lsls等,這種加s的指令常見于數(shù)據(jù)轉移指令(mov系列)、數(shù)學運算指令(加減乘除、移位等),而不會出現(xiàn)在分支指令家族、內存操作指令(ldr, str, push,?pop等)、比較指令(cmp等)。

????加不加s的指令本質上沒有區(qū)別,如果有的讀者看到這種末尾帶一個s的指令,默認可以把它去掉(當然需要分清楚這個s究竟是不是添加上的,比如跳轉指令bls,這里的s不能去掉,因為ls表示的是“小于等于”的意思,上面也說到了跳轉指令中不會出現(xiàn)這種額外添加的s)。

????本期專欄涉及到一些比較專業(yè)的知識,對于之前沒有了解過的讀者們可能有著不小的閱讀難度。為了對綠寶石ROM有更深刻的理解,或者功利一點,為了找到更厲害的金手指,了解這些知識是有必要的。當然,如果是由于作者的表達水平有限,給讀者帶來了困擾甚至是誤導,請在評論區(qū)指出,讀者提出的好的意見和建議是促使作者提升表達能力的重要基礎。

????綠寶石源代碼里的函數(shù)成千上萬,逐一分析是不現(xiàn)實的。為了能在分析代碼這個枯燥的過程中還能感受到哪怕一點點的樂趣,接下來的幾期專欄會緊密結合金手指的探索過程,盡量和游戲本身的內容靠攏。否則忙碌了半天,到頭來連自己為什么忙碌可能都忘記了(雖然在這個過程中能力得到了不知不覺的提高)。

????再次感謝眾位讀者的支持!

口袋妖怪綠寶石——數(shù)據(jù)提取與代碼分析(5-THUMB匯編指令基礎)的評論 (共 條)

分享到微博請遵守國家法律
太和县| 长武县| 洪泽县| 阆中市| 偃师市| 自贡市| 博客| 美姑县| 华亭县| 堆龙德庆县| 重庆市| 介休市| 泸定县| 汝城县| 临猗县| 古田县| 策勒县| 新疆| 前郭尔| 咸丰县| 门源| 忻城县| 比如县| 秦安县| 德令哈市| 阿克苏市| 扎鲁特旗| 四子王旗| 嘉峪关市| 安岳县| 平武县| 寿阳县| 青神县| 河源市| 竹山县| 余姚市| 平阳县| 道孚县| 吉水县| 勐海县| 广昌县|