不以規(guī)矩.不能成方圓。--《孟子·離婁上》
創(chuàng)新互聯(lián)主要從事網(wǎng)站制作、成都網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)遼寧,10余年網(wǎng)站建設(shè)經(jīng)驗,價格優(yōu)惠、服務(wù)專業(yè),歡迎來電咨詢建站服務(wù):13518219792
說到指令集以及CPU架構(gòu)體系,大家就會想到計算機(jī)專業(yè)課程里面的計算機(jī)體系結(jié)構(gòu)的方面的內(nèi)容。既然課程中已經(jīng)有了的內(nèi)容我就不想那么枯燥的去復(fù)述一遍,而是先看一個類的定義:
//定義寄存器編號
typedef enum : int {
Reg0,
Reg1,
Reg2,
Reg3
} RegNum;
//定義系統(tǒng)調(diào)用編號
typedef enum : int {
Int3 //設(shè)備輸出,將寄存器Reg0中的內(nèi)容輸出到屏幕
} Interrupt;
//定義指令索引
typedef int Instruct;
/**
虛擬CPU類,模擬CPU所提供的指令。
虛擬CPU由4個寄存器和運算部件組成。四個寄存器的編號分別定義在RegNum中;運算部件提供了賦值、加減、比較、跳轉(zhuǎn)9個指令。
*/
@interface VCPU : NSObject
//將一個常量值賦值給編號為reg的寄存器中。
-(void)moveFromConst:(int)val toReg:(RegNum)reg;
//將編號為reg1的寄存器中的值賦值給編號為reg2的寄存器中。
-(void)moveFromReg:(RegNum)reg1 toReg:(RegNum)reg2;
//將編號為reg的寄存器中的值賦值給地址為addr的內(nèi)存中。
-(void)moveFromReg:(RegNum)reg toAddr:(Addr)addr;
//將地址為addr的內(nèi)存中的值賦值給編號為reg的寄存器中。
-(void)moveFromAddr:(Addr)addr toReg:(RegNum)reg;
//將編號為reg1的寄存器中的值加上編號為reg2的寄存器中的值并將結(jié)果保存到編號為reg2的寄存器中。
-(void)addFromReg:(RegNum)reg1 toReg:(RegNum)reg2;
//將編號為reg1的寄存器中的值減去編號為reg2的寄存器中的值并將結(jié)果保存到編號為reg2的寄存器中。
-(void)subFromReg:(RegNum)reg1 toReg:(RegNum)reg2;
//如果兩個寄存器內(nèi)容相等則執(zhí)行instruct所指定的指令,否則什么也不做。
-(void)isEqualReg:(RegNum)reg1 withReg:(RegNum)reg2 thenGoto:(Instruct)instruct;
//跳轉(zhuǎn)到instruct所指定的指令中去。
-(void)jumpTo:(Instruct)instruct;
//系統(tǒng)返回
-(void)ret;
//系統(tǒng)調(diào)用,目前只支持屏幕輸出調(diào)用Int3,表示將寄存器編號為0中的值輸出到屏幕。
-(void)sys:(Interrupt)interrupt;
@end
上面是一個叫VCPU的類的定義部分,它是一個用OC語言實現(xiàn)的用來模擬CPU功能的類。我們再來看一個使用這個類的代碼片段:
-(void)main:(VCPU*)cpu memory:(VMemory*)memory
{
VINSTRUCT_BEGIN
VINSTRUCT(0, [cpu moveFromConst:10 toReg:Reg0]) //將常數(shù)10保存到CPU的寄存器Reg0中
VINSTRUCT(1, [cpu moveFromConst:15 toReg:Reg1]) //將常數(shù)15保存到CPU的寄存器Reg1中
VINSTRUCT(2, [cpu addFromReg:Reg0 toReg:Reg1]) //將寄存器Reg0中的值于寄存器Reg1中的值相加并保存到Reg1中
VINSTRUCT(3, [cpu moveFromReg:Reg1 toAddr:0x1000]) //將保存在Reg1中的相加結(jié)果保存到內(nèi)存地址為0x1000處的內(nèi)存中
VINSTRUCT(4, [cpu moveFromAddr:0x1000 toReg:Reg0]) //將內(nèi)存地址0x1000處的內(nèi)存值保存到寄存器Reg0中
VINSTRUCT(5, [cpu moveFromConst:25 toReg:Reg1]) //將常數(shù)25保存到CPU的寄存器Reg1中
VINSTRUCT(6, [cpu isEqualReg:Reg0 withReg:Reg1 thenGoto:9]) //如果Reg0中的值和Reg1中的值相等則執(zhí)行第9條指令:進(jìn)行打印輸出
VINSTRUCT(7, [cpu moveFromReg:Reg1 toAddr:0x1000]) //將寄存器Reg1中的值保存到內(nèi)存地址為0x1000中。
VINSTRUCT(8, [cpu jumpTo:10]) //跳轉(zhuǎn)去執(zhí)行第10條指令
VINSTRUCT(9, [cpu sys:Int3]) //系統(tǒng)調(diào)用,輸出保存在Reg0中的值。
VINSTRUCT(10, [cpu ret]) //程序結(jié)束。
VINSTRUCT_END
}
您能看懂上面代碼所實現(xiàn)的功能嗎(要想查看并運行完整的代碼請到我的 github站點中的VirtualSystem處下載)?您是否在例子里面隱約的感受到了上面代碼里面涉及到的一些關(guān)于CPU、內(nèi)存、進(jìn)程等方面的概念和知識了?它其實就是實現(xiàn)了如下的簡單功能:
-(void)main
{
int a = 10;
int b = 15;
a = a + b;
if ( a == 25){
NSLog(@"output:%d",a);
}
}
考察一下VCPU類,你會發(fā)現(xiàn)這個類提供了一些非?;A(chǔ)的操作方法:加減處理、數(shù)據(jù)移動、比較、地址跳轉(zhuǎn)、系統(tǒng)調(diào)用等功能。調(diào)用者可以利用這個類提供的操作方法來編寫并完成某個特定的功能。這個類的內(nèi)部實現(xiàn)還提供了幾個臨時存儲空間,可以通過RegNum編號來讀寫里面的數(shù)值。 VCPU實際上是一個對真實CPU所具有的能力的一個簡單的模擬類。我們來看一下CPU的組成:
從上面的CPU結(jié)構(gòu)圖片中可以看出CPU主要分為存儲單元(SU)和運算單元(ALU)以及控制單元(CU)。如果將這些部件和結(jié)構(gòu)映射到VCPU這個類時你會發(fā)現(xiàn):存儲單元所對應(yīng)的就是里面的數(shù)據(jù)成員;而運算單元和控制單元則對應(yīng)里面的所有實例方法,運算單元提供了CPU指令的實現(xiàn)(VCPU類提供了眾多的方法實現(xiàn))。
我們稱一個CPU里面所提供的所有的指令的集合稱之為指令集。
我們可以用OC語言來實現(xiàn)一個VCPU類,也可以用Swift語言來實現(xiàn)一個Swift版本的VCPU類,也可以用Java語言來實現(xiàn)一個Java版本的VCPU類。 這其中不同的語言所提供的方法的定義形式是完全不同的: 就比如說OC里面可以提供直接操作內(nèi)存地址的方法,但是Java里面則無法提供直接操作內(nèi)存地址的方法;即使是OC語言中我們要實現(xiàn)VCPU類中的方法也可以有很多種不同的方式。
不同的廠家以及不同的技術(shù)工藝和技術(shù)水平以及具體的設(shè)備上所實現(xiàn)的CPU的體系架構(gòu)以及提供的功能也是有差異的。比如ARM指令架構(gòu)體系的CPU、x86指令體系架構(gòu)的CPU、POWER-PC指令架構(gòu)體系的CPU。這些不同體系的CPU因為架構(gòu)完全不同導(dǎo)致所提供的指令和存儲單元也完全不同。我們不可能讓ARM指令直接在X86的CPU上執(zhí)行(就如OC的提供方法無法在Java中執(zhí)行是一個道理)。相同體系架構(gòu)下的CPU指令則在一定程度上是可以相互兼容的,因為相同架構(gòu)體系下的CPU的指令集是一致的(類比為接口一致,但是內(nèi)部實現(xiàn)則不相同),比如說Intel公司所生產(chǎn)的x86系列的CPU和AMD公司所生產(chǎn)的x86系列CPU所提供的指令集是相似和兼容的,他們之間的差別只是內(nèi)部的實現(xiàn)不同而已。
CPU指令集定義的是一個中央處理器所應(yīng)該提供的基礎(chǔ)功能的集合,它是一個標(biāo)準(zhǔn)是一個接口也是一個協(xié)議。在軟件開發(fā)中具有協(xié)議和接口定義的概念,無論是消費者還是提供者都需要遵循這個標(biāo)準(zhǔn)來進(jìn)行編程和交互:提供者要實現(xiàn)接口所具有的功能,至于如何實現(xiàn)則是內(nèi)部的事情,不對外暴露,消費者也不需要知道具體的實現(xiàn)細(xì)節(jié);消費者則總是要按接口提供的功能方法并組合使用來完成某種功能。這種設(shè)計的思維對于硬件系統(tǒng)也是一樣適用的。一般情況下某種CPU指令集通常都是由某些設(shè)計或者生產(chǎn)CPU的公司或者某標(biāo)準(zhǔn)組織共同定義而形成。那么目前市面上有哪些主流的CPU指令集或CPU架構(gòu)體系呢?
此處參考自:https://baike.baidu.com/item/Intel%20x86/1012845?fromtitle=x86&fromid=6150538
x86架構(gòu)是Intel公司在1978年推出的Intel 8086中央處理器中首度出現(xiàn),從Intel80386開始支持32位的系統(tǒng)。x86現(xiàn)在幾乎是個人計算機(jī)的標(biāo)準(zhǔn)平臺,成為了歷來最成功的CPU架構(gòu)。其他公司也有制造x86架構(gòu)的處理器:有AMD、Cyrix、NEC、IBM、IDT以及Transmeta等。
64位架構(gòu)
到2002年,由于32位特性的長度,x86的架構(gòu)開始到達(dá)某些設(shè)計的極限。這個導(dǎo)致要處理大量的信息儲存大于4GB會有困難。Intel原本已經(jīng)決定在64位的時代完全地舍棄x86兼容性,推出新的架構(gòu)稱為IA-64技術(shù)作為他的Itanium處理器產(chǎn)品線的基礎(chǔ)。IA-64與x86的軟件天生不兼容;它使用各種模擬形式來運行x86的軟件,不過,以模擬方式來運行的效率十分低下,并且會影響其他程序的運行。AMD公司則主動把32位x86(或稱為IA-32)擴(kuò)充為64位。它以一個稱為AMD64的架構(gòu)出現(xiàn)(在重命名前也稱為x86-64),且以這個技術(shù)為基礎(chǔ)的第一個產(chǎn)品是單內(nèi)核的Opteron和Athlon 64處理器家族。由于AMD的64位處理器產(chǎn)品線首先進(jìn)入市場,且微軟也不愿意為Intel和AMD開發(fā)兩套不同的64位操作系統(tǒng),Intel也被迫采納AMD64指令集且增加某些新的擴(kuò)充到他們自己的產(chǎn)品,命名為EM64T架構(gòu)(顯然他們不想承認(rèn)這些指令集是來自它的主要對手),EM64T后來被Intel正式更名為Intel 64(也就是x64指令集)。
在iOS編程時如果要運行在模擬器上,代碼生成的機(jī)器指令時就需要指定使用i386還是x64指令集,因為目前的mac電腦上基本采用了x86或者x64架構(gòu)的CPU。
此處參考自:https://baike.baidu.com/item/ARM/7518299
ARM處理器是英國Acorn有限公司設(shè)計的低功耗成本的第一款RISC微處理器。全稱為Advanced RISC Machine。ARM處理器本身是32位設(shè)計,但也配備16位指令集。1978年12月5日,物理學(xué)家赫爾曼·豪澤(Hermann Hauser)和工程師Chris Curry,在英國劍橋創(chuàng)辦了CPU公司(Cambridge Processing Unit),主要業(yè)務(wù)是為當(dāng)?shù)厥袌龉?yīng)電子設(shè)備。1979年,CPU公司改名為Acorn公司。
起初,Acorn公司打算使用摩托羅拉公司的16位芯片,但是發(fā)現(xiàn)這種芯片太慢也太貴。"一臺售價500英鎊的機(jī)器,不可能使用價格100英鎊的CPU!"他們轉(zhuǎn)而向Intel公司索要80286芯片的設(shè)計資料,但是遭到拒絕,于是被迫自行研發(fā)。
1985年,Roger Wilson和Steve Furber設(shè)計了他們自己的第一代32位、6M Hz的處理器,
并用它做出了一臺RISC指令集的計算機(jī),簡稱ARM(Acorn RISC Machine)。這就是ARM這個名字的由來。
目前市面上的主流智能手機(jī)等移動設(shè)備配備的CPU都采用ARM架構(gòu)。iOS應(yīng)用真機(jī)編譯出來的機(jī)器指令都是ARM指令,因此需要在編譯時指定armv7或者arm64指令集。
此處參考自: https://baike.baidu.com/item/MIPS架構(gòu)/1539401?fr=aladdin
MIPS架構(gòu)(英語:MIPS architecture,為Microprocessor without interlocked piped stages architecture的縮寫),是一種采取精簡指令集(RISC)的處理器架構(gòu),1981年出現(xiàn),由MIPS科技公司開發(fā)并授權(quán),廣泛被使用在許多電子產(chǎn)品、網(wǎng)絡(luò)設(shè)備、個人娛樂裝置與商業(yè)裝置上。最早的MIPS架構(gòu)是32位,最新的版本已經(jīng)變成64位。
目前國內(nèi)的龍芯CPU,采用的就是MIPS指令集。
此處參考自:https://baike.baidu.com/item/POWER%20PC/5963071?fr=aladdin
POWER-PC由摩托羅拉公司和蘋果公司聯(lián)合開發(fā)的高性能32位和64位RISC微處理器系列,以與壟斷PC機(jī)市場的Intel微處理器和微軟公司的軟件相競爭。PowerPC微處理器1994年推出。
IBM以前跟Intel競爭過桌面處理器市場,但由于市場策略不當(dāng)?shù)仍?,IBM沒賺到什么錢,于是決定退出桌面市場。POWER系列處理器是它退出桌面市場后才開發(fā)出來的服務(wù)器用處理器,蘋果電腦用的處理器只是Power系列里的一種,據(jù)說是IBM為蘋果特制的簡化版本,而蘋果獨一無二的經(jīng)營理念使蘋果電腦與其它PC都不兼容,所以目前的Power系列處理器不能用于桌面PC。目前蘋果電腦因PowerPC處理器不適合蘋果發(fā)展而轉(zhuǎn)而使用Intel處理器。
您是否在很多iOS庫的頭文件里面看到過POWER-PC的宏定義,早期的蘋果電腦都用POWER-PC的CPU,現(xiàn)在蘋果電腦基本都改為x64架構(gòu)的CPU了。
上面列出了一些關(guān)于CPU架構(gòu)和指令集的介紹,不同的體系結(jié)構(gòu)具有各自的優(yōu)缺點,我們可以從不同的角度對CPU進(jìn)行分類:
所謂字長就是指CPU的指令在一個周期內(nèi)能夠處理的最大的數(shù)字或者理解為對內(nèi)存地址的最大的尋址能力。因此按這個長度可以做如下分類:
一般情況下大字長的CPU指令集都會兼容小字長的CPU指令集。比如32位的應(yīng)用程序能夠在64位的CPU上執(zhí)行,而小字長的CPU指令集則無法直接提供大字長指令集的能力,如需要支撐則通常都是通過模擬來完成的,比如說一個64位字長CPU的讀取數(shù)據(jù)指令在32位字長CPU上就可以通過模擬兩次讀取來完成,現(xiàn)在有的CPU提供了指令模擬的功能,因此某些64位的應(yīng)用程序還是可以運行在32位的CPU上的,只不過性能和速度會存在很大的損耗。
此處參考自:https://wenku.baidu.com/view/b5a138d43186bceb19e8bb62.html、https://zhidao.baidu.com/question/200786121943026445.html。
所謂指令的復(fù)雜度就是指CPU指令集中所提供的指令的數(shù)量、指令尋址模式、指令參數(shù)、以及CPU內(nèi)部的架構(gòu)設(shè)計的復(fù)雜度、以及指令本身所占據(jù)的字節(jié)數(shù)等來進(jìn)行劃分的一種方式,一般有兩種類型的分類:
CISC指令集。CISC的英文全稱為“Complex Instruction Set Computer”,即“復(fù)雜指令系統(tǒng)計算機(jī)”,從計算機(jī)誕生以來,人們一直沿用CISC指令集方式。早期的桌面軟件是按CISC設(shè)計的,并一直沿續(xù)到現(xiàn)在。目前,桌面計算機(jī)流行的x86體系結(jié)構(gòu)即使用CISC。在CISC微處理器中,程序的各條指令是按順序串行執(zhí)行的,每條指令中的各個操作也是按順序串行執(zhí)行的。順序執(zhí)行的優(yōu)點是控制簡單,但計算機(jī)各部分的利用率不高,執(zhí)行速度慢。CISC架構(gòu)的服務(wù)器主要以x86/x64架構(gòu)(Intel Architecture)為主,而且多數(shù)為中低檔服務(wù)器所采用。
下面的表格舉出了CISC和RISC兩種體系結(jié)構(gòu)的差別:
此處參考自:http://blog.csdn.net/conowen/article/details/7256260
按指令流和數(shù)據(jù)流來進(jìn)行分類的依據(jù)是CPU的一條指令可以同時處理多少條數(shù)據(jù),或者一條數(shù)據(jù)同時被多少條指令處理,以及在一個CPU時間周期內(nèi)可以同時執(zhí)行多少條指令等規(guī)則來劃分的。因此可以劃分為如下四種:
單指令流單數(shù)據(jù)流機(jī)器(SISD)
SISD機(jī)器是一種傳統(tǒng)的串行計算機(jī),它的硬件不支持任何形式的并行計算,所有的指令都是串行執(zhí)行。并且在某個時鐘周期內(nèi),CPU只能處理一個數(shù)據(jù)流。因此這種機(jī)器被稱作單指令流單數(shù)據(jù)流機(jī)器。早期的計算機(jī)都是SISD機(jī)器,如馮諾.依曼架構(gòu),如IBM PC機(jī),早期的巨型機(jī)和許多8位的家用機(jī)等。
單指令流多數(shù)據(jù)流機(jī)器(SIMD)
SIMD是采用一個指令流處理多個數(shù)據(jù)流。這類機(jī)器在數(shù)字信號處理、圖像處理、以及多媒體信息處理等領(lǐng)域非常有效。Intel處理器實現(xiàn)的MMXTM、SSE(Streaming SIMD Extensions)、SSE2及SSE3擴(kuò)展指令集,都能在單個時鐘周期內(nèi)處理多個數(shù)據(jù)單元。也就是說我們現(xiàn)在用的單核計算機(jī)基本上都屬于SIMD機(jī)器。(個人覺得GPU也屬于這個范疇)
多指令流單數(shù)據(jù)流機(jī)器(MISD)
MISD是采用多個指令流來處理單個數(shù)據(jù)流。由于實際情況中,采用多指令流處理多數(shù)據(jù)流才是更有效的方法,因此MISD只是作為理論模型出現(xiàn),沒有投入到實際應(yīng)用之中。
最后我們還是回到VCPU類來,VCPU是一個對CPU的簡單的模擬實現(xiàn)。我們知道用vmware軟件可以用來模擬出一個操作系統(tǒng)運行的硬件環(huán)境,而實現(xiàn)了虛擬設(shè)備的功能;微軟公司在2017年宣布他的Visual studio 2017上能夠開發(fā)并運行iOS應(yīng)用,并且可以無縫的將代碼拷貝到XCODE上編譯并運行。其實現(xiàn)的原理是Visual studio2017本身提供了一個OC語言編譯器,同時他內(nèi)部也提供了一個Cocoa UI框架的模擬實現(xiàn)版本,所以能在上面運行iOS應(yīng)用。
從上面的幾個例子中我們可以發(fā)現(xiàn)一個特點就是:一個系統(tǒng)各個層次之間的調(diào)用總是通過某些約定的規(guī)則或者定義的接口來進(jìn)行的,并且調(diào)用者是不知道也不需要知道提供者是如何實現(xiàn)這些能力的,總是一切皆是接口:
正是因為有這些接口的定義以及標(biāo)準(zhǔn)的形成,我們才可以將原本真實的實現(xiàn)模擬出另外一個虛擬的實現(xiàn)出來。這也就是所謂的虛擬化的本質(zhì)。虛擬化可以發(fā)生在任何一個層面,也可以進(jìn)行全局虛擬或者是部分虛擬。我們可以對CPU的指令以及硬件接口進(jìn)行模擬從而構(gòu)建出一套類似vmware一樣的虛擬機(jī)軟件來運行任何操作系統(tǒng);我們也可以對操作系統(tǒng)提供的接口API進(jìn)行模擬從而構(gòu)建出一套類似Wine一樣的虛擬Windows運行環(huán)境出來;我們還可以對操作系統(tǒng)所提供的文件系統(tǒng)或者存儲系統(tǒng)來進(jìn)行模擬從而提供出一套類似Docker之類的應(yīng)用容器出來;我們也可以對Cocoa Framework進(jìn)行模擬從而提供出一個套類似Vistual studio2017上能運行和編寫OC應(yīng)用的編譯環(huán)境來(微軟開源了這個框架:微軟的OC實現(xiàn)支持)。
虛擬化首先要先接口標(biāo)準(zhǔn)定義,然后再在別人接口之上完成了一套自己的實現(xiàn)?,F(xiàn)在的系統(tǒng)從上層的軟件到下層的硬件之間都是通過接口協(xié)議進(jìn)行調(diào)用的,因此我們可以在各個層次上都實現(xiàn)虛擬的能力。
敬請期待下一篇:深入iOS系統(tǒng)底層之XCODE對匯編的支持介紹
目錄
1.深入iOS系統(tǒng)底層之匯編語言
2.深入iOS系統(tǒng)底層之指令集介紹
3.深入iOS系統(tǒng)底層之XCODE對匯編的支持介紹
4.深入iOS系統(tǒng)底層之CPU寄存器介紹
5.深入iOS系統(tǒng)底層之機(jī)器指令介紹
6.深入iOS系統(tǒng)底層之賦值指令介紹
7.深入iOS系統(tǒng)底層之函數(shù)調(diào)用介紹
8.深入iOS系統(tǒng)底層之其他常用指令介紹
9.深入iOS系統(tǒng)底層之函數(shù)棧介紹
10.深入iOS系統(tǒng)底層之函數(shù)棧(二)介紹
11.深入iOS系統(tǒng)底層之不定參數(shù)函數(shù)實現(xiàn)原理介紹
12.深入iOS系統(tǒng)底層之在高級語言中嵌入?yún)R編語言介紹
13.深入iOS系統(tǒng)底層之常見的匯編代碼片段介紹
14.深入iOS系統(tǒng)底層之OC中的各種屬性以及修飾的實現(xiàn)介紹
15.深入iOS系統(tǒng)底層之ABI介紹
16.深入iOS系統(tǒng)底層之編譯鏈接過程介紹
17.深入iOS系統(tǒng)底層之可執(zhí)行文件結(jié)構(gòu)介紹
18.深入iOS系統(tǒng)底層之MACH-O文件格式介紹
19.深入iOS系統(tǒng)底層之映像文件操作API介紹
20.深入iOS系統(tǒng)底層之知名load command結(jié)構(gòu)介紹
21.深入iOS系統(tǒng)底層之程序加載過程介紹
22.深入iOS系統(tǒng)底層之靜態(tài)庫介紹
23.深入iOS系統(tǒng)底層之動態(tài)庫介紹
24.深入iOS系統(tǒng)底層之framework介紹
25.深入iOS系統(tǒng)底層之基地址介紹
26.深入iOS系統(tǒng)底層之模塊內(nèi)函數(shù)調(diào)用介紹
27.深入iOS系統(tǒng)底層之模塊間函數(shù)調(diào)用介紹
28.深入iOS系統(tǒng)底層之機(jī)器指令動態(tài)構(gòu)造介紹
29.深入iOS系統(tǒng)底層之crash問題解決方法
30.深入iOS系統(tǒng)底層之無上下文crash解決方法
31.深入iOS系統(tǒng)底層之常用工具和命令的實現(xiàn)原理介紹
32.深入iOS系統(tǒng)底層之真實的OC類內(nèi)存結(jié)構(gòu)介紹
歡迎大家訪問我的github地址和簡書地址
本文名稱:深入iOS系統(tǒng)底層之指令集介紹
當(dāng)前網(wǎng)址:http://aaarwkj.com/article2/ijheic.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站排名、網(wǎng)站策劃、、網(wǎng)站改版、網(wǎng)站導(dǎo)航、微信公眾號
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)