转:http://blog.yufeng.info/archives/498
我们在编码的时候, 通常会好奇, 这时候需要观察erl源码生成的VM opcode. Erlang的VM是register based的VM, 生产的opcode很容易理解.
生成汇编格式有2种方式:
1. 从源码生成抽象码. erlc +”‘S’” mod.erl, 生成mod.S
2. 从beam生成Opcode. 未公开的功能. erts_debug:df 参数M或者 M, F, 生成mod.dis
来吧,实践下:
| Erlang R14A (erts-5.8) 1 [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false] [lock-counting] | 
 
| Eshell V5.8  (abort with ^G) | 
 
| eg.beam  eg.dis  eg.erl  eg.S | 
 
 
 
我们得到了eg.S, eg.dis这2个反汇编的结果. 我们再来参观下.
先看源码:
root@ubuntu:~/exam# cat eg.erl
|     kilo_byte(N-1, [Acc|Acc]). | 
 
 
 
中间汇编码, 供transform进行处理和编译器进一步生成opcode.
root@ubuntu:~/exam# cat eg.S
| {exports, [{kilo_byte,0}, | 
 
| {function, kilo_byte, 0, 2}. | 
 
|     {func_info,{atom,eg},{atom,kilo_byte},0}. | 
 
|     {move,{literal,"*"},{x,1}}. | 
 
|     {move,{integer,10},{x,0}}. | 
 
| {function, kilo_byte, 2, 4}. | 
 
|     {func_info,{atom,eg},{atom,kilo_byte},2}. | 
 
|     {test,is_eq_exact,{f,5},[{x,0},{integer,0}]}. | 
 
|     {gc_bif,'-',{f,0},2,[{x,0},{integer,1}],{x,0}}. | 
 
|     {put_list,{x,1},{x,1},{x,1}}. | 
 
|     {func_info,{atom,eg},{atom,loop},0}. | 
 
|     {move,{integer,100},{x,1}}. | 
 
|     {move,{integer,1},{x,0}}. | 
 
|     {call_ext,2,{extfunc,lists,seq,2}}. | 
 
|     {call_ext,1,{extfunc,lists,sum,1}}. | 
 
| {function, module_info, 0, 9}. | 
 
|     {func_info,{atom,eg},{atom,module_info},0}. | 
 
|     {call_ext_only,1,{extfunc,erlang,get_module_info,1}}. | 
 
| {function, module_info, 1, 11}. | 
 
|     {func_info,{atom,eg},{atom,module_info},1}. | 
 
|     {call_ext_only,2,{extfunc,erlang,get_module_info,2}}. | 
 
 
 
VM opcode形式, VM就是来解释运行这些code的
| B5146074: i_func_info_IaaI 0 eg kilo_byte 0 | 
 
| B5146088: move_cx "*"x(1) | 
 
| B5146094: i_move_call_only_fcr eg:kilo_byte/2 10 x(0) | 
 
| B51460A0: i_func_info_IaaI 0 eg kilo_byte 2 | 
 
| B51460B4: i_is_eq_immed_frc f(B51460C8) x(0) 0 | 
 
| B51460C0: move_return_xr x(1) x(0) | 
 
| B51460C8: i_fetch_rc x(0) 1 | 
 
| B51460D0: i_minus_jId j(00000000) 2 x(0) | 
 
| B51460E0: test_heap_II 2 2 | 
 
| B51460EC: put_list_xxx x(1) x(1) x(1) | 
 
| B51460F4: i_call_only_f eg:kilo_byte/2 | 
 
| B51460FC: i_func_info_IaaI 0 eg loop 0 | 
 
| B5146110: allocate_tt 0 0 | 
 
| B5146118: move_cx 100 x(1) | 
 
| B5146124: i_move_call_ext_cre 1 x(0) lists:seq/2 | 
 
| B5146130: i_call_ext_e lists:sum/1 | 
 
| B5146138: i_call_last_fP eg:loop/0 0 | 
 
| B5146144: i_func_info_IaaI 0 eg module_info 0 | 
 
| B5146158: move_cr eg x(0) | 
 
| B5146160: allocate_tt 0 1 | 
 
| B5146168: call_bif1_e erlang:get_module_info/1 | 
 
| B5146170: deallocate_return_P 0 | 
 
| B5146178: i_func_info_IaaI 0 eg module_info 1 | 
 
| B514618C: move_rx x(0) x(1) | 
 
| B5146194: move_cr eg x(0) | 
 
| B514619C: allocate_tt 0 2 | 
 
| B51461A4: call_bif2_e erlang:get_module_info/2 | 
 
| B51461AC: deallocate_return_P 0 | 
 
 
 
收工!