GCC中SIMD指令的應用方法

X86架構上的多媒體應用開發,如果能夠使用SIMD指令進行優化, 性能將大大提高。目前,IA-32的SIMD指令包括MMX,SSE,SSE2等幾級。 在GCC的開發環境中,有幾種使用SIMD指令的方式,本文逐一介紹。

X86的SIMD指令 ...simd instrucitons in X86

IA-32 Intel體系結構的指令主要分為以下幾類 [1]

  • 通用
  • x87 FPU
  • MMX技術
  • SSE/SSE2/SSE3擴展

MMX/SSE類擴展引入了SIMD(單指令多數據)的執行模式,可用于加速多媒體應用。 下面簡要介紹一下這些指令的執行環境和特征。

  • 8個32位通用寄存器可為各個SIMD擴展所使用;
  • MMX:8個64位MMX寄存器(mm0 - mm7),也可為各SSE擴展所使用;
    • 數據為整數,最多支持兩個32位
    • 運算中沒有寄存器能夠進行溢出指示
  • SSE:8個128位xmm寄存器,MXSCR寄存器,EFLAGS寄存器
    • 支持單精度浮點
    • MXSCR含有rounding, overflow標志
    • 支持64位SIMD整數
  • SSE2:執行環境同sse
    • 雙精度浮點
    • 128位整數
    • 雙—單精度轉換
  • SSE3:與Inte Prescott處理器一同發布不久,共13條指令
    • 主要增強了視頻解碼、3D圖形優化和超線程性能

MMX技術出現最早,目前幾乎所有的X86處理器都提供支持,包括嵌入式X86, 所以下面的討論主要基于MMX,但方法完全適用于SSEn, 包括像AMD的3D Now等其它SIMD擴展。

MMX指令又分為以下幾種:

  • 數據傳送:movd, movq
  • 數據轉換:packsswb, packssdw, packuswb, punpckhbw, punpckhwd, punpckhdq, punpcklbw, punpcklwd, punpckldq
  • 并行算術:paddb, paddw, paddd, paddsb, paddsw, paddusb, paddusw, psubb, psubw, psubd, psubsb, psubsw, psubusb, psubusb, psubusw, pmulhw, pmullw, pmaddwd
  • 并行比較:pcmpeqb, pcmpeqw, pcmpeqd, pcmpgtb, pcmpgtw, pcmpgtd
  • 并行邏輯:pand, pandn, por, pxor
  • 移位與旋轉:psllw, pslld, psllq, psrlw, psrld, psrlq, psraw, psrad
  • 狀態管理:emms

這些指令除了需要注意功能外,還需要注意處理的數據類型。以上內容為背景介紹,細節請參考手冊。





性能優化 ...Performance Optimization

當使用C/C++完成了一個嵌入式應用的所有功能,性能問題常擺在面前, 這時可以使用profile工具(如gprof)找出產生瓶頸的函數, 將這些函數使用匯編徹底重寫, 例如MPEG-4編解碼器xvid項目 [4]就使用了這種方法, 而且針對不同處理器/指令集分別給出了不同的優化, 正是如此該項目無論功能、還是性能均為一流, 顯然這是深度優化的目標所在。

在使用流水線、VLIW以及SIMD的體系結構(比如某些DSP)上, 整個函數的手工優化可以帶來幾倍到幾十倍的性能提升。 不過,性能允許,對于函數內關鍵部分使用一些特定的實現, 既突出重點提高性能,又可以盡多地利用C/C++的高級特征, 相對縮短開發周期。 下面給出使用GCC時,應用MMX指令的幾種混合編程方法:

  • Intel C/C++ 編譯器intrinsics
  • GCC builtin操作
  • 嵌入匯編asm construct




Intel C/C++ 編譯器intrinsics ...Intel C/C++ Compiler Intrinsics

查看IA-32 Intel指令集手冊 [2]時, 部分指令的解釋中會有一項“Intel C/C++ Compiler Intrinsic Equivalent”, 會指出該指令對等的intrinsic。 intrinsic在C/C++程序中的語法是以函數形式出現, 編譯時可以直接翻譯為一條MMX指令(復合情況會生成最直接的幾條), 換言之,如果不使用intrinsic,可能需要多條C/C++語句完成, 而編譯器卻并不能保證將這幾條語句能夠生成這條最高效的MMX指令。 并不是每條MMX指令都有對等的intrinsic, 手冊的附錄中列出了所有的, 它們分為簡單型(simple)和復合型(composite)兩種, 每個簡單型的就是對應一條指令,而復合型則對應多條指令。

GCC支持Intel C/C++ Compiler Intrinsics。用法如下示例:


      #include <stdio.h>#include <xmmintrin.h> /*一定需要包括此頭文件*//*gcc -Wall -march=pentium4 -mmmx -o ins  mmx_ins.c*/int main(int argc,char *argv[]){ /*使用MMX做以下向量的點積*/short in1[] = {1, 2, 3, 4};short in2[] = {2, 3, 4, 5};int out1;int out2;__m64 m1;    /* MMX支持64位整數的mm寄存器 */__m64 m2;    /* MMX操作需要使用mm寄存器 */__m128 m128; /* for SSEn only*//*每次往mm寄存器裝入兩個short型的數,注意是兩個*/m1 = _mm_cvtsi32_si64(((int*)in1)[0]);m2 = _mm_cvtsi32_si64(((int*)in2)[0]); /*一條指令進行4個16位整數的乘加*//*生成兩個32位整數*/m2  = _mm_madd_pi16(m1, m2); /*將低32位整數放入通用寄存器*/out1 =  _mm_cvtsi64_si32(m2);/*將高32位整數右移后,放入通用寄存器*/m2  = _mm_slli_pi32(m2, 32);out2 =  _mm_cvtsi64_si32(m2);/*清除MMX狀態*/_mm_empty();/*將兩個32位數相加,結果為8*/out1 += out2;printf("a: %d/n", out1);return(0);}

幾點說明:

  • 即使你不是P4平臺,編譯時也請使用以下選項,
    /*gcc -Wall -march=pentium4 -mmmx -o ins mmx_ins.c*/
    否則,會出現如下類似信息:
    ...xmmintrin.h:34:3: #error "SSE instruction set not enabled"
  • 最終結果實際并沒有求得四對乘積的和,只是前兩對的, instrinsic _mm_cvtsi32_si64只向mm寄存器放入了低32位,高32位為零, 但mmx有指令movq可以做到64位的數據傳送,intrinsic沒有對應, 這也說明并不是所有的指令有等價的intrinsic。
  • 當計算的向量為兩對0x8000, 0x8000時,即(-2^15)*(-2^15) + (-2^15)*(-2^15) , 結果應該為 2^31,但計算出來的值是 -2^31, 因為發生了溢出,可程序無從知道。 這是使用MMX時,應特別注意的,計算溢出沒有任何標志位指示,一個極大的值變為極小,SSE對此做了改善。
  • 程序不再使用MMX之時,注意使用emms指令清除MMX狀態。




使用built-in操作 ...GCC built-in Operation

什么是built-in操作?就是對待MMX操作數,就如int, float等基本數據類型一般, 有相應定義的操作,如加(+)、減(-),或者數據類型之間的轉換。 詳細內容參考GNU GCC Manual[5] Extensions to the C Language Family4#4Built-in Functions4#4 X86 Built-in Functions一節。

一些MMX指令有其相應的built-in操作, 下面一段代碼為例:


      #include <stdio.h>/*無需特別的頭文件,built-in嘛*//* gcc -Wall  -o bins  builtinmmx.c*//*定義了一個vector數據類型,hi表示16位,4表示4個*/typedef int v4hi __attribute__ ((mode(V4HI)));/*定義了2個32位的vector類型,si表示32位*/typedef int v2si __attribute__ ((mode(V2SI)));int main(int argc,char *argv[]){ short pa[4] = {0x8000, 0x8000, 1, -1};short pb[4] = {0x8000, 0x7FFF, -1, -2};v4hi va, vb;v4hi vsum;va = ((v4hi*)pa)[0];vb = ((v4hi*)pb)[0];/* 4個16位進行飽和加 *///vsum = __builtin_ia32_paddsw(va, vb);/* 4個16位還可以直接進行加法,但不同于兩個long long相加 */vsum =  va + vb;/*vector的輸出還需要強制轉換為long long*/printf("...with MMX instructions...to compute vec_add: %llx /n", (long long)vsum);//結果1:0xfffd0000ffff8000//結果2:0xfffd0000ffff0000return(0);}

幾點說明:

  • 是的,這里built-in vector及其操作,隨著GCC的發展正在加強。如果需要使用以上范例,應使用GCC 3.4以上版本;
  • 使用builtin函數時,與intrinsic相似;但本質卻是不同,這里兩個向量使用‘+’操作就說明了vector也如其它數據類型一樣,編譯器直接支持,只不過這里的加法就是指四個單元數分別相加,低位單元的進位不會影響相鄰高位單元的數據;
  • vector還可以強制轉換為通用數據。




嵌入匯編 ...Inline asm

GCC一開始就允許C代碼中嵌入asm指令,并不只是針對MMX指令, 不過對于MMX技術,顯然也是一個很好的利用方法, 詳細的語法請參考GNU GCC手冊 [5], 或者GCC: The Complete Reference [6]''Inline Assembly''一節。 如下是一個點積的例子:


      #include <stdio.h>/** GCC -o ins  inlinemmx.c **/int main(int argc,char *argv[]){ int i;int result;short a[] = {1, 2, 3, 4, 5, 6, 7, 8};short b[] = {1, 1, 1, 1, 1, 1, 1, 1};printf("...with MMX instructions.../n");/*首先,將點積合累積寄存器清零,實際缺省就為0?*/asm("pandn %%mm5,%%mm5;"::);/*讀入a, b,每四對數相乘后分兩組相加,形成兩組和*//*這里的循環控制是C在做*/for(i = 0; i < sizeof(a)/sizeof(short); i += 4){asm("movq %0,%%mm0;/movq %1,%%mm1;/pmaddwd %%mm1,%%mm0;/paddd %%mm0,%%mm5; #相乘后相加 ":: "m" (a[i]), "m" (b[i]));}/*將兩組和分離,并相加*/asm("movq %%mm5, %%mm0;/psrlq $32,%%mm5;/paddd %%mm0, %%mm5;/movd %%mm5,%0;/emms":"=r" (result):);printf("result: 0x%x/n", result);//這里結果為0x24return(0);}

幾點說明:

  • 這里是典型的在函數中C和匯編混合編程;
  • 注意匯編指令中操作數的順序;
  • 這里可以直接使用movq等沒有intrinsics/built-in對應的指令;
  • 注意在asm指令序列中間不要加雜注釋,可能導致生成的代碼不正確。




MMX實用一例:合成濾波器 ...Synthesis Filter in X86 SIMD INSTRUCTIONS

下面是合成濾波器(Synthesis Filter)的一個優化過程, 合成濾波器在語音編解碼中有廣泛應用, 運行時也占用了整個算法中較高比例的時間。


      for (i = 0; i < lg; i++){s = L_mult(x[i], a[0]);/*L_mult是相乘后左移*/for (j = 1; j <= M; j++){/*M這里固定為10*/s = L_msu(s, a[j], yy[-j]);/*L_msu是乘減后左移操作*/}s = L_shl(s, 3); /*左移三位*/*yy++ = g729round(s);}#endif

上面的代碼,因為內存循環為10,可以考慮展開,并統一操作為乘加指令。


      /*為了使用乘加操作,需要調整10個系數的順序*/for(i = 0; i < M; i++)ta[i] = -a[M - i];ta[11] = 0;ta[10] = a[0];for (i = 0; i < lg; i++){*yy = x[i];yy[1] = 0;s = L_mac(s, ta[11], yy[1]);s = L_mac(s, ta[10], yy[0]);s = L_mac(s, ta[9], yy[-1]);s = L_mac(s, ta[8], yy[-2]);s = L_mac(s, ta[7], yy[-3]);s = L_mac(s, ta[6], yy[-4]);s = L_mac(s, ta[5], yy[-5]);s = L_mac(s, ta[4], yy[-6]);s = L_mac(s, ta[3], yy[-7]);s = L_mac(s, ta[2], yy[-8]);s = L_mac(s, ta[1], yy[-9]);s = L_mac(s, ta[0], yy[-10]);s = L_shl(s, 3);*yy++ = g729round(s);}

以上循環內核正好可以將MMX的8個寄存器全部利用。


      /*為了使用乘加操作,需要調整10個系數的順序*/for(i = 0; i < M; i++)ta[i] = -a[M - i];ta[11] = 0;ta[10] = a[0];/*11個系數分別放入3個MMX寄存器,0作填充*/asm("movq %0,%%mm0;/movq %1,%%mm1;/movq %2,%%mm2"/:/: "m" (ta[0]), "m" (ta[4]), "m"(ta[8]));/*利用MMX技術進行濾波器核心操作*/for (i = 0; i < lg; i++){*yy = x[i];yy[1] = 0;asm("pandn %%mm6,%%mm6;/movq %1,%%mm3;/movq %2,%%mm4;/movq %3,%%mm5;/pmaddwd %%mm0,%%mm3;/pmaddwd %%mm1,%%mm4;/pmaddwd %%mm2,%%mm5;/paddd %%mm3, %%mm6;/paddd %%mm4, %%mm6;/paddd %%mm5, %%mm6;/movq  %%mm6, %%mm7;/psrlq $32, %%mm6;/paddd %%mm7, %%mm6;/movd %%mm6,%0;/emms"::"r"(s), "m" (yy[-10]), "m" (yy[-6]), "m"(yy[-2]));/*因為指令結果飽和屬性的限制,s還沒有左移,所以下面多做一位飽和左移*/s = L_shl(s, 4);*yy++ = g729round(s);}

幾點說明:

  • 注意:以上嵌入的匯編代碼輸出結果s放在了輸入處,屬于實踐中的個案;
  • MMX沒有乘左移之類的DSP指令,甚至還沒有加飽和之類的操作,SSE中有一定增強;
  • 以上操作,理論上存在溢出可能,所以最后使用原有的飽和左移操作,減少了一定風險;
  • 上面的部分代碼操作顯然允許并行,這在VLIW系統中十分有用;
  • 這已經形成了該濾波器全面優化的核心。




總結 ...Conclusion

如果愿意盡多地利用SIMD技術,可能需要更多地使用匯編級的編碼, 不過也有一些高級語言和匯編的混合編程技術能夠幫助你, 它們有的提高性能更大一些, 有的形式上更優雅些,本質上效率也不錯, 都不失好的方法,建議嘗試。

正是如此,一方面CPU上支持越來越多的SIMD指令集擴展, 另一方面GCC也正在加緊支持這些擴展的易用,對,正在, 碰到一些問題,先想辦法繞過去, 這里使用GCC 3.4.1,根據經驗效果還是不錯的。





關于文檔

GCC中SIMD指令的應用方法

This document was generated using the LaTeX2HTML translator Version 2002 (1.62)

Copyright ? 1993, 1994, 1995, 1996, Nikos Drakos, Computer Based Learning Unit, University of Leeds.
Copyright ?, 1998, 1999, Ross Moore, Mathematics Department, Macquarie University, Sydney.

The command line arguments were: latex2html -iso_language CN -html_version 4.0,unicode -address '?2004 CoreUp Designs' -local_icons -split 0 -nonavigation gccsimd

The translation was initiated by on 2004-12-13





參考資料

  1. Intel: IA-32 Intel Architechture Software Developer's Manual, Volume 1: Basic Architecture(2002)
  2. Intel: IA-32 Intel Architechture Software Developer's Manual, Volume 2: Instruction Set Reference(2003)
  3. Intel: IA-32 Intel Architechture Software Developer's Manual, Volume 3: System Programming Guide(2003)
  4. XviD.org,http://www.xvid.org/(up-to-date)
  5. GNU, GCC online documentation, http://www.gnu.org/software/GCC/onlinedocs/(up-to-date)
  6. Authur Griffith, GCC: The Complete Referencea, McGraw Hill(2002)




關于作者

?

錢浙濱,1999年從上海交通大學圖像處理與模式識別研究所獲得博士學位, 曾參與完成計算機視覺、正規語言和移動通信等方面的研發工作; 目前他和他的團隊主要從事DSP系統開發,特別是多媒體編解碼算法的性能優化, 以及相關的Linux嵌入式應用; 他們也提供WLAN相關的技術咨詢, 歡迎訪問http://embeddedcore.com進行交流。


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/454169.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/454169.shtml
英文地址,請注明出處:http://en.pswp.cn/news/454169.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

使用angular4和asp.net core 2 web api做個練習項目(二), 這部分都是angular

上一篇: http://www.cnblogs.com/cgzl/p/7755801.html 完成client.service.ts: import { Injectable } from angular/core; import { Http, Headers } from angular/http; import { Observable } from rxjs/Observable; import { ErrorHandler } from angular/core; import rxj…

leelen可視對講怎么接線_樓宇對講系統怎么布線 樓宇對講系統布線方式【介紹】...

隨著智能小區規模不斷增加&#xff0c;樓宇可視對講系統應用越來越廣泛&#xff0c;因而視頻信號的傳輸方式與布線設計顯得越來越重要。視頻信號與數據和音頻信號不同&#xff0c;可行的一種傳輸方式為視頻信號基帶傳輸&#xff0c;下面小編就簡要介紹一下這種傳輸方式和布線方…

路由匯總實例

5.2.2.2 路由匯總策略 之前提到過&#xff0c;在網絡管理員計劃好子網選擇并進行預期地路由匯總時&#xff0c;手動路由匯總工作能取得最佳效果。例如&#xff0c;之前的例子設定好了一個考慮周全的計劃&#xff0c;管理員只使用遠離Yosemite路由器并以10.2開頭的子網。這個規定…

《操作系統》OS學習(五):連續內存分配 內存碎片、動態分配、碎片整理、伙伴系統

內存碎片 在沒有其他方式輔助的情況下&#xff0c;我們分配給一個進程的內存是連續的。在分配時候我們需要有動態分配與碎片處理。如何理解呢&#xff1f;就是每個進程需要一塊內存&#xff0c;我們要選取合適的位置的內存分配給它。當有的進程先結束了內存還給操作系統&#…

GCC 中文手冊 - 摘自純C論壇

GCC Section: GNU Tools (1) Updated: 2003/12/05 Index Return to Main Contents NAME gcc,g-GNU工程的C和C編譯器(egcs-1.1.2) 總覽(SYNOPSIS) gcc[option|filename ]... g[option|filename ]... 警告(WARNING) 本手冊頁內容摘自GNU C編譯器的完整文檔,僅限于解釋選項的含義…

python如何實現支持中文

#codingutf-8print("我要python支持中文") 默認情況下&#xff0c;python是不支持中文的。 如果要實現python支持中文&#xff08;我是從python3.6開始學習的&#xff09;&#xff0c;只要在python文檔的開頭加入&#xff1a;“#codingutf-8"就可以了。轉載于:h…

世界之窗瀏覽器刪除文本框信息_文本框——Excel里的便利貼

工作表里面的單元格應該是足夠我們來記錄數據和信息了。但是文本框這個功能在工作表中還是存在&#xff0c;可以理解為便利貼功能。插入文本框1.點擊“插入”選項卡。2.然后點擊“文本框”。3.在下拉菜單里面&#xff0c;有兩種可供選擇&#xff1a;橫排文本框和垂直文本框。在…

RHEL 5服務篇—常用網絡配置命令

常用網絡配置命令 在“Linux系統管理”的文章中&#xff0c;大家已經學習了Linux系統的基本管理命令和技巧&#xff0c;為了進一步學習Linux網絡服務打下了良好的基礎。所以我作者以后將陸續推出Linux網絡服務的相關文章。希望大家能給與我大大的支持。 今天我們就來學習一下…

清華大學《操作系統》(六):非連續內存分配 段式、頁式、段頁式存儲管理

背景 連續內存分配給內存分配帶來了很多不便&#xff0c;可能所有空閑片區大小都無法滿足需求大小&#xff0c;這個分配就會失敗。基于這種現狀&#xff0c;就有了非連續內存分配的需求。非連續分配成功的幾率更高&#xff0c;但也面對更多的問題&#xff0c;比如分配時是不是…

python監控文件內容變化_Python監控文件內容變化

{"moduleinfo":{"card_count":[{"count_phone":1,"count":1}],"search_count":[{"count_phone":4,"count":4}]},"card":[{"des":"阿里云文件存儲NAS是一個可共享訪問&#xf…

C語言第三次博客作業---單層循環結構

一、PTA實驗作業。 題目1 1.實驗代碼 int n,i; double height1,height2;//1為輸入身高&#xff0c;2為輸出身高。 char sex; //1<height1<3; //N<1; scanf("%d",&n); while(n--){getchar();scanf("%c%lf",&sex,&height1);switch(sex)…

函數和函數式編程

python的過程就是函數&#xff0c;因為解釋器會隱式地返回默認值None。 實際編程中大部分偏函數更接近過程&#xff0c;不顯示地返回任何東西。 當沒有顯示地返回元素或者如果返回None時&#xff0c;python會返回一個None。 * 元組 ** 字典 def子句的剩余部分包括了一個雖…

清華大學《操作系統》(七):虛擬存儲、覆蓋、交換

接下來幾節都是對虛擬存儲的講解。虛擬存儲是非連續存儲管理的擴展。通過將內存中的數據暫存到外存的方式&#xff0c;為進程提供更大的內存空間。虛擬存儲出現的主要原因是因為程序規模的增長速度遠遠大于存儲器容量的增長速度&#xff0c;導致內存空間不夠用。其實針對內存空…

遵義大數據中心項目工程概況_市委書記張新文到曹州云都大數據中心等項目現場調研建設情況...

4月25日&#xff0c;市委書記張新文到曹縣調研重點項目建設情況&#xff0c;研究推進措施。市委常委、秘書長任仲義參加活動。張新文首先來到曹州云都大數據中心項目建設現場&#xff0c;查看項目推進情況。曹州云都大數據中心&#xff0c;是涵蓋云計算區、研發辦公區、公寓生活…

linux 可執行文件的分析(gcc GUN BUILEIN)

1、GCC The History of GCC 1984年&#xff0c;Richard Stallman發起了自由軟件運動&#xff0c;GNU (Gnus Not Unix)項目應運而生&#xff0c;3年后&#xff0c;最初版的GCC橫空出世&#xff0c;成為第一款可移植、可優化、支持ANSI C的開源C編譯器。GCC最初的全名是GNU C Com…

Cassandra 的數據存儲結構——本質是SortedMapRowKey, SortedMapColumnKey, ColumnValue

Cassandra 的數據存儲結構 Cassandra 的數據模型是基于列族&#xff08;Column Family&#xff09;的四維或五維模型。它借鑒了 Amazon 的 Dynamo 和 Googles BigTable 的數據結構和功能特點&#xff0c;采用 Memtable 和 SSTable 的方式進行存儲。在 Cassandra 寫入數據之前&a…

清華大學《操作系統》(八):置換算法

功能&#xff1a;置換算法是指當出現缺頁異常時&#xff0c;需要調入新頁面而內存已滿時&#xff0c;置換算法選擇被置換的物理頁面。 設計目標&#xff1a; 盡可能減少頁面的調入調出次數&#xff1b;把未來不再訪問或短期內不訪問的頁面調出。 頁面鎖定&#xff1a; 了解具…

python email模塊詳解_python模塊之email: 電子郵件編碼解碼 (一、解碼郵件)

python自帶的email模塊是個很有意思的東西&#xff0c;它可以對郵件編碼解碼&#xff0c;用來處理郵件非常好用。處理郵件是一個很細致的工作&#xff0c;尤其是解碼郵件&#xff0c;因為它的格式變化太多了&#xff0c;下面先看看一個郵件的源文件&#xff1a;Received: from …

爛泥:通過vsphere給esxi添加本地硬盤

公司ESXi服務器的硬盤空間不夠使用&#xff0c;現在新加了一塊硬盤在ESxi服務器上。在服務器上添加完硬盤后&#xff0c;在Vsphere上是看不到新加硬盤的。 下面我們來通過虛擬機模擬該情況&#xff0c;先添加一塊硬盤。如下圖&#xff1a; 在Esxi添加完硬盤后&#xff0c;現在通…

清華大學《操作系統》(九):進程和線程

進程 定義&#xff1a; 進程是指一個具有一定獨立功能的程序在一個數據集合上的一次動態執行的過程。 組成&#xff1a; 代碼數據狀態寄存器&#xff08;正在運行的一個程序的所有狀態信息&#xff09;&#xff1a;CPU狀態CP0、指令指針IP通用寄存器&#xff1a;AX、BX、CX…