4.smali語法學習筆記

smali語言還是相對純機器碼來說,比較容易理解的
--但最好是結合工具一起學--
--還可以參考其他的整理文章--

先來一個最簡單的模型類


simpeModel.java

對應的smali


simpleModel.smali

(表格只是簡單做一個映射關系的整理)

java smali description
package .class 包名
extends .super 父類名
class .source 類名
params .field 定義字段
int I int類型
Integer Ljava/lang/Integer Integer類型
引用類型 Lxx/xx/xx 該引用類型的完整包名
boolean Z 布爾值
byte B 字節
short S 短整型
char C 字符
long J 長整型
float F 浮點數
double D 浮點數
void V
數組類型 [ 數組
function .method 定義方法
constructor 構造器方法
.prologue 開始了
.registers 申請寄存器的個數,貌似不用關心這個
.line x 對應源java文件行數
兩個簡單的方法
image.png

func1括號里有Lxx/xx/xx說明有形參,形參類型是String,也有返回值,返回值類型也是String
.param 指名 形參名 value
.prologue以下開始正式的代碼邏輯
.line 38 ,源碼38行的代碼
return-object 返回該對象的引用,其實就是把p0里的值返回來。

func2無形參,返回值類型String
const-string 聲明了一個String 類型的變量 ,值是 "abcdefg"
.local 說是 指定了使用的局部變量的個數,我這里簡單的認為,就是把v0給了一個局部變量 func2string

簡單的if-else判斷
fun3的smali

沒想到這么長。
這里有點繞,根據


跳轉指令
if-else跳轉指令

當vB為0的時候


image.png

則直接翻譯smali為

L93-int類型形參num,放到寄存器p1

L96~L97-源碼47行,如果p1的值小于等于0,跳到cond_3

L99~L102-源碼49行,結束local寄存器p1,跳到goto_2,
返回p1的值

L104~L109-源碼48行,重開寄存器p1,cond_3 入口
如果p1的值 不等于0,跳到cond_7
否則(也就是p1等于0)把 0x0這個值給p1,然后跳到goto_2

L113~L115 -也就是源碼49行,cond_7入口,
neg-int對第一個p1進行求補,然后把值給第二個p1

L117~L118 -goto_2入口,end_method

是不是感覺和java代碼func3看起來不一樣?
我給自己的解釋是類似java內存模型發生了重排序的優化,也不知道對不對,有大神知道的話評論區求解答。
不過回過頭來再看這個smali,
順序上雖然和源碼順序并不一致,但是按照直接翻譯的意思去寫java代碼

if( p1 <= 0){
    if(p1 != 0)return -p1
    else return 0
} else return p1

結果是一樣的。

再來一個


image.png
image.png

有了func3的翻譯經驗
func4就很好翻譯了
if-eqz p1,也就是形參num p1等于0的話,直接到cond_3,賦值0,最后返回。
其余的直接返回p1

if(p1 == 0)return 0
else return p1

這個優化感覺更能說服自己了,==操作比!=操作更簡單

來一個switch跳轉


switch

太長了

L145~L146-源碼59行,拿p1做switch(packed-switch關鍵字)偏移區pswitch_data_a
要看到底部
L174~L179-實際上只有兩個case需要做判斷 pswitch-6和pswitch-8(也就是兩個偏移區)
L156~L163-pswitch_6,把0x0給v0,跳到goto_5
L165~L172-pswitch_8,把0x1給v0,跳到goto_5
L151~L154-goto_5入口把int型的本地(.local關鍵字)參數result指向寄存器v0,返回v0
其余的 把0x29a給v0

int result;
switch(p1){
  case pswitch_6:
          result = 0;
          break;
  case pswitch_8:
          result = 1;
          break;
  default:
          result = 0x29a;
          break;
}
return result;

相當于幫我優化了case -1,因為case -1和default都是同樣的處理方法


常用的加log打印信息的方法


image.png
System.out.println("sout");
Log.d("log", func2())

那加入在有些情況下,調用Log.d,該類并沒有引入
android.util.Log包怎么辦?


通過完整的包名調用
我發誓這兩種寫法,smali編譯出來是一樣的

放一個四哥的自定義代碼添加方案
以上筆記,僅供參考。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • importUIKit classViewController:UITabBarController{ enumD...
    明哥_Young閱讀 3,874評論 1 10
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,754評論 18 399
  • 一、海賊錢包 活動時間:4月12日-4月18日(7天) 活動內容:活動期間內每日累計充值指定金額,可以獲得對應獎勵...
    趙様閱讀 278評論 0 0
  • 《我們》 是被同一道雷電劈中的兩棵樹 是黑夜里最高傲的兩朵火苗 是被巨石隔開的兩條河 是暴風驟雨里相擁合流的兩條路...
    何攔偉閱讀 378評論 6 5
  • 七號田閱讀 112評論 0 1