2013年11月5日 星期二

[原創] Modified machine code inside .vi file , a proof of how LabVIEW runs in machine code

在了解.vi 檔案內帶有編譯完成machine code之後,可以做一個小小實驗來佐證LabVIEW執行時是直接跑machine code的.考慮簡單的加法運算 255 + 255 =510,透過Code Extractor.vi擷取machine code的部分存檔為"SimpleAdd.vi_255+255.bin";
接著修改為0+255=255,一樣透過Code Extractor.vi擷取machine code的部分存檔為"SimpleAdd.vi_0+255.bin"; 

比對一下"SimpleAdd.vi_255+255.bin"與"SimpleAdd.vi_0+255.bin", 可以發現只差在下圖紅字的地方,其實也可以發現LabVIEW編譯器會直接將兩個常數255+255視為一個常數510(0x01FE)
未來寫code如果遇到有代表意義的常數相加時可以不用客氣直接大辣辣地貼出來,LabVIEW編譯器會幫你自動最佳化成最簡的常數

修改Code Extractor.vi ,讓他可以將修改後的machine code的binary file經zlib加密後取代原始vi檔的machine code部分,並另存檔案修改黨名為Modified_XXX.

開啟修改後的"Modified_ SimpleAdd.vi", Block Diagram雖然顯示 0+255 但執行卻是510
證明了LabVIEW run-time 執行時確實是跑machine code的!
 執行時選用Highlight execution可以看到非常有趣的畫面...

點Ctrl+Shift後再點run button, LabVIEW就會重新編譯回0+255=255了

2013年11月4日 星期一

[原創] Convert LabVIEW code to x86 assembly code Introduction

從NI Community看了一篇有趣的文章
 LabVIEW code generation - behind the scenes...

這篇文章解釋了LabVIEW運行時會先把圖形化程式轉成x86 asm , 中間不會生成c code,不管是debug/release run都是直接由compiler編譯labview code轉成 x86 machine code , 因此不會受到c code compiler影響, NI只要專注在 Labview compiler的優化即可.

參考該文章範例進行實作,實作環境為 LabVIEW 2013 (32-bit) , Windows 8 (x 64) , i3-2100CPU@3.10GHz

考慮以下兩個程式碼,簡單的for loop 迴圈,shift register,加法運算, 僅改變部分初始值然後看看labview compiler 轉 machine code程式碼的差異




PS.為了簡化asm code長度 , vi的設定為取消debugging (如下圖所示)

轉為binary後 ,由hex檔直接比對,很容易就可以看出初始值差異的位置,
如左邊的F4 01即是0x1F4 , 迴圈跑500次的常數,shift register的初始值255,回圈內累加常數0x5F等





人眼看machine code絕對痛苦萬分,透過免費版IDA pro , deassembly machine code成asm code,可以幫助了解 labview compiler 執行效能 ,


 因為我也不熟 x86 asm , 上圖是我猜測的迴圈執行流程 , 中間穿插其他程式我猜可能數值型態的檢查

跑過以上流程後隱約可以感覺labview程式實際執行的流程,大概就可以解釋開發labview時遇到的以下幾個現象(不保證正確)

Q1. 不同版本 vi或相同版本vi轉到其他電腦上時,vi畫面右上角會出現 * 號要求存檔
A1. LabVIEW compiler 會檢查編譯環境,若發現需要重新編譯則會建議使用者執行前先存檔進行編譯.

Q2.新版LabVIEW跑舊版程式時,理論上新版經過優化執行速度會增加,執行時間會減少,但若沒有重新存檔則執行時間差異不大,存檔完才會有較大差異.
A2. 新版開舊版檔案時, .vi內的machine code若沒經過重新編譯,在machine code不變的情況下執行效能當然一樣.

未來幾篇文章會用這個方式將LabVIEW code轉 asm , 看看那些coding style可以獲得較佳的執行效率.