例項分析Erlang的彙編指令

2021-08-27 13:25:56 字數 3464 閱讀 4205

《erlang虛擬機器(vm)簡介》一文中介紹的暫存器和指令引數型別是學習erlang vm相關知識的基礎,也是理解本文內容的前提,這裡就不贅述了。

先看將要分析的例項的erlang源**:

%% mytest.erl

-module(mytest).

-compile(export_all).

%% 返回atom

t1() ->

ok.%% 呼叫bif

t2(a) ->

integer_to_list(a).

%% 加法運算

t3(a) ->

a + 10.

%% 呼叫內部函式

t4(a) ->

t3(a).

%% 函式分支

t5(0) -> 0;

t5(a) -> a + 1.

%% 尾遞迴

t6(, result) -> result;

t6([h | t], result) ->

h1 = h + 1,

t6(t, [h1 | result]).

erlc +"'s'" test.erl

生成彙編檔案:

%% test.s

. %% version = 0

, ,,,

,,

,]}...

%% 返回atom

. %% label就是標號,或者稱為**標籤,

%% 在跳轉時,這是乙個程式的入口點

. ]}.

,,0}.

. %% move指令,將原子「ok」送暫存器0

,}.%% 返回

return.

%% 呼叫bif

%% t2(a) ->

%% integer_to_list(a).

. .

]}.,,1}.

. ]}.

%% 呼叫bif integer_to_list

}.%% 加法運算

%% t3(a) ->

%% a + 10.

. .

]}.,,1}.

. ]}.

%% 呼叫guard bif,+操作符也是乙個bif函式,

%% 引數為[,],然後把結果送r0,即r0累加立即數10,

%% 如果執行出錯,則跳轉到label 0(這裡是丟擲錯誤)

%% 後面的1是幹什麼用的?(見註1)

,1,[,],}.

return.

%% 呼叫內部函式

. .

]}.,,1}.

. %% 跳轉到label 6,即呼叫函式t3

}.%% 函式分支

%% t5(0) -> 0;

%% t5(a) -> a + 1.

. .

]}.,,1}.

. %% 測試r0是否等於0

,[,]}.

%% 如果測試成功則返回,否則跳到label 11

return.

. ]}.

%% 執行加法運算

,1,[,],}.

return.

%% 尾遞迴

%% t6(, result) -> result;

%% t6([h | t], result) ->

%% h1 = h + 1,

%% t6(t, [h1 | result]).

. .

]}.,,2}.

. %% 測試r0是否是乙個非空list,如果不是則跳轉到

,}.%% r0儲存的是乙個list指標

%% 從list(r0)頭部取出乙個元素送r2,剩餘的送r3,

%% 相當於:[h|t] = r0, r2 = h, r3 = t

,,}.

]}.%% r2 + 1 結果送 r0

%% 後面的4是幹什麼用的?(見註1)

,4,[,],}.

%% 測試堆空間至少有2 words,4為live

%% 這裡傳入的live值有什麼作用?為了gc嗎?

.%% htop[0] = r0, htop[1] = r1, r1 = &htop[0]

,,}.

%% r3送r0,r3即是上面剩餘的list

,}.%% 目前已經為下一次的呼叫準備好了r0和r1這兩個引數

%% 呼叫自已

%% 生成opcode時,call_only會合併上面的move一起生成move_call_only_xrf x(3) x(0) mytest:t6/2 ???

}.. %% 測試r0是否為空list,如果不為空則跳轉到報錯

,}.%% 將r1送r0,這是函式的最後返回結果

,}.return.

%% 以下兩個函式,***,不解釋。

. .

.,,0}.

. ,}..}.

. .

.,,1}.

. ,}.

,}..

}.

注1:很多函式呼叫的指令後面都會有乙個數字,不太理解這個數字是幹什麼用的。google了一會,沒找到答案。可能它是乙個位址值,作為被呼叫函式的執行空間的起始位址。但這只是乙個猜測,即使是這樣,這個值又是怎麼樣計算出來的?

現以加法為例查詢一下這個數字的**。

在ops.tab中查詢gc_bif,有如下結果:

#

# optimize addition and subtraction of small literals using

# the i_increment/4 instruction (in bodies, not in guards).

#gc_bif2 p live u$bif:erlang:splus/2 int=i reg=d dst => \

gen_increment(reg, int, live, dst)

gc_bif2 p live u$bif:erlang:splus/2 reg=d int=i dst => \

gen_increment(reg, int, live, dst)

再從beam_load.c中找到如下結果:

static genop*

gen_increment(loaderstate* stp, genoparg reg, genoparg integer,

genoparg live, genoparg dst)

原來它是乙個live值。

小猜

被呼叫的函式只能使用live值以上的暫存器,這樣就不會覆蓋正在使用的暫存器值,使用這種方法,也省去了使用棧。但是,這種方法不會導致暫存器不夠用嗎?或許只有簡單函式的呼叫才做了這樣的優化。

ARM跳轉指令B的反彙編分析

為說明跳轉指令b的反彙編分析方法,這裡以一段 為例 text global start start b step1 step1 b step1 反彙編 如下 00000000 start 0 eaffffff b 4 4 e59ff000 ldr pc,pc,0 c 8 eafffffe b 8 c...

彙編中的指令

跳轉指令用於實現程式流程的跳轉,在 arm 程式中有兩種方法可以實現程式流程的跳 1 使用專門的跳轉指令。2 直接向程式計數器 pc 寫入跳轉位址值。通過向程式計數器 pc 寫入跳轉位址值,可以實現在 4gb 的位址空間中的任意跳轉,在跳轉之前結合使用 mov lr pc 等類似指令,可以儲存下一條...

彙編的各種指令

不怎麼用就忘記了,以後每學到乙個新的指令就記錄下來 如何在64位win10系統搭載彙編環境 1 什麼是debug?debug是dos,windows都提供的實模式,程式的除錯工具,使用他,可以檢視cpu各種暫存器中的內容,記憶體中的情況和在機器碼級跟蹤程式的執行。2 我們用到的debug功能 r命令...