當前位置: 華文星空 > 知識

在龍芯3A5000上執行Windows程式

2022-03-18知識

2022-03-18:本文所述操作步驟較為繁瑣,另寫了一篇操作簡單的替代本文內容:

龍芯3A5000是龍芯最新的桌面CPU,它基於龍芯自主設計的LoongArch架構(指令集),效能接近市場主流CPU水平。因為各種作業系統和應用程式都與指令集相關,所以x86架構(指令集)的CPU就不能直接執行ARM架構(指令集)的應用程式,反之亦然。因此誕生了各種各樣的二進制(指令)轉譯技術,用於跨架構模擬執行其它平台的作業系統和應用程式,各種二進制(指令)轉譯技術可以分為軟體轉譯、硬體轉譯、軟硬結合的轉譯這三大類。我先簡述一下二進制轉譯技術,然後再給出在UOS和龍芯3A5000上執行任何Windows程式的方法。

二進制轉譯技術簡述

以軟體方式進行二進制(指令)轉譯必須存在一個宿主系統,模擬器程式在宿主系統上執行。比如各種遊戲模擬器,用來在電腦上玩紅白機遊戲、街機遊戲、PS遊戲等,以純軟體的方式構建了一個虛擬的主機環境,讓那些遊戲程式成為缸中之腦,遊戲程式執行的所有指令、請求的所有資源都是由轉譯軟體模擬出來的,但它以為自己是在真正的主機中執行。

模擬通用電腦的CPU和相關硬體環境要比模擬遊戲主機復雜得多。這方面的代表軟體,有開源的可虛擬多種架構的qemu、蘋果的rosetta 2、以及微軟Windows11在arm上模擬x86和在x86上模擬arm的技術等等。其中qemu可以在多種架構(指令集)之間相互轉換,不但只支持動態轉譯,而且效能最低,平均執行效率僅為原生效能的5%左右。蘋果和微軟都是一對一的專用轉譯,且與作業系統深度結合,效率較高。

硬體轉譯以Transmeta CPU為代表,它的CPU本身是一種「超長指令字」架構,但在指令譯碼的階段,接受的是x86指令,然後把x86指令轉換為它自己的指令來執行。這種方式使它的CPU看起來就是一塊x86架構的CPU,並且不需要對電腦中的其它硬體進行模擬,各種支持x86指令集的作業系統和應用程式都可以在使用Transmeta CPU的電腦上直接安裝執行。Intel/AMD現在的CPU其實也是硬體轉譯技術的代表,它們內部是執行的「微碼(類似於精簡指令集)」,而對於的表現則依然是x86架構的處理器。

龍芯的LoongArch架構(指令集)則代表了第三個分類,即軟體和硬體結合的二進制轉譯方式。這種方式既有軟體轉譯的靈活性,又能接近或達到硬體轉譯的效率,兼具二者的優點。龍芯的二進制轉譯本質上也是軟體轉譯,但是對軟體轉譯中比較耗時的處理提供了專門的硬體指令來加速轉譯過程,因此稱它為軟硬結合的二進制轉譯技術。龍芯之所以不使用純硬體的轉譯方式,是因為我們必須建立自主的軟體生態體系。如果像Transmeta那樣對外表現為x86的CPU,那麽它能直接執行的就只有基於x86的作業系統和應用程式,生存狀況高度依賴於Intel和微軟的態度,因此它雖然在Intel的訴訟中獲勝,但卻在Intel對市場的操作下慘然離場。

龍芯的LoongArch架構(指令集)本身是一種獨立的,完善的指令系統,可以建立獨立於x86/ARM之外的軟體生態體系。 龍芯的二進制轉譯技術主要是在LoongArch原生軟體生態建設的初期,用於補充原生軟體的不足,LoongArch架構和龍芯CPU的生存不依賴於Intel/ARM/MS/Google等主導的軟體生態。 二進制轉譯技術具有單方面的決定權,任何公司都沒有理由阻止任何軟體以二進制轉譯的方式在某種原生不支持的架構上執行。即使軟體開發商以檢測CPU型號等技術手段阻止執行,那麽以軟體為主體的二進制轉譯技術也能輕松解決這個問題,而固化在CPU硬體中的各種資訊和特征則不可能像軟體那樣線上升級。以軟體轉譯為主體的二進制轉譯,甚至可以針對特定程式把自己模擬成特定的CPU型號。

即使要轉譯的目標架構頻繁升級指令集版本,增加新的指令,不斷推陳出新,對於龍芯來說,要模擬最新的CPU和指令集,也只是更新一下軟體的事兒。而那些需要架構授權的CPU產品,如果沒有購買到新版本的架構授權,那就無論如何釋出多少個新款CPU產品,都不可能相容新版架構的新指令。

龍芯二進制轉譯系統的簡單結構說明

龍芯的二進制轉譯系統仍在開發當中,尚未公開技術資料,但當前已經有可以使用的測試版本。我僅僅根據對當前狀態分析的結果,簡單描述一下它的基本結構如下圖,可能不太準確,也不夠詳細,意會就好。

基於龍芯LoongArch架構(指令集)的CPU,在執行原生的LoongArch指令集的程式時,不需要二進制轉譯,可以直接執行。

在執行基於其它架構(指令集)的Linux程式時,由龍芯的二進制轉譯模組對指令進行轉譯。程式對Linux的API呼叫,可以直接由作業系統本身提供支持。

在執行Windows(x86)的程式時,由於Linux系統本身不能提供Windows系統的API,因此需要使用Wine來提供對Windows API的支持。Wine是給Windows(x86)程式提供虛擬的API介面,而不負責對指令的轉譯,因此只用wine並不能在非x86的CPU執行Windows程式。 在x86的應用程式中,不但程式自身邏輯以及第三方庫的二進制程式碼都是x86指令,而且用於呼叫Windows API的二進制程式碼也是x86指令,如果沒有二進制轉譯,在LoongArch上Windows程式甚至連程式入口的程式碼都不能執行,也無法呼叫Window API,程式自身的程式碼和第三方庫就更不可能執行了。

作業系統API(應用程式編程介面)是由作業系統提供給應用程式的介面,在Linux上執行Windows程式時,假如呼叫讀取檔數據的API,就可以由Wine給應用程式提供這個介面,但介面內部不再是Windows的程式碼,而是由Wine去呼叫Linux的相關介面來實作相同的功能,這就是對API的模擬。在應用程式讀取到數據之後做的操作,就不在Wine的管轄範圍內了。比如程式取得數據後可能加密解密、可能作為影像數據計算對比度、可能作為音訊數據計算特殊音效……這些操作可能是由程式自身程式碼來完成,也可能是呼叫其它的庫檔的介面來實作。 這些在Wine支持範圍之外的程式碼,在x86架構(指令集)的CPU上是由CPU直接執行,在LoongArch架構(指令集)的CPU上,就只能由二進制轉譯模組轉譯為LoongArch的指令來執行。

作業系統和應用程式對CPU指令的使用,是屬於ABI(應用程式二進制介面)的一部份,ABI的層級很低,是二進制程式碼的規範。在基於LoongArch架構的CPU上執行x86程式時,就是由二進制轉譯模組來處理對指令的轉譯,也就是對x86的ABI規範的模擬。不管是Linux還是Windows的應用程式,只要它不是LoongArch原生指令集的,最終都需要經過二進制轉譯才能在龍芯的CPU上執行。

龍芯的二進制轉譯模組當前和qemu一樣也是只支持動態轉譯,但效率比原生的qemu高出一個數量級。將來會支持動、靜態結合的轉譯模式,也就是程式執行時的動態轉譯結果可以保留下來,下次執行相同的程式就直接使用轉譯的結果,僅對程式執行時修改自身程式碼等行為需要動態轉譯。這樣可以降低轉譯的CPU消耗,轉譯執行的效率可以大振幅提高,預計執行x86程式可以達到80%的原生效率。這裏的80%是指平均80%,而不像某些純軟體的轉譯方案僅對特定型別程式轉譯效率較高,就籠統地宣傳「高效率」。

在龍芯3A5000上實戰執行Windows程式

最簡單的方式,是在使用3A5000的電腦上安裝統信的UOS系統,然後等著UOS系統的市集中提供了什麽Windows軟體,就安裝什麽軟體,可以無障礙,無門檻,無後顧之憂……可是Windows的軟體千奇百怪,UOS的市集不可能提供所有的Windows軟體,那麽我們就需要動動小手,自己解決自己的需求。

目前只有UOS for 3A5000(體驗版)系統中整合了龍芯的二進制轉譯模組,而龍芯自己的Loongnix為什麽反而還沒有提供二進制轉譯的支持呢?「體驗版」這三個字很重要,是否穩定無關緊要。龍芯的Loongnix卻是已經正式釋出的產品,對於龍芯的行業使用者來說,往系統中更新一個還沒有開發完成的、可能不穩定的功能模組,大概不是什麽喜聞樂見的事情。因此我下面就以UOS為例說明一下如何在龍芯3A5000上執行「任何」的Windows軟體,「任何」是指可以嘗試任何軟體,但不能保證所有軟體都能正常執行。

UOS中已經整合了龍芯二進制轉譯模組,但要執行Windows軟體仍然需要一個Wine環境。 UOS本身有多個版本的Wine,有經過深度/統信改良了效率和相容性的deepin-wine,也有原生的版本,我們要使用deepin-wine。最簡單的方式是從UOS市集中安裝一個由Wine支持的軟體,環境就自動配置好了。如果使用Loongnix或其它的系統,就需要手工完成這個過程,可能還需要從UOS復制一些檔和配置,比較麻煩。建議安裝的軟體是PhotoShop,因為PhotoShop是一個很大很復雜的軟體,能夠讓PhotoShop正常執行的環境,就能讓大多數軟體正常執行。

UOS對Wine版軟體的組織方式是給每個軟體一套單獨的Windows環境,也就是說每個軟體包中都有配套的Windows、Program Files、ProgramData、User等系統資料夾。這些資料夾和軟體本身,都被打包成一個files.7z檔,安裝到「/opt/apps」資料夾下以包名命名的子資料夾中。軟體首次執行時,files.7z被解壓到「/home/使用者名稱/.deepinwine/」資料夾中,並自動配置相關的執行環境。這種方式的好處是每個軟體都相對獨立,避免因某些共用檔的版本不同導致不能執行,壞處就是會增加許多額外的檔。但實際增加的檔體積並不會很大,因為前面說了Wine只是提供虛擬的API介面,因此包中的作業系統的DLL檔實際都是只有介面沒有程式碼的「代理」版本,每個檔只幾KB大小。系統DLL介面的功能是由Wine資料夾中的對應的.so檔來實作的。只有系統DLL之外的,軟體自身的以及第三方的DLL檔才是「真實」的DLL檔。

在安裝了PhotoShop(Wine)之後,在「/opt/apps/com.pscs6.deepin/files」資料夾中的files.7z和run.sh是我們需要用到的。

如果你已經執行過剛剛安裝的PhotoShop,那麽在「/home/使用者名稱/.deepinwine」資料夾中會有「Deepin-CS6」資料夾,「.deepinwine」是隱藏資料夾,在Linux中檔(夾)名字前面加「.」表示隱藏,在檔管理器中看不到,需要手工在位址列輸入才能開啟。它裏面的內容如下:

dosdevices資料夾中的內容是虛擬硬碟碟符和com介面的連結檔,比如「c:」檔就連結到「drive_c」資料夾。「drive_c」資料夾是虛擬的Windodws系統的C槽,裏面的內容一看就眼熟:

如果你要向這個由Wine虛擬的Windows環境中安裝軟體,或復制綠色軟體來執行,就把「drive_c」當成Windows的C槽來用,都往裏面復制就行了。其實直接使用PhotoShop的這個Wine環境資料夾也可以,但是為了避免一些麻煩,比如防止意外解除安裝了PhotoShop之後你放在裏面的軟體也被一同刪除,我們還是最好自己弄個單獨的環境。另外說明一下,這是32位元的Wine環境,不能執行64位元的Windows程式,如果要執行64位元的程式,需要手工配置64位元的環境,因為UOS還沒有提供直接安裝的64位元Windows程式。

先把前面在「/opt/apps/com.pscs6.deepin/files」中看到的files.7z復制到「/home/使用者名稱/.deepinwine」資料夾中,然後在files.7z上單擊右鍵,在右鍵選單中選擇「解壓到當前資料夾」。然後「/home/使用者名稱/.deepinwine」下面就會多出一個「files」資料夾,把它改個名字,比如「MyGames」或者像我一樣改成「Default」。這個資料夾中的內容和之前「Deepin-CS6」資料夾中的一樣,但你不需要在這裏執行PhotoShop,因此可以把「/home/guee/.deepinwine/Default/drive_c/Program Files」裏面的Adoeb刪除掉,節省一些空間。

再然後可以把下載到的綠色軟體或者安裝程式等都復制到「/home/guee/.deepinwine/Default/drive_c」中你喜歡的位置,最後把前面看到的「run.sh」復制出來進行一些修改,就可以執行它們了。當然也可以復制下面的內容,保存為一個副檔名為「.sh」的檔,註意要在檔內容的「許可權管理」中設定「允許以程式執行」。

#!/bin/sh #在/home/guee/.deepinwine/下面你的Windows環境所在的子資料夾名。 BOTTLENAME = "Default" #Wine的版本 APPVER = "13.0deepin6~wine5" #要執行的程式的路徑,你的drive_c資料夾就是c:/,後是相對於它的路徑。 #註意Linux中的路徑分隔符是/,而Windows中是\,這裏按照Linux的規則寫。 EXEC_PATH = "c:/ali213-AngryBirdschs/AngryBirds.exe" #啟動Wine的指令碼程式,是Wine內建的。 START_SHELL_PATH = "/opt/deepinwine/tools/run_v4.sh" #大概是這個程式關聯的文件型別,這裏設定為""。 export MIME_TYPE = "" #Wine的主程式,這是環境變量,在run_v4.sh這個啟動指令碼中會使用它。 export APPRUN_CMD = "deepin-wine5-stable" #語言環境設定 export PATCH_LOADER_ENV = "LC_ALL=zh_CN.UTF-8" #也是環境變量設定 export SPECIFY_SHELL_DIR = ` dirname $START_SHELL_PATH ` DEEPIN_WINE_BIN_DIR = ` dirname $APPRUN_CMD ` DEEPIN_WINE_DIR = ` dirname $DEEPIN_WINE_BIN_DIR ` #export WINEPREDLL="$ARCHIVE_FILE_DIR/dlls" #還是環境變量設定 if [ -n " $PATCH_LOADER_ENV " ] && [ -n " $EXEC_PATH " ] ; then export $PATCH_LOADER_ENV fi if [ -d " $DEEPIN_WINE_BIN_DIR " ] && [ " $DEEPIN_WINE_BIN_DIR " != "." ] ; then export DEEPIN_WINE_BIN_DIR fi #啟動Wine,並指定由Wine啟動的應用程式。 $START_SHELL_PATH $BOTTLENAME $APPVER " $EXEC_PATH " " $@ "

上面的「EXEC_PATH」後面的字串就是你要執行的程式路徑,我是從「遊俠網」下載了一個綠色版本的【憤怒的小鳥】,其實看到資料夾名中的「ali213」應該就猜到了。這是綠色軟體,如果要執行的不是綠色軟體而是安裝程式,過程也一樣,只要把安裝程式設定為要執行的程式就可以了。安裝完成後,可以再修改一下執行指令碼,把「EXEC_PATH」後面的字串改為安裝完成的程式路徑。

安裝程式執行時如果在Windows的桌面或開始功能表建立了捷徑,一般情況下Wine就會自動幫你在UOS的桌面和開始功能表中建立對應的Linux格式的捷徑。如果Wine沒幫你建立,那麽也可以自己建立,也就是編寫一個副檔名為「.desktop」的檔放在桌面上,或者「/usr/share/applications」中(開始功能表中的程式捷徑)。只是向「/usr/share/applications」這個資料夾寫檔需要root許可權,如果沒有開啟UOS的開發者模式,那麽把「.desktop」檔放在「/home/使用者名稱/.local/share/applications」中也可以。

「.desktop」檔的格式我就不詳細說明了,在網上有很多資料。

至此,就可以嘗試在龍芯3A5000的電腦上用二進制轉譯功能執行任何的32位元Windows程式了。可能成功,也可能執行出錯。反正我已經成功安裝、執行了很多小軟體和遊戲,比如7z、帝國時代2、仙劍奇俠傳、憤怒的小鳥、CS……等等。並不只是小程式和老遊戲可以執行,已經有一些網友測試了一些較大的和較新的軟體,可以正常執行的程式很多。

補充:

本處補充的內容其實文中已經提到,甚至是黑體加粗的,但總有人假裝看不到,那麽這裏我再集中說一下。

1. 龍芯二進制轉譯和蘋果羅塞塔2的異同:

原理都一樣,實作有區別。

二進制轉譯的基本流程是:讀取可執行檔->解析指令流->把源指令轉譯為目標指令->執行目標指令。中間涉及到寄存器的重新導向、源程式(系統)虛擬地址到目標平台的實體位址轉換、系統中斷的模擬、各種API的呼叫等等,所有的二進制轉譯都是這個樣子。

羅塞塔2只執行蘋果自己系統的軟體,因此軟體對系統API的呼叫,可以由系統自己提供支持。龍芯如果只執行x86的Linux軟體,軟體需要的API也可以由系統本身提供,這樣和羅塞塔2就沒有什麽本質區別。

執行效率方面,羅塞塔2當前優於龍芯的二進制轉譯,因為它支持靜態轉譯,也就是曾經轉譯過的程式碼可以把結果保存起來。對於非動態程式碼,下次執行時可以執行之前轉譯的結果,使部份程式碼的執行效率與原生效率相當。龍芯的二進制轉譯有支持靜態轉譯的計劃,但當前還沒有完成,也就是基本上是和qemu差不多的純動態轉譯。但是,龍芯當前的純動態轉譯效率是qemu的10倍,這就是龍芯二進制轉譯相關的硬體指令和對x86的一些硬體特性模擬帶來的效果。如果繼續最佳化,並且加上靜態轉譯,理論上最終效率會高於羅塞塔2。

羅塞塔2只支持從x86到ARM的轉譯,龍芯的規劃中支持x86、ARM、MIPS、RISC-V到LoongArch的轉譯。如果以純軟體方式轉譯,其實任何架構之間都可以實作互譯,但龍芯的LoongArch當前只對上述架構進行了硬體加速的支持。

2. Wine和龍芯二進制轉譯的關系:

Wine只是提供對Windows API的支持,不包含指令轉譯的功能,因此在ARM Linux需要E x aGear來提供二進制轉譯功能,再加上Wine才能執行Windows程式,在龍芯LoongArch上也是一樣,Linux上沒有Wine時只能執行其它架構的Linux程式,加上了Wine才能執行Windows程式。

如果沒有二進制轉譯,就不可能在非x86架構的CPU上透過Wine執行x86架構的Windows程式。

3. LoongArch架構和二進制轉譯的意義:

LoongArch在層級上,是與x86/AMD64、ARM、MIPS等並列的,是建設自主軟體生態的基礎。只有建設了自主軟體生態,才能擺脫對國外巨頭控制的軟體生態的依賴。

LoongArch不是國內第一個自主設計的指令集,但LoongArch是國內自主設計的指令集中最適合通用電腦的,且有最完善的指令功能設計的,且有最強大的推廣和行動能力的。

二進制轉譯功能不是為了「融入國際主流」,而是為了在自主生態建設初期補充原生軟體的不足。「融入國際主流」本質上是給國際巨頭開疆拓土,然後有被卸磨殺驢的可能性。二進制轉譯則完全相反,是在發展自身的同時借用其它軟體生態的成果,只會強大自身,而不會反哺對手。