微機原理教案準備_第1頁
微機原理教案準備_第2頁
微機原理教案準備_第3頁
微機原理教案準備_第4頁
微機原理教案準備_第5頁
已閱讀5頁,還剩90頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領

文檔簡介

3.1指令系統(tǒng)概述指令系統(tǒng)是微處理器所能執(zhí)行的各種指令的集合,定義了一個微處理器所能完成的基本操作。不同的微處理器具有不同的指令系統(tǒng),本章以Intel公司的8086為例來介紹微處理器的指令系統(tǒng)。采用8086CPU的指令系統(tǒng)作為范例的原因有以下幾點:(1)應用的廣泛性。幾乎所有的微機系統(tǒng)使用的都是x86系列的CPU(主要生產(chǎn)廠家有Intel公司和AMD公司)。(2)指令的兼容性。8086的指令系統(tǒng)是所有x86系列CPU的指令系統(tǒng)的基礎,編寫的程序可以直接在80286、80386乃至Pentium、Core2Duo上執(zhí)行。(3)資料的豐富性。x86系列CPU普及程度極廣,其相關技術資料很容易找到,給應用開發(fā)帶來很大方便。(4)與課程內(nèi)容配合?!編讉€概念】指令——控制CPU完成指定操作的命令。機器指令——指令的二進制代碼形式。例如:1100110100100001(或表示成十六進制形式為:CD21H)。匯編指令——助記符形式的指令。例如:INT21H。指令系統(tǒng)——CPU的所有指令及其使用規(guī)則的集合。8086指令按功能分為六大類(92種),下表列出了最常用的一些指令。8086CPU常用指令一覽表指令類型助記符數(shù)據(jù)傳送一般數(shù)據(jù)傳送MOV,PUSH,POP,XCHG,XLAT輸入輸出指令IN,OUT地址傳送指令LEA,LDS,LES標志傳送指令PUSHF,POPF算術運算加法指令ADD,ADC,INC減法指令SUB,SBB,DEC,CMP乘、除法指令MUL,DIV十進制調(diào)整指令DAA,AAA,DAS,AAS,AAM,AAD邏輯運算和移位AND,OR,NOT,XOR,TESTSHL,SAL,SHR,SAR,ROL,ROR,RCL,RCR串操作MOVS,CMPS,SCAS,LODS,STOS控制轉移JMP,條件轉移指令(Jxx),LOOP/LOOPE/LOOPNEINT/IRET,CALL/RET處理器控制CLC,STC,CLD,STD,HLT3.1.1指令的基本組成指令分為操作碼(也稱為指令碼)和操作數(shù)兩個部分,操作碼表示這條指令所要進行的是什么樣的操作,操作數(shù)指示所要操作的對象。大多數(shù)8086指令的長度在1~4個字節(jié)之間,其長度與操作碼和指令中操作數(shù)的多少以及操作數(shù)的類型有關。操作數(shù)越多,指令就越長。8086指令系統(tǒng)規(guī)定,一條指令的操作數(shù)最多只能有兩個。1.指令格式8086CPU的指令格式如下:操作碼[目的操作數(shù)][,源操作數(shù)]其中:操作碼用便于記憶的助記符來表示(一般是英文單詞的縮寫)。操作數(shù)可以是雙操作數(shù)(源操作數(shù)和目的操作數(shù)),也可以是單操作數(shù),有的指令甚至可以不給出操作數(shù)(隱含操作數(shù))?!纠?】雙操作數(shù)的指令:MOVAX,BX;MOV是操作碼,AX是目的操作數(shù),BX是源操作數(shù)單操作數(shù)的指令:CALLproc1;CALL是操作碼,proc1是目的操作數(shù)無操作數(shù)的指令:STC;STC是操作碼2.操作數(shù)類型8086指令系統(tǒng)中的操作數(shù)主要分為三類:立即數(shù)操作數(shù)、寄存器操作數(shù)和存儲器操作數(shù)。1)立即數(shù)操作數(shù)

所謂立即數(shù)是指具有固定數(shù)值的操作數(shù),即常數(shù)。它可以是字節(jié)(8位)或字(16位),當它們分別代表無符號數(shù)和帶符號數(shù)時,其各自的取值范圍如下表所示。立即數(shù)操作數(shù)的取值范圍8位數(shù)16位數(shù)無符號數(shù)00H-0FFH(0~255)0000H-0FFFFH(0~65535)有符號數(shù)80H-7FH(-128~+127)8000H-7FFFH(-32768~+32767)立即數(shù)的取值超出了規(guī)定的范圍,就會發(fā)生錯誤。在指令中,立即數(shù)操作數(shù)只能用作源操作數(shù),而不能用作目的操作數(shù)?!纠?】MOVAX,1200H;正確,立即數(shù)可以用做源操作數(shù)MOV1200H,AX;錯誤,立即數(shù)不能用做目的操作數(shù)2)寄存器操作數(shù)寄存器操作數(shù)存放在8086CPU的8個通用寄存器或段寄存器中,既可以作為源操作數(shù),也可以用作目的操作數(shù)。通用寄存器中的AX、BX、CX、DX既可以作為四個16位寄存器,用來存放字操作數(shù),也可以當作八個8位寄存器(AH、AL、BH、BL、CH、CL、DH、DL),用來存放字節(jié)操作數(shù)。SI、DI、BP、SP只能存放字操作數(shù)。AX(16位)AX(16位)AH(8位)AL(8位)BX(16位)BH(8位)BL(8位)CX(16位)CH(8位)CL(8位)DX(16位)DH(8位)DL(8位)SI(16位)SI(16位)DI(16位)DI(16位)BP(16位)BP(16位)SP(16位)SP(16位)段寄存器用來存放當前操作數(shù)的段基地址。在與通用寄存器或存儲器傳送數(shù)據(jù)時,段寄存器可作為源操作數(shù)或目的操作數(shù)。CS(16位)CS(16位)DS(16位)ES(16位)SS(16位)段寄存器存放當前操作數(shù)的段基地址注意:1.不允許用一條指令把立即數(shù)傳送到段寄存器。如果需要這樣做,可用某個通用寄存器作為中間橋梁,用兩條傳送指令實現(xiàn)。2.不允許用傳送指令把某個值傳送給CS。3.僅有個別指令將標志寄存器FLAGS作為操作數(shù)?!纠?】MOVDS,1200H;錯誤,不允許把立即數(shù)傳送到段寄存器改為:MOVAX,1200H;正確,使用AX作為中介把立即數(shù)1200H送到DS寄存器MOVDS,AX【例4】MOVCS,AX;錯誤,不允許用顯式指令把值傳送給CS寄存器MOVFLAGS,AX;錯誤,不允許用數(shù)據(jù)傳送指令給標志寄存器賦值POPF;正確,可以把堆棧棧頂?shù)膬?nèi)容彈出到標志寄存器3)存儲器操作數(shù)存儲器操作數(shù)可以是字節(jié)(8位)、字(16位)或雙字(32位),分別要占據(jù)一個、兩個或四個存儲單元。存儲器操作數(shù)在指令中既可作為源操作數(shù),也可作為目標操作數(shù)。但對大多數(shù)指令,不允許源操作數(shù)和目標操作數(shù)同時為存儲器操作數(shù)。若確實要對兩個存儲器操作數(shù)進行操作,可以使用任一通用寄存器作為中間橋梁來實現(xiàn)。在匯編語言中,存儲器單元是用邏輯地址來制定的,而邏輯地址是由段基地址和偏移地址兩部分構成。所以,要訪問存儲器操作數(shù)必須首先確定操作數(shù)所在的段基地址。如上所說,段基地址是放在段寄存器中的,所以,訪問存儲器操作數(shù)前,應先確定對應的段寄存器是否已經(jīng)初始化為所需要的段基地址。那么,訪問存儲器操作數(shù)要使用四個段寄存器中的哪一個呢?8086CPU規(guī)定,若指令中沒有指明使用哪一個段寄存器的內(nèi)容作為段基地址來訪問存儲器操作數(shù),則根據(jù)操作數(shù)的特征來確定所使用的默認段寄存器。各種存儲器操作所約定的默認段寄存器、段超越(即顯式地指明段寄存器)所允許的段寄存器、以及相應的偏移地址來源見下表。段寄存器使用的一些基本約定存儲器操作類型默認的段寄存器允許超越的段寄存器段內(nèi)偏移地址來源取指令CS無IP堆棧操作SS無SP通用數(shù)據(jù)傳送DSCS,ES,SS按尋址方式取得串操作源串地址DSCS,ES,SSSI串操作目的串地址ES無DIBP作為基址寄存器SSCS,DS,ES按尋址方式取得【例5】MOVAL,[2A00H];通用數(shù)據(jù)傳送,用DS的內(nèi)容作為段基地址,偏移地址為2A00H

PUSHAX;堆棧操作,用SS的內(nèi)容作為段基地址,偏移地址在SP中

LODSW;串操作,用DS的內(nèi)容作為源串地址的段基地址,偏移地址在SI中

ADDAL,[BP+DI];BP作為基址寄存器,用SS的內(nèi)容作為段基地址,偏移地址為BP和DI之和3.1.2指令的執(zhí)行時間了解指令的執(zhí)行時間,對編寫時間敏感的程序是很重要的。例如:在用軟件產(chǎn)生定時或延時時或工業(yè)控制領域中對某些實時性要求較嚴的誠和,都需要估算出一段程序的運行時間。一條指令的執(zhí)行時間以時鐘周期數(shù)為單位。不同指令的執(zhí)行時間有較大的差別,這里列出了部分常用指令的執(zhí)行時間及其訪問存儲器的次數(shù)。常用指令執(zhí)行時間指令所需時鐘周期數(shù)訪問內(nèi)存次數(shù)MOV累加器到內(nèi)存內(nèi)存到累加器寄存器到寄存器內(nèi)存到寄存器寄存器到內(nèi)存10(14)10(14)28(12)+EA9(13)+EA11011MOV立即數(shù)到寄存器立即數(shù)到內(nèi)存寄存器到段寄存器內(nèi)存到段寄存器段寄存器到寄存器段寄存器到內(nèi)存410(14)+EA28(12)+EA29(13)+EA010101ADD或SUB寄存器到寄存器內(nèi)存到寄存器寄存器到內(nèi)存立即數(shù)到寄存器立即數(shù)到內(nèi)存39(13)+EA16(24)+EA417(25)+EA01202MUL累加器乘8位寄存器累加器乘16位寄存器累加器和內(nèi)存字節(jié)乘累加器和內(nèi)存字乘70~77118~133(76~83)+EA[124(128)~139(143)]+EA0011IMUL累加器乘8位寄存器累加器乘16位寄存器累加器和內(nèi)存字節(jié)乘累加器和內(nèi)存字乘80~98128~154(86~104)+EA[134(138)~160(164)]+EA0011DIV除數(shù)在8位寄存器中除數(shù)在16位寄存器中除數(shù)為8位內(nèi)存數(shù)除數(shù)為16位內(nèi)存數(shù)80~90144~162(86~96)+EA[150(154)~168(172)]+EA0011IDIV除數(shù)在8位寄存器中除數(shù)在16位寄存器中除數(shù)為8位內(nèi)存數(shù)除數(shù)為16位內(nèi)存數(shù)101~112165~184(107~118)+EA[171(175)~190(194)]+EA0011循環(huán)和移位在寄存器中移1位在寄存器中移若干位內(nèi)存數(shù)據(jù)移1位內(nèi)存數(shù)據(jù)移若干位28+4*位數(shù)15(23)+EA20(28)+EA+4*位數(shù)JMP段內(nèi)/段間直接轉移段內(nèi)間接轉移段間間接轉移158(12)+EA24(32)+EA條件轉移JCXZ6(不轉移)18(轉移)其它條件轉移指令Jxx4(不轉移)16(轉移)注:(1)表中EA表示偏移地址。小括號內(nèi)的數(shù)為8088進行字操作的時鐘數(shù)。因為8088的數(shù)據(jù)線只有8位,每個總線周期只能傳送一個字節(jié),所以對字操作要再加上4個時鐘周期。(2)對條件轉移指令,若條件滿足,執(zhí)行的時間比較長。因為要產(chǎn)生轉移,就要包括取下一條指令所需的時間。若條件不滿足,執(zhí)行時間就較短。因為此時不產(chǎn)生轉移,而是執(zhí)行下一條指令。存取操作數(shù)的時間與采用的尋址方式有關。寄存器尋址執(zhí)行的時間最短,而對存儲器操作數(shù)則還需考慮計算偏移地址所花的時間。這里列出了不同尋址方式下,計算偏移地址所需要的時間。計算偏移地址EA所需時間尋址方式計算EA所需時鐘數(shù)直接尋址6寄存器間接尋址5寄存器相對尋址9基址、變址尋址[BX+SI],[BX+DI]7[BP+SI],[BP+DI]8基址、變址加相對尋址[BX+SI+位移量],[BP+DI+位移量]11[BX+DI+位移量],[BP+SI+位移量]12注:若有段超越,則需再加上兩個時鐘周期??梢钥闯觯瑢ν环N指令,如果尋址方式不同,其指令執(zhí)行時間可能相差很大。寄存器操作數(shù)的指令執(zhí)行速度最快,立即數(shù)操作數(shù)次之,存儲器操作數(shù)指令的執(zhí)行速度最慢。這是由于寄存器位于CPU的內(nèi)部,執(zhí)行寄存器操作數(shù)指令時,8086的執(zhí)行單元(EU)可以直接從CPU內(nèi)部寄存器中取得操作數(shù),不需要訪問內(nèi)存,因此執(zhí)行速度很快。立即數(shù)操作數(shù)作為指令的一部分,在取指時已經(jīng)被8086總線接口單元(BIU)取出后存放在指令隊列中,執(zhí)行指令時也不需要訪問內(nèi)存,因而執(zhí)行速度也比較快。而存儲器操作數(shù)先要由總線接口單元計算出其所在單元的20位物理地址,然后再執(zhí)行存儲器的讀寫操作。所以相對前述兩種操作數(shù)來說,指令的執(zhí)行速度最慢?!纠慨斖ㄓ脭?shù)據(jù)傳送指令(MOV)的操作數(shù)分別為:寄存器、立即數(shù)和存儲器時,分別計算指令的執(zhí)行時間,已知CPU的時鐘頻率為5MHz。CPU的時鐘頻率為5MHz,即一個時鐘周期為0.2μs。則從寄存器到寄存器之間的傳送指令的執(zhí)行時間為:

t=2×0.2=0.4μs立即數(shù)傳送到寄存器的指令執(zhí)行時間為:

t=4×0.2=0.8μs

而存儲器到寄存器的字節(jié)傳送,設存儲器采用基址、變址尋址方式,則指令執(zhí)行時間為:

t=(8+EA)×0.2=(8+8)×0.2=3.2μs從上例可以看出,不同類型的尋址方式或不同類型的操作數(shù)可以導致指令執(zhí)行時間相差一個數(shù)量級,因此,我們在編寫程序時:1)盡量使用寄存器作為操作數(shù);2)盡量使用簡單的尋址方式。3.28086的尋址方式尋址方式,主要是指獲得操作數(shù)所在的地址的方法。在8086系統(tǒng)中,一般將尋址方式分為兩大類,一類是尋找操作數(shù)的地址,另一類是尋找要執(zhí)行的下一條指令的地址,即程序的地址。后者主要在程序轉移或過程調(diào)用時用來尋找目的地址或入口地址,這將在調(diào)用指令(CALL)和程序轉移指令(JMP)中介紹。本節(jié)我們主要討論針對操作數(shù)地址的尋址方式。在8086指令系統(tǒng)中,基本的尋址方式有7種,另外通常也把隱含尋址也當作是一種不同的尋址方式:①立即尋址

②直接尋址

③寄存器尋址

④寄存器間接尋址⑤寄存器相對尋址⑥基址變址尋址⑦基址變址相對尋址⑧隱含尋址8086尋址方式一覽表尋址方式名稱源操作數(shù)的例子源操作數(shù)的允許形式立即操作數(shù)立即尋址MOVAX,1200H指令中的常數(shù)寄存器操作數(shù)寄存器尋址MOVAX,BX通用寄存器或段寄存器存儲器操作數(shù)直接尋址MOVAX,[1200H]“[常數(shù)]”或“[變量]”或“變量”寄存器間接尋址MOVAX,[DI][BX、BP、SI、DI之一]寄存器相對尋址MOVAX,[BX+1200H][BX、BP、SI、DI之一+位移量]基址變址尋址MOVAX,[BX+DI][BX或BP+SI或DI]基址變址相對尋址MOVAX,[BX+DI+1200H][BX或BP+SI或DI+位移量]3.2.1立即尋址(ImmediateAddressing)要點:?操作數(shù)直接在指令中給出?只適用于源操作數(shù)立即尋址方式中,操作數(shù)是一個常數(shù)(也稱為立即數(shù))。操作數(shù)作為指令的一部分,緊跟在指令的操作碼之后(見例2圖(a)),存放于內(nèi)存的代碼段中。并在CPU取指令時隨指令碼一起取出。立即數(shù)可以是8位或16位的整數(shù)。注意:立即尋址方式只適用于源操作數(shù)。【例1】MOVAX,1C8FH;正確,把16位二進制數(shù)1C8FH送到AX寄存器中

ADDBYTEPTR[2A00H],8FH;正確,把8位二進制數(shù)8FH累加到2A00H內(nèi)存單元中

MOV2A00H,AX;錯誤,立即數(shù)不能作為目的操作數(shù)【例2】指令“MOVAX,3102H”將16位的立即數(shù)3102H送入累加器AX。指令執(zhí)行后,AH=31H,AL=02H。這是一條三字節(jié)指令,指令在存儲器中的存放形式及其執(zhí)行情況如下圖(b)所示。......操作碼操作數(shù)高8位操作數(shù)低8位.........(b)代碼段...MOV操作碼31H02H.........存儲器代碼段(a)存儲器AHALAX3.2.2直接尋址(DirectAddressing)要點:?指令中直接給出操作數(shù)的偏移地址(形式上為一個16位二進制數(shù))直接尋址指令是在指令的操作碼后面中直接給出操作數(shù)的16位偏移地址,偏移地址也稱為有效地址(EA,EffectiveAddress),該地址與指令的操作碼一起存放在內(nèi)存的代碼段,按低8位-高8位的順序存放,取指令時與指令操作碼一起被送入CPU。直接尋址指令中,默認使用DS寄存器作為操作數(shù)的段基址寄存器。當然也可以顯式地指定使用其他段寄存器——稱為段超越前綴,如下例中第二條指令中的“ES:”?!纠?】MOVAX,[2A00H];將內(nèi)存中從DS:2A00H開始的連續(xù)兩個字節(jié)的內(nèi)容傳送到AX寄存器

MOVDX,ES:[8000H];將內(nèi)存中從ES:8000H開始的連續(xù)兩個字節(jié)的內(nèi)容傳送到AX寄存器

MOVSI,BUFFER;將內(nèi)存中從DS:BUFFER開始的連續(xù)兩個字節(jié)的內(nèi)容傳送到SI寄存器上述第三條指令中的BUFFER這種形式的地址稱為符號地址——用符號來表示一個具體的偏移地址。注意:請仔細區(qū)別直接尋址指令與立即尋址指令二者的不同。直接尋址指令中的數(shù)值是操作數(shù)的16位偏移地址,而不是操作數(shù)本身。為了區(qū)分二者,指令系統(tǒng)規(guī)定偏移地址是一個數(shù)字時要加上方括號(符號地址可省略方括號)。【例2】指令“MOVAX,[3102H]”將數(shù)據(jù)段中偏移地址為3102H和3103H兩個單元中的內(nèi)容送到AX。如果(DS)=2000H,則所訪問的操作數(shù)的物理地址為:20000H+3102H=23102H指令執(zhí)行后:AX=1122H。指令的執(zhí)行情況如下圖所示。......MOV操作碼31H02H...22H...存儲器數(shù)據(jù)段AHALAX11H代碼段23103H23102H另外,若操作數(shù)不是存放在DS段,則在指令中要使用段超越前綴加以聲明?!纠?】指令“MOVBX,ES:[1200H]”用ES寄存器中的內(nèi)容作為段基地址,將偏移地址為1200H和1201H兩單元的內(nèi)容送到BX寄存器中。3.2.3寄存器尋址(RegisterAddressing)要點:?操作數(shù)放在某個寄存器中寄存器尋址方式中,操作數(shù)放在CPU的某個寄存器中,它可以是通用寄存器(8位或16位),也可以是基址寄存器(BX,BP)、變址寄存器(SI,DI)或段寄存器。注意:寄存器尋址指令在取操作數(shù)時不需要訪問存儲器,因此與段地址無關,故指令中不可以使用段超越前綴?!纠?】MOVAX,BX;將BX寄存器的內(nèi)容傳送到AX寄存器

MOV[3F00H],AX;將AX寄存器的內(nèi)容傳送到從DS:3F00H開始的連續(xù)兩個內(nèi)存單元

MOVCL,AL;將AL寄存器的內(nèi)容傳送到CL寄存器

MOVAX,BL;錯誤,源操作數(shù)和目的操作數(shù)的字長不同

MOVES:AX,DX;錯誤,寄存器尋址不能使用段超越前綴【例2】指令“MOVSI,AX”將AX的內(nèi)容送到寄存器SI中。若指令執(zhí)行前AX=2233H,SI=4455H,則指令執(zhí)行后SI=2233H,而AX中的內(nèi)容保持不變,仍為2233H。4455H4455H2233HSIAX執(zhí)行前2233H2233H2233H執(zhí)行后SIAX采用寄存器尋址時,操作數(shù)在CPU的寄存器中,指令在執(zhí)行時不必通過訪問內(nèi)存就可取得操作數(shù),故執(zhí)行速度較快。3.2.4寄存器間接尋址(RegisterIndirectAddressing)要點:?操作數(shù)的偏移地址放在寄存器中?只有SI、DI、BX和BP可作間址寄存器寄存器間接尋址與寄存器尋址方式不同,指令中指定的寄存器的內(nèi)容不是操作數(shù),而是操作數(shù)的偏移地址。也就是說操作數(shù)的偏移地址放在寄存器中,操作數(shù)本身則在存儲器中。用來做間接尋址的寄存器有時也稱為指針寄存器,或簡稱指針(試比較C語言中的指針)。寄存器間接尋址方式可用的寄存器只允許是SI、DI、BX和BP,統(tǒng)稱為間址寄存器。選擇不同的間址寄存器,涉及的段寄存器將有所不同。在默認情況下,用SI、DI、BX作間址寄存器時,操作數(shù)在數(shù)據(jù)段,段基地址由DS決定;用BP作間址寄存器,則操作數(shù)在堆棧段,段基地址由SS決定。但無論選擇哪一個間址寄存器,都允許段超越,即可在指令中用段超越前綴指明當前操作數(shù)在哪一個段。注意:因為間址寄存器中放的是操作數(shù)地址,所以用作間址的寄存器必須加上方括弧,以避免與寄存器尋址混淆。【例1】MOVAX,[BX];以BX的內(nèi)容為偏移地址,DS的內(nèi)容為段地址,取出一個字到AX寄存器MOVSI,[BP];以BP的內(nèi)容為偏移地址,SS的內(nèi)容為段地址,取出一個字到SI寄存器MOVCL,CS:[DI];使用段超越前綴,所要訪問的數(shù)據(jù)在代碼段中MOVAX,[DX];錯誤,DX不能用作間址寄存器MOVCL,[AX];錯誤,AX不能用作間址寄存器【例2】指令“MOVAX,[SI]”的尋址過程示例。已知DS=6000H,SI=1200H,(61200H)=44H,(61201H)=33H,則指令執(zhí)行后,AX=3344H。指令的執(zhí)行情況如下圖所示。.........44H...存儲器數(shù)據(jù)段33H44HAX33H61201H61200H6000DS1200SI60000+120061200地址因為指令中沒有指定段超越,所以尋址時使用默認的段寄存器DS。若操作數(shù)所在段的段地址在ES中,則本例中的指令應寫成:MOVAX,ES:[SI]。3.2.5相對的寄存器間接尋址(RelativeRegisterIndirectAddressing)要點:?操作數(shù)的偏移地址=間址寄存器的內(nèi)容加上8/16位的位移量?只有SI、DI、BX和BP可作間址寄存器相對的寄存器間接尋址簡稱為寄存器相對尋址,在這種尋址方式中,操作數(shù)存放在存儲器中,而其偏移地址等于指令中給出的間址寄存器的內(nèi)容與給出的8/16位的位移量之和。操作數(shù)的段由哪個段寄存器指定,仍由所使用的間址寄存器決定。位移量也可看作相對值,故把這種帶位移量的寄存器間接尋址方式稱為寄存器相對尋址。有時,尋址方式中的基本偏移量也稱為基地址。至于位移量和基地址哪個放在間址寄存器中,哪個作為位移量可任意,因為最終總是由二者相加得到偏移地址。點擊觀看相對寄存器尋址的動畫演示。【例1】MOVAX,[BX+8];操作數(shù)的偏移地址為BX的內(nèi)容加上8,段地址在DS中

MOVCX,TABLE[SI];TABLE是用符號表示的基地址,位移量在SI中

MOVAX,[BP+1000H];操作數(shù)的偏移地址為BP的內(nèi)容加上1000H,段地址在SS中注意:以上指令中的地址表達式有兩種不同的寫法,它們都是正確的?!纠?】指令MOVAX,BUFF[BX]的操作。假定DS=6000H,BX=1000H,BUFF=2A00H,(63A00H)=66H,(63A01H)=55H。物理地址=60000H+1000H+2A00H=63A00H.........66H...存儲器數(shù)據(jù)段55H66HAX55H63A01H63A00H60000(DS)1000(BX)+2A00(BUFF)63A00地址指令執(zhí)行后:AX=5566H寄存器相對尋址常用于存取表格或一維數(shù)組中的元素——把表格的起始地址作為基地址,用元素的下標計算出位移量,即可存取表格中的任意一個元素。位移量的計算方法是:位移量=下標×每個元素的字節(jié)數(shù)注:經(jīng)常也會把表格的起始地址作為位移量,把元素的下標計算出來的值作為基地址?!纠?】某數(shù)據(jù)表的首地址(偏移地址)為TABLE,要取出該表中的第10個元素(均為8位二進制數(shù))傳送到AL寄存器中,可用如下指令段實現(xiàn)

MOVSI,9;第10個數(shù)的下標為9(位移量是從0開始的)

MOVAL,TABLE[SI];第10個數(shù)的偏移地址為TABLE+9

如果該表中的每個元素占用兩個字節(jié)(16位),則上述指令段應改為MOVSI,9;第10個數(shù)的下標為9ADDSI,SI;每個元素占兩個字節(jié),所以用元素的下標乘2得到位移量(18)

MOVAL,TABLE[SI];第10個數(shù)的偏移地址為TABLE+18在匯編語言中,地址表達式的書寫格式允許有不同的形式。例如,以下幾種寫法本質上是完全等價的:

MOVAX,DATA[SI]

MOVAX,[SI]DATA

MOVAX,[DATA+SI]

MOVAX,[SI+DATA]

另外,在有些教科書中將使用BX、BP作為間址寄存器的寄存器相對尋址方式稱為基址尋址方式;而將使用SI、DI作為間址寄存器的寄存器相對尋址方式稱為變址尋址方式。3.2.6基址加變址尋址(IndexedBasedRegisterIndirectAddressing)要點:?操作數(shù)的偏移地址由一個基址寄存器的內(nèi)容和一個變址寄存器的內(nèi)容相加得到?地址表達式中只允許出現(xiàn)一個變址寄存器(SI或DI)和一個基址寄存器(BX或BP)基址加變址尋址方式中,操作數(shù)的偏移地址是由一個基址寄存器(BX或BP)的內(nèi)容和一個變址寄存器(SI或DI)的內(nèi)容相加而得到。注:1)在默認的情況下,指令中若用BX作基址寄存器,則段地址在DS中;而如果用BP作基址寄存器,則段地址在SS中?!梢允褂枚纬礁采w此規(guī)則。2)指令中不允許同時出現(xiàn)兩個基址寄存器或兩個變址寄存器?!纠?】MOVAX,[BX][SI];操作數(shù)的偏移地址由BX的內(nèi)容和SI的內(nèi)容相加得到

MOVAX,[BX+SI];同上,另一種格式

MOVAX,DS:[BP][DI];操作數(shù)的偏移地址由BP和DI的內(nèi)容相加得到,段基地址在DS中,而不是在SS中

MOVAX,[BX][BP];錯誤,地址表達式中不能出現(xiàn)兩個基址寄存器

MOVAX,[DI][SI];錯誤,地址表達式中不能出現(xiàn)兩個變址寄存器【例2】指令MOVAX,[BX][SI]的操作。假定DS=8000H,BX=2000H,SI=1000H。

物理地址=80000H+2000H+1000H=83000H

.........22H...存儲器數(shù)據(jù)段11H22HAX11H83001H83000H80000(DS)2000(BX)+1000(SI)83000地址指令執(zhí)行后:AX=1122H3.2.7相對的基址加變址尋址(IndexedBasedRelativeRegisterIndirectAddressing)要點:?操作數(shù)的偏移地址由基址寄存器的內(nèi)容、變址寄存器的內(nèi)容和一個8/16位的位移量三者相加得到?地址表達式中只允許出現(xiàn)一個變址寄存器(SI或DI)和一個基址寄存器(BX或BP)這種尋址方式事實上是基址加變址尋址方式的擴充。指令中指定了一個基址寄存器和一個變址寄存器,同時還給出一個8位或16位的位移量,將三者內(nèi)容相加就得到操作數(shù)的偏移地址。至于默認的段寄存器,仍由所使用的基址寄存器決定。指令允許使用段超越?!纠?】指令MOVAX,DATA[DI][BX]的尋址過程。假定DS=8000H,BX=2000H,DI=1000H,DATA=200H。

.........34H...存儲器數(shù)據(jù)段12H34HAX12H83201H83200H80000(DS)2000(BX)1000(DI)+200(DATA)83200地址指令執(zhí)行后,AX=1234H。與寄存器間接尋址方式類似,相對的基址加變址尋址同樣也可以表示成多種形式,例如:

MOVAX,DATA[SI][BX]

MOVAX,[BX+DATA][SI]

MOVAX,[BX+SI+DATA]

MOVAX,DATA[BX+SI]

同樣地,相對的基址加變址尋址也不允許在指令中同時出現(xiàn)兩個基址寄存器或兩個變址寄存器。下列指令格式是非法的:

MOVAX,DATA[SI][DI]

MOVAX,DATA[BX][BP]使用相對的基址-變址尋址方式可以很方便地訪問二維數(shù)組。方法如下:把數(shù)組在內(nèi)存中的首地址(偏移地址)作為位移量,元素所在行的行起始位移量放入基址寄存器,元素所在列的列位移量放入變址寄存器。然后在指令中使用相對的基址加變址尋址方式即可。(注:變址寄存器和基址寄存器可交換使用)【例2】二維數(shù)組A定義如下:A=A=183252409它在內(nèi)存中從地址Array開始按行存放:相對位移量Array+0+1+2+3+4+5+6+7+8...183252409...A[0,0]A[0,1]A[0,2]A[1,0]A[1,1]A[1,2]A[2,0]A[2,1]A[2,2]假定現(xiàn)在要取出A[1,2]送到AL寄存器中。根據(jù)上面介紹的方法:1)把數(shù)組在內(nèi)存中的首地址Array作為位移量2)元素所在行的行位移量=行號*每行元素個數(shù)*每元素字節(jié)數(shù)=1*3*1=3。完成行位移量計算的指令段如下:MOVAX,1;行號MOVCX,3;每行元素個數(shù)MULCX;行號*每行元素個數(shù),結果在AX中MOVCX,1;每元素字節(jié)數(shù)MULCX;行號*每行元素個數(shù)*每元素字節(jié)數(shù),結果在AX中MOVSI,AX;行位移量放入變址寄存器3)元素所在列的列位移量=列號*每元素字節(jié)數(shù)=2*1=2。完成列位移量計算的指令段如下:MOVAX,2;列號MOVCX,1;每元素字節(jié)數(shù)MULCX;列號*每元素字節(jié)數(shù),結果在AX中MOVBX,AX;列位移量放入基址寄存器然后用相對的基址加變址指令把A[1,2]傳送到AL寄存器:MOVAL,Array[SI][BX];等價于MOVAL,Array+5可以看出,存儲單元Array+5中的內(nèi)容就是元素A[1,2]。3.2.8隱含尋址要點:?指令中未顯式地給出操作數(shù),而是隱含的、固定的;?隱含尋址并非沒有操作數(shù),而是由于操作數(shù)固定,因此無需顯式地寫出。【例】指令MULBL的功能是把AL中的內(nèi)容與BL中的內(nèi)容相乘,乘積送到AX寄存器。即AL×BL→AX。這條指令隱含了被乘數(shù)寄存器AL及乘積寄存器AX。類似的指令還有:XLAT、IMUL、DIV、IDIV、CBW、CWD、MOVS、LODS、STOS、CMPS、SCAS等。3.2.9比例尋址要點:?比例尋址只適用于80386、80486及后續(xù)的x86系列CPU,如Pentium等。?比例尋址是指將基址寄存器或變址寄存器的內(nèi)容乘上一個比例因子。比例因子為1、2、4、8中的任一值?!纠縈OVAX,[ESI*8]MOVAX,[ESI*2+10]MOVAX,[EBX*4+EDX]MOVAX,[EBX+ESI*4+TABLE]可以看出,當比例因子為1時,上述指令與寄存器間接尋址、寄存器相對尋址、基址變址尋址、基址變址相對尋址等價。注:1)上述指令中,ESI、EBX等為32位寄存器。這樣的寄存器有8個:EAX、EBX、ECX、EDX、ESI、EDI、EBP、ESP,它們是8086通用寄存器的擴充。2)在80386以后的CPU中,8個32位通用寄存器都可以作為基址寄存器使用,除ESP外的其它7個32位通用寄存器都可以作為變址寄存器使用。3)在80386以后的CPU中,增加了FS和GS兩個段寄存器。4)在80386以后的CPU中,所有尋址方式中隱含的段寄存器取決于使用的基址寄存器:如果基址寄存器為ESP和EBP,則隱含的段寄存器為SS,其他情況下隱含的段寄存器為DS。5)如果地址表達式中有兩個寄存器,則不帶比例因子的寄存器是基址寄存器;如果兩個寄存器都不帶比例因子,則左邊的寄存器是基址寄存器。如果地址表達式中只有一個寄存器,則它就是基址寄存器。3.38086指令系統(tǒng)本節(jié)將詳細介紹8086指令系統(tǒng)。下面是本節(jié)中用到的一些符號及其含義。OPRD泛指各種類型的操作數(shù)

mem存儲器操作數(shù)

acc累加器操作數(shù)

dest目的操作數(shù)src源操作數(shù)

disp8位或16位偏移量,可用符號地址表示

DATA8位或16位立即數(shù)

PORT輸入/輸出端口,可用數(shù)字或表達式表示()表示寄存器的內(nèi)容或存儲單元的內(nèi)容

[]表示偏移地址請注意,以下通用規(guī)則對本節(jié)介紹的所有指令都適用:1)立即數(shù)不能作為目的操作數(shù)。2)CS和IP寄存器不能作為操作數(shù)使用(源和目的都不允許)。3)雙操作數(shù)指令中的兩個操作數(shù)不能都是存儲器(串操作指令除外),不能都是段寄存器,也不能一個是立即數(shù),一個是段寄存器。4)源操作數(shù)和目的操作數(shù)的類型至少有一個能夠確定。如果兩個都確定,則二者類型必須相同。5)雙操作數(shù)指令中,必須將目標操作數(shù)寫在前面,源操作數(shù)寫在后面,二者之間用逗號分隔。8086指令可分成以下6類:

數(shù)據(jù)傳送類算術運算類邏輯運算和移位類串操作類程序控制類處理器控制類3.3.1數(shù)據(jù)傳送指令要點:?數(shù)據(jù)傳送指令幾乎都是雙操作數(shù)指令,某些指令在形式上雖然為單操作數(shù),但實際上另一個操作數(shù)是隱含的。?數(shù)據(jù)傳送指令能夠將源操作數(shù)的內(nèi)容傳送到目的操作數(shù)中,或者將兩個操作數(shù)內(nèi)容進行交換。數(shù)據(jù)傳送指令是程序中使用最為頻繁的一類指令,無論什么樣的程序,都需要將原始數(shù)據(jù)、中間運算結果、最終結果及其它控制、狀態(tài)信息在CPU的寄存器和存儲器之間進行多次傳送。數(shù)據(jù)傳送指令能夠實現(xiàn)的操作如下圖:CSCS立即數(shù)(常數(shù)).........存儲器段寄存器DS、ES、SS通用寄存器請注意此圖中線段的方向!I/O端口僅累加器數(shù)據(jù)傳送類指令按功能又可分為四小類:?通用數(shù)據(jù)傳送?地址傳送?標志傳送?輸入輸出通用數(shù)據(jù)傳送要點:?數(shù)據(jù)傳送指令能夠將源操作數(shù)的內(nèi)容傳送到目的操作數(shù)中,或者將兩個操作數(shù)內(nèi)容進行交換。?一般情況下,通用數(shù)據(jù)傳送指令中的操作數(shù)是作為普通數(shù)據(jù)來對待的。?使用通用數(shù)據(jù)傳送指令時要注意指令語法規(guī)則。通用數(shù)據(jù)傳送指令包括一般傳送指令M0V、堆棧操作指令PUSH和P0P、交換指令XCHG、查表轉換指令XLAT和字位擴展指令CBW和CWD。①一般傳送指令MOV【格式及操作】MOVdest,src;dest←src【功能】將源操作數(shù)的內(nèi)容傳送到目的操作數(shù),而源操作數(shù)內(nèi)容保持不變。也就是說,MOV指令實際上是完成了一次數(shù)據(jù)的復制?!纠?】MOVAL,08H;AL←08HMOVBX,SI;BX←SI

M0VDS,AX;DS←AX

MOV[2000H],CH;(DS:2000H)←CH

MOV指令的操作數(shù)之一為存儲器時,若傳送的是字操作數(shù),那么將對連續(xù)兩個存儲器單元進行存取,字操作數(shù)的高8位對應存儲器的高地址單元,字操作數(shù)的低8位對應存儲器的低地址單元?!纠?】

M0V[BX],1234H;(DS:BX)←1234H。若DS=8000H,BX=08H,則指令執(zhí)行后,(80008H)=34H,(80009H)=12HMOVAX,[6000H];若(DS:6000H)=11H,(DS:6001H)=22H,則指令執(zhí)行后,AX=2211H數(shù)據(jù)傳送指令應遵循指令系統(tǒng)的通用規(guī)則。【例3】MOVAX,BL;錯誤!兩個操作數(shù)的類型必須相同

MOV[BX],[SI];錯誤!兩個操作數(shù)不能都是存儲器單元

MOVDS,1200H;錯誤!不允許把立即數(shù)直接傳送到段寄存器

MOVSS,ES;錯誤!兩個操作數(shù)不能都是段寄存器

MOVCS,AX;錯誤!CS寄存器不能作為目的操作數(shù)MOV10H,AL;錯誤!立即數(shù)不能作為目的操作數(shù)以上操作在規(guī)則上是不允許的,但如果我們確實要執(zhí)行這樣的操作,則可以用間接的方法實現(xiàn)。【例4】兩個存儲器單元之間的數(shù)據(jù)傳送可用以下方法實現(xiàn):MOVAX,[SI]MOV[BX],AX立即數(shù)傳送到段寄存器可用以下方法實現(xiàn):MOVAX,1200HMOVDS,AX段寄存器之間的數(shù)據(jù)傳送可用以下方法實現(xiàn):MOVAX,ESMOVSS,AX點擊這里查看更多的例子。[top]②堆棧操作指令PUSH/P0P堆棧的概念堆棧的操作為什么要按“后進先出(LIFO)”的方式工作呢?這是由于設置堆棧的目的決定的。我們知道,在運行一個主程序時,常常需要調(diào)用子程序或響應中斷而進入中斷服務程序,這都需要暫時停止正在執(zhí)行的程序,而轉去執(zhí)行子程序或中斷服務程序,但在子程序或服務程序執(zhí)行完后,必須能夠返回到主程序剛才被中斷的地方繼續(xù)執(zhí)行原來的程序。這就要求在轉子程序前必須保存返回地址(也稱斷點),即調(diào)用子程序(或中斷服務程序)的那條指令的下一條指令的CS和IP的內(nèi)容。另外,還要保存子程序中要用到的寄存器原來的值。這些內(nèi)容都要用堆棧來進行保存。在執(zhí)行子程序(或中斷服務程序)的過程中,有可能又會需要調(diào)用子程序(或中斷服務程序),如下圖所示,這就需要保護多個斷點,并保證能夠逐個正確返回,這意味著后保存的斷點地址應該先取出。這就是堆棧要按“后進先出”方式工作的原因。斷點1執(zhí)行子程序2斷點2主程序斷點1執(zhí)行子程序2斷點2主程序子程序1子程序調(diào)用示意圖子程序調(diào)用示意圖子程序2堆棧壓入數(shù)據(jù)時總是從高地址向低地址方向增長,從堆棧取數(shù)據(jù)時正好相反;堆棧操作以SS:SP為指針,堆棧指針SP總是指向棧頂,每壓入一個數(shù)據(jù),SP減2;每彈出一個數(shù)據(jù),SP加2;SP的初值決定了堆棧的大小,SP的值不允許小于零;堆棧的存取以字(16位二進制數(shù))為單位;堆棧指令中的操作數(shù)只能是寄存器或存儲器操作數(shù),而不能是立即數(shù)。

∶∶∶SSSP棧頂單元堆棧段堆棧增長方向低地址高地址存儲器(2)堆棧操作指令堆棧操作指令共有兩條,壓棧指令PUSH和彈出(出棧)指令POP。這兩條指令中都只需指明一個操作數(shù)即可,另一個操作數(shù)隱含為堆棧棧頂。

【格式及操作】PUSHsrc;src壓入堆棧,SP減2POPdest;棧頂內(nèi)容彈出到dest,SP加2【功能】PUSH指令把16位的操作數(shù)壓入棧頂,POP指令從棧頂彈出一個16位數(shù)據(jù)到目的操作數(shù)。這里,操作數(shù)src和dest可以是:

寄存器(包括數(shù)據(jù)寄存器、地址指針和變址寄存器);段寄存器(CS除外,PUSHCS指令是合法的,而P0PCS指令是非法的);

存儲器單元。無論是哪一種操作數(shù),其類型都必須是字操作數(shù)。若為寄存器,必須是16位寄存器;若為存儲器,則應是兩個地址連續(xù)的存儲單元。點擊觀看PUSH和POP指令動畫演示?!纠?】

PUSHAX;通用寄存器AX的內(nèi)容壓入堆棧PUSHBP;基址指針寄存器BP的內(nèi)容壓入堆棧

PUSHDATA[SI];兩個連續(xù)的存儲單元的內(nèi)容壓入堆棧

POPDS;棧頂內(nèi)容彈出到段寄存器DS中POP[BX];棧頂內(nèi)容彈出到兩個連續(xù)的存儲單元中【例6】若AX=1122H,則PUSHAX指令執(zhí)行前后的情況如下圖所示。yyyyxxSP堆棧段SS低地址高地址壓棧前yyxx11H22HSP堆棧段SS壓棧后1122HAX1122HAX-2【例6】若棧頂內(nèi)容為5678H,則POPAX指令執(zhí)行前后的情況如下圖所示。yyyyxx56H78HSP堆棧段SS低地址高地址出棧前yyxxSP堆棧段SS出棧后xxxxHAX5678HAX+2[top]③交換指令XCHG【格式及操作】XCHGOPRD1,OPRD2;(OPRD1)←→(OPRD2)【功能】將源操作數(shù)與目的操作數(shù)的內(nèi)容互相交換。交換指令對操作數(shù)的要求:源操作數(shù)和目的操作數(shù)均可以是寄存器或存儲器,但不能同時為存儲器。操作數(shù)不能為段寄存器?!纠?】設DS=2000H,SI=0200H,AL=11H,(20200H)=88H,則執(zhí)行指令“XCHG[SI],AL”后,AL=88H,(20200H)=11H。AL的內(nèi)容與(20230H)存儲單元的內(nèi)容進行了交換?!纠?】把AX和BX的內(nèi)容進行交換。XCHGAX,BX;注:也可以寫成XCHGBX,AX[top]④查表轉換指令XLAT【格式及操作】XLAT;AL←((BX)+(AL))或:XLATsrc_table;src_table為要查找的數(shù)據(jù)表的首地址【功能】以DS的內(nèi)容作為段地址,以BX+AL之和作為偏移地址,從該存儲器單元取出一個字節(jié)送到AL。XLAT指令可以根據(jù)數(shù)據(jù)表中元素的序號取出表中的相應元素(也可以看成是對一維數(shù)組的訪問)。指令的使用方法是:(1)在數(shù)據(jù)段中先定義數(shù)據(jù)表或一維數(shù)組(注意,數(shù)據(jù)表或數(shù)組中的元素必須是字節(jié)類型);(2)將表或數(shù)組的首地址(偏移地址)送到BX,要查找的元素的序號(下標)送AL(注:序號(下標)從0開始);(3)執(zhí)行XLAT指令,表或數(shù)組中指定序號(下標)的元素就被傳送到AL中。利用XLAT指令實現(xiàn)代碼轉換操作十分方便?!纠?】利用XLAT指令實現(xiàn)二進制數(shù)到ASCII碼的轉換。ASCIIDB30H,31H,32H,33H,34H,35H,36H,37HDB38H,38H,41H,42H,43H,44H,45H,46H...CONV:LEABX,ASCII;BX←ASCII碼表首地址M0VAL,8;假定要把8轉換為對應的ASCII碼(38H)XLAT;查表轉換執(zhí)行結果:AL=38H,即8所對應的ASCII碼。注意:因為轉換時使用AL存放元素的下標,所以轉換表長度最大為256個字節(jié)元素(即256個表項)。點擊觀看XLAT指令動畫演示。[top]⑤字位擴展指令CBW/CWD算術運算指令要求兩個操作數(shù)的字長必須滿足一定規(guī)則。例如:對加、減和乘法運算指令,兩個操作數(shù)必須等字長;而對除法運算指令,要求被除數(shù)的字長應為除數(shù)的兩倍。因此,有時需要將一個字節(jié)的數(shù)擴展為字,或將一個字的數(shù)擴展為雙字。但有符號數(shù)的擴展并非只是前面補零那么簡單,而是在擴展時應根據(jù)符號位決定前面補為全零還是補為全1,即將符號位擴展到整個高8位(或高16位)。例如,要把有符號數(shù)24H擴展為一個字,則結果為0024H;而如果要擴展的數(shù)是84H,則結果為FF84H。擴展指令共有兩條:CBW和CWD,這兩條指令都是隱含操作數(shù)指令?!靖袷郊安僮鳌緾BW;當(AL)<80H時,AH=0,否則AH=FFH。CWD;當(AX)<8000H時,DX=0,否則DX=FFFFH?!竟δ堋緾BW通過將AL的符號位擴展到AH把一個8位數(shù)擴展為16位數(shù),結果在AX中;CWD通過將AX的符號位擴展到DX把一個16位數(shù)擴展為32位數(shù),結果在DX:AX中。【例10】把字節(jié)8EH擴展為字,程序如下:

MOVAL,8EH

CBW;結果:AX=FF8EH【例11】把字43FFH擴展為雙字,程序如下:MOVAX,43FFH

CWD;結果:DX:AX=000043FFH地址傳送指令要點:?地址傳送指令用于將某個操作數(shù)的地址傳送到寄存器中,以便作為地址指針使用。?LEA用于把操作數(shù)的偏移地址傳送到指定的16位的寄存器中。?LES/LDS用于把存放在存儲單元中的32位操作數(shù)地址取出傳送到指定的段寄存器和一個16位的寄存器中。8086指令系統(tǒng)提供了三條用于傳送地址的指令:LEA、LDS和LES。①偏移地址傳送指令LEA【格式及操作】LEAreg16,mem;將mem的偏移地址送到指定的16位寄存器【功能】將mem的偏移地址送到指定的16位寄存器。注意,源操作數(shù)mem必須是一個存儲器操作數(shù),目標操作數(shù)reg16必須是一個16位的通用寄存器?!纠?】用寄存器間接尋址方式把存儲器中從BUFFER開始的兩個字節(jié)分別送到AL和AH寄存器。LEABX,BUFFER;先將BUFFER的偏移地址傳送到BX寄存器

MOVAL,[BX];取出BUFFER中的第一個數(shù)據(jù)送AL

MOVAH,[BX+1];取出BUFFER中的第二個數(shù)據(jù)送AH

【例2】設BX=1000H,DS=6000H,(61005H)=33H,(61006H)=44H。試比較以下兩條指令的執(zhí)行結果:

LEABX,[BX+5]

MOVBX,[BX+5]

見下圖。LEA指令執(zhí)行后:BX=1005H;MOV指令執(zhí)行后:BX=4433H。.........44H33H............61005H61006H10H05H44H33HBXBX執(zhí)行LEA指令后執(zhí)行MOV指令后存儲器點擊觀看LEA指令操作動畫演示。點擊觀看LEA指令應用動畫。[top]②地址指針傳送指令LDS【格式及操作】LDSreg16,mem32;將源操作數(shù)mem32中的內(nèi)容傳送到DS和reg16【功能】把存儲器mem32中存放的一個32位的遠地址指針(包括偏移地址和段地址)傳送到reg16和DS。低16位的內(nèi)容作為偏移地址傳送到reg16,高16位的內(nèi)容作為段地址傳送到數(shù)據(jù)段寄存器DS。指令中,源操作數(shù)mem32為存儲器操作數(shù),目標操作數(shù)reg16是任意一個16位的通用寄存器。訪問源操作數(shù)mem32使用的段寄存器默認為DS。LDS指令非常類似于MOV指令,它們都是將存儲器操作數(shù)的內(nèi)容傳送到目的操作數(shù)。它們的區(qū)別是:LDS指令傳送的是32位數(shù)據(jù)。MOV指令只能傳送8位或16位數(shù)據(jù);LDS指令把傳送的數(shù)據(jù)看成是地址。MOV指令傳送的數(shù)據(jù)做什么用途取決于上下文;LDS指令的目的操作數(shù)是兩個寄存器:DS和一個通用寄存器。MOV指令的目的操作數(shù)只能是一個寄存器或一個存儲器單元?!纠?】設DS=6000H,存儲器中從6000H:0348H開始的4個單元中存放了一個32位的遠指針9000H:8011H,而9000H:8011H單元中存放了數(shù)據(jù)1234H,如圖所示。以下指令將32位遠指針裝入DS:SI中,然后使用該指針把9000H:8011H單元的內(nèi)容傳送到AX。LDSSI,[0348H];將DS:0384H中的32位指針(9000H:8011H)傳送到DS和SI

MOVAX,[SI];將9000H:8011H中的內(nèi)容傳送到AX12H34H...90H00H80H11H...12H34H...90H00H80H11H...6000H:0384H9000H:8011H80119000+98011DSSI1234HAXMOV指令的操作LDS指令的操作[top]③地址指針傳送指令LES【格式及操作】LESreg16,mem32;將源操作數(shù)mem32中的內(nèi)容傳送到ES和reg16【功能】這條指令的功能和LDS指令非常類似,所不同的是,目的操作數(shù)內(nèi)容的高16位被傳送到ES,而不是DS。標志傳送指令要點:?標志傳送指令包括PUSHF、POPF、LAHF和SAHF。?PUSHF指令把標志寄存器的內(nèi)容壓入堆棧,POPF指令把堆棧棧頂?shù)膬?nèi)容彈出到標志寄存器。?LAHF指令把5個狀態(tài)標志傳送到AH,SAHF指令把AH的7、6、4、2、0位傳送到標志寄存器的對應位。①標志壓棧指令PUSHF【格式及操作】PUSHF;將標志寄存器的內(nèi)容壓入堆棧,SP減2本指令為隱含尋址,源操作數(shù)為標志寄存器,目的操作數(shù)為堆棧。本指令主要用于保護標志寄存器的內(nèi)容。②標志出棧指令POPF【格式及操作】POF;將棧頂?shù)膬?nèi)容彈出到標志寄存器,SP加2本指令為隱含尋址,源操作數(shù)為堆棧,目的操作數(shù)為標志寄存器。本指令用于恢復標志寄存器原來的內(nèi)容?!纠?】PUSHF;保護標志寄存器的內(nèi)容到堆棧,以防下面的加法操作破壞標志寄存器的內(nèi)容MOVAX,NUM1;執(zhí)行加法操作ADDAX,NUM2POPF;恢復標志寄存器的內(nèi)容③標志卸出指令LAHF【格式及操作】LAHF;將5個狀態(tài)標志位傳送到AH寄存器【功能】LAHF指令將標志寄存器FLAGS中的5個標志位:SF(符號標志)、ZF(零標志)、AF(輔助進位標志)、PF(奇偶標志)和CF(進位標志)分別傳送到AH的對應位,如下圖所示。OODITFLAGSSZAPCAH1502467④標志存入指令SAHF【格式及操作】SAHF;將AH寄存器的5個狀態(tài)標志位傳送到標志寄存器【功能】SAHF和LAHF指令的操作正好相反,它將AH中的第7、6、4、2、0位分別傳送到標志寄存器FLAGS的對應位。該指令的執(zhí)行顯然會影響標志位SF、ZF、AF、PF和CF,它們將分別被AH的對應位的狀態(tài)修改,但其它標志位不受影響。LAHF與SAHF指令的用途是為了方便修改某些狀態(tài)標志。先把標志傳送到AH,修改后再寫回標志寄存器?!纠?】把AF標志置為1。程序段如下:LAHFORAH,00010000BSAHF注:其實要修改某個標志位,也可以用算術指令實現(xiàn),因為大多數(shù)算術指令都會影響這5個狀態(tài)標志。特別地,對CF標志位,還有專用指令可以修改它。輸入輸出指令(I/O傳送指令)要點:?輸入輸出指令是專門用于對輸入/輸出端口進行讀寫的指令。?輸入輸出指令只能通過AL(或AX)對輸入/輸出端口進行讀寫。?輸入輸出指令只允許用兩種尋址方式:直接尋址和寄存器間接尋址(只能使用DX作為間址寄存器)。輸入輸出指令簡稱I/O指令,是專門用于對輸入/輸出端口(I/O端口)進行讀寫的指令,共有兩條:IN和OUT。使用I/O指令有兩點要注意:1)使用哪個寄存器來暫存輸入(或輸出)的數(shù)據(jù)?8086指令系統(tǒng)規(guī)定,只能通過AL(或AX)與I/O端口進行數(shù)據(jù)傳送。所以指令中的操作數(shù)必定有一個是AL(或AX)。2)I/O端口地址如何指定?在8086系統(tǒng)中,不同的I/O端口也是用地址來區(qū)分的。I/O指令只允許使用兩種尋址方式:(1)直接尋址:在指令中給出一個8位的I/O端口地址,地址范圍為0~FFH;(2)寄存器間接尋址:端口地址由DX寄存器指定,地址范圍為0~FFFFH。①輸入指令IN【格式及操作】INacc,PORT;從I/O端口讀數(shù)據(jù),傳送到AL(或AX),使用直接尋址或:INacc,DX;同上,但使用寄存器間接尋址【功能】從I/O端口輸入一個字節(jié)到AL或輸入一個字到AX中。-在IN指令中,源操作數(shù)是一個端口(地址直接寫在指令中或由DX間接給出),目的操作數(shù)只能是累加器(AL或AX)。-指令的具體形式有以下四種:INAL,port;8位端口地址,輸入一個字節(jié)到ALINAX,port;8位端口地址,輸入一個字到AXINAL,DX;16位端口地址,輸入一個字節(jié)到ALINAX,DX;16位端口地址,輸入一個字到AX【例1】INAL,80H;從地址為80H的端口輸入一個字節(jié)到ALINAL,DX;從指定端口輸入一個字節(jié)到AL,端口地址在DX寄存器中【例2】從地址為3A0H的端口輸入一個字節(jié)到AL。程序段如下:MOVDX,3A0H;將16位端口地址送DX(只能使用DX!)INAL,DX;從該端口輸入一個字節(jié)到AL注:在此程序段中,IN指令不能寫成“INAL,3A0H”,因為3A0H超出直接尋址規(guī)定的地址范圍。[top]②輸出指令OUT【格式及操作】OUTPORT,acc;將AL(或AX)中的內(nèi)容輸出到I/O端口,直接尋址或:OUTDX,acc;同上,但使用寄存器間接尋址【功能】把AL中的8位數(shù)據(jù)或AX中的16位數(shù)據(jù)輸出到I/O端口。-在OUT指令中,源操作數(shù)只能是累加器(AL或AX),目的操作數(shù)是I/O端口(地址直接寫在指令中或由DX間接給出)。-指令的具體形式有以下四種:OUTport,AL;8位端口地址,將AL中的8位數(shù)據(jù)輸出到端口OUTport,AX;8位端口地址,將AX中的16位數(shù)據(jù)輸出到端口OUTDX,AL;16位端口地址,將AL中的8位數(shù)據(jù)輸出到端口OUTDX,AX;16位端口地址,將AX中的16位數(shù)據(jù)輸出到端口【例3】OUT43H,AL;將AL的內(nèi)容輸出到地址為43H的端口OUTDX,AX;將AX的內(nèi)容輸出,端口地址在DX寄存器中OUT280H,AL;錯誤!端口地址超出直接尋址規(guī)定的地址范圍OUT20H,[SI];錯誤!輸出指令的源操作數(shù)只能是累加器OUTBX,AL;錯誤!間接尋址只能使用DX作為間址寄存器【例4】將存儲器單元MYDATA中的8位數(shù)據(jù)輸出到280H端口。程序段如下:MOVDX,280H;將16位端口地址280H傳送到DX中MOVAL,MYDATA;把MYDATA單元中的數(shù)據(jù)傳送到ALOUTDX,AX;將AL的內(nèi)容輸出到280H端口3.3.2算術運算指令要點:?算術運算指令可實現(xiàn)加、減、乘、除四類基本算術運算。?大多數(shù)算術運算指令均會影響5個狀態(tài)標志(CF、ZF、SF、AF、OF)。?對加減法運算,無符號數(shù)和有符號數(shù)使用同一套指令,但應注意:參加運算的操作數(shù)要么都是無符號數(shù),要么都是有符號數(shù)。?算術運算應考慮溢出問題。概述:8086指令系統(tǒng)提供了加、減、乘、除4組基本的算術運算指令,可實現(xiàn)字節(jié)或字、無符號數(shù)或有符號數(shù)的運算。算術運算指令有單操作數(shù)的,也有雙操作數(shù)的。單操作數(shù)指令的操作數(shù)不能夠是立即數(shù);而雙操作數(shù)指令中,立即數(shù)只能作為源操作數(shù)。算術運算會涉及到運算結果是否溢出的問題。無符號數(shù)和有符號數(shù)的運算是否溢出分別用CF和OF來判斷。除4組基本的算術運算指令外,8086指令系統(tǒng)還提供了與之對應的4類十進制運算調(diào)整指令。算術運算指令的執(zhí)行大多會對標志位產(chǎn)生影響。算術運算中的溢出問題:以8位二進制數(shù)的加法為例,兩個8位數(shù)相加時有4種情況:二進制運算對應的十進制運算數(shù)據(jù)作為無符號數(shù)數(shù)據(jù)作為有符號數(shù)Case1:無符號數(shù)和有符號數(shù)均不溢出00001000+0001111000100110結果:26H(38)CF=0,OF=08+3038未超出8位無符號二進制數(shù)表示范圍+8+(+30)+38未超出8位有符號二進制數(shù)表示范圍Case2:無符號數(shù)溢出,有符號數(shù)不溢出00001000+11111101100000101結果:5CF=1,OF=08+253261超出8位無符號二進制數(shù)表示范圍+8+(-3)+5未超出8位有符號二進制數(shù)表示范圍Case3:無符號數(shù)不溢出,有符號數(shù)溢出00001000+0111110110000101結果:-123(補碼)CF=0,OF=18+125133未超出8位無符號二進制數(shù)表示范圍+8+(+125)+133超出8位有符號二進制數(shù)表示范圍Case4:無符號數(shù)和有符號數(shù)均溢出10001000+11110111101111111結果:127CF=1,OF=1136+247383超出8位無符號二進制數(shù)表示范圍-120+(-9)-129超出8位有符號二進制數(shù)表示范圍上面四種情況說明,算術運算溢出的判別是比較復雜的,不能只用一個標志位來判別。算術運算溢出是一種出錯狀態(tài),在運算過程中應當避免。算術運算指令可分成以下5組:加法運算減法運算乘法運算除法運算BCD碼運算調(diào)整加法運算指令要點:?加法指令實現(xiàn)兩個操作數(shù)的求和運算,或者是單個操作數(shù)的增量運算。?判斷加法運算是否溢出,應根據(jù)操作是有符號數(shù)加法還是無符號數(shù)加法區(qū)別對待。?加法運算會改變狀態(tài)標志位的值。?對加法運算,無符號數(shù)和有符號數(shù)使用同一套指令,但應注意:參加運算的操作數(shù)要么都是無符號數(shù),要么都是有符號數(shù)。加法指令包括不帶進位的加法指令ADD、帶進位的加法指令ADC和加1(增量)指令INC。①不帶進位的加法指令ADD【格式及操作】ADDdest,src;dest←(dest)+(src)【功能】實現(xiàn)兩個操作數(shù)的相加,其結果送回目的操作數(shù)中。加法指令對操作數(shù)的要求如下:可以是字節(jié)(8位),也可以是字(16位),但二者必須一致。源操作數(shù)可以是立即數(shù)。可以是無符號數(shù),也可以是有符號數(shù),但二者應一致。不允許都是存儲器操作數(shù)。不允許是段寄存器?!纠?】ADDCL,20H;CL←(CL)+20HADDAX,SI;AX←(AX)+(SI)ADD[BX+2],AL;(BX+2)←((BX)+2)+(AL)ADDDX,[BX+SI];DX←(DX)+((BX)+(SI))ADDAX,CL;錯誤!操作數(shù)類型應一致ADD[SI],[BX];錯誤!不允許兩個操作數(shù)都是存儲器ADDDS,AX;錯誤!不允許把段寄存器作為操作數(shù)加法指令對全部6個狀態(tài)標志位都會產(chǎn)生影響?!纠?】試分析以下兩條指令執(zhí)行后的狀態(tài):MOVAL,7EH

ADDAL,5BH

分析:我們用手工的方法來模擬以上兩條指令的執(zhí)行,如下......01111110+0101101111011001根據(jù)運算過程可得出各狀態(tài)標志位的值:(Ci表示第i位的進位)C3=1,所以AF=1;C7=0,所以CF=0;C7⊕C6=1,所以OF=1;結果中1的個數(shù)為奇數(shù),所以PF=0;結果的bit7=1,所以SF=1;結果不為零,所以ZF=0。其中CF=0意味著若操作數(shù)是無符號數(shù),則結果沒有產(chǎn)生溢出;而OF=1意味著若操作數(shù)是有符號數(shù),則運算結果溢出。事實上,根據(jù)運算結果AL=D9H>7FH(8位有符號數(shù)的最大值)和D9H<FFH(8位無符號數(shù)的最大值)也可得到相同結果。[top]②帶進位的加法指令ADC【格式及操作】ADCdest,src;dest←(dest)+(src)+(CF)【功能】源操作數(shù)dest、目的操作數(shù)src、進位標志CF三者相加,結果送回目的操作數(shù)中。ADC指令在格式、功能及對標志位的影響方面都與ADD指令基本相同,只是CF也要參加求和運算?!纠?】設CF=1,寫出以下指令執(zhí)行后的結果。MOVAL,7EH

ADCAL,86H

指令執(zhí)行后:AL=7EH+ABH+1=2AH,且CF=1。ADC指令主要用于多字節(jié)的加法運算中。由于8086一次最多只能進行16位的加法運算,故對于多字節(jié)加法,應把操作數(shù)分成若干個16位數(shù)(或8位數(shù))分別求和,而在高位相加時,必須要考慮低位的進位,這時就要用到ADC指令。【例4】求兩個32位無符號數(shù)0107A379H與10067E4FH二者之和。MOVDX,0107H;第一個數(shù)高16位傳送到DX

MOVAX,0A379H;第一個數(shù)低16位傳送到AX

MOVBX,1006H;第二個數(shù)高16位傳送到BX

MOVCX,7E4FH;第二個數(shù)低16位傳送到CX

ADDAX,CX;低16位相加,進位在CF中ADCDX,BX;高16位相加,并加上低16位的進位

相加的最后結果為:110E21C8H。[top]③加1(增量)指令INC【格式及操作】INCdest;dest←(dest)+1【功能】目的操作數(shù)加1,結果仍送回目的操作數(shù)中。本指令的功能類似于C語言中的“++”運算符,通常在循環(huán)程序中用于修改地址指針及循環(huán)次數(shù)。指令中的操作數(shù)可以是寄存器或存儲器操作數(shù);可以是8位,也可以是16位。但不能是段寄存器,也不能是立即數(shù)。【例5】INCAX;AX←(AX)+1

INCBL;BL←(BL)+1

INCBYTEPTR[SI];將SI所指向的字節(jié)單元的內(nèi)容+1INC指令不影響CF標志,但對其它5個狀態(tài)標志AF、OF、PF、SF及ZF會產(chǎn)生影響。減法運算指令要點:?減法指令實現(xiàn)兩個操作數(shù)的求差運算,或者是單個操作數(shù)的減量運算。?判斷減法運算是否溢出,應根據(jù)操作是有符號數(shù)減法還是無符號數(shù)減法區(qū)別對待。?減法運算會改變狀態(tài)標志位的值。?對減法運算,無符號數(shù)和有符號數(shù)使用同一套指令,但應注意:參加運算的操作數(shù)要么都是無符號數(shù),要么都是有符號數(shù)。減法指令包括不帶借位的減法指令SUB、帶借位的減法指令SBB、減1(減量)指令DEC、求補指令NEG以及比較指令CMP。①不帶借位的減法指令SUB【格式及操作】SUBdest,src;dest←(dest)-(src)【功能】用目標操作數(shù)減去源操作數(shù),結果仍送回目標操作數(shù)。SUB指令對操作數(shù)的要求以及對狀態(tài)標志位的影響和ADD指令完全相同。請參考ADD指令?!纠?】SUBAL,60H

SUB[BX+20H],DX

SUBAX,CXSUBAL,[BX+SI];AL的內(nèi)容與SS:(BP+SI)單元的內(nèi)容相減,結果送AL[top]②帶借位的減法指令SBB【格式及操作】SBBdest,src;dest←(dest)-(src)-(CF)【功能】用目的操作數(shù)減去源操作數(shù)以及標志位CF的值,結果仍送到目的操作數(shù)。SBB指令對操作數(shù)的要求以及對狀態(tài)標志位的影響與SUB指令完全相同,只是CF也要參加求差運算。【例2】SBBBL,30H;BL←(BL)-30H-(CF)SBBDX,[SI];DX←(DX)-((SI))-(CF)SBB指令主要用于多字節(jié)的減法運算,它與ADC指令的用法基本類似。【例3】x、y、z均為32位數(shù),分別存放在地址為X、Y、Z的三個存儲單元中,用指令序列實現(xiàn)w=x+y+24-z,結果放在W單元中。解:因為x、y、z均為32位數(shù),所以我們用兩個16位寄存器完成32位運算。程序段如下:MOVAX,X

MOVDX,X+2;DX:AX←x

ADDAX,Y

ADCDX,Y+2;DX:AX←x+y

ADDAX,24

ADCDX,0;DX:AX←x+y+24

SUBAX,ZSBBDX,Z+2;DX:AX←x+y+24-z

MOVW,AX

MOVW+2,DX;32位結果存入W單元[top]③減1(減量)指令DEC【格式及操作】DECdest;dest←(dest)-1【功能】將目的操作數(shù)的內(nèi)容減1,結果仍然放在目的操作數(shù)中。本指令的功能類似于C語言中的“――”運算符,通常在循環(huán)程序中用于修改地址指針及循環(huán)次數(shù)。DEC指令對操作數(shù)的要求以及對標志位的影響與INC指令完全相同?!纠?】DECSI;SI←(SI)-1

DECBX;BX←(BX)-1

DECBYTEPTR[DI];(DI)←((DI))-1【例5】編寫一個延時程序,延時時間任意。解:可以用空循環(huán)的方法消耗時間,在循環(huán)中對計數(shù)器CX減1,直到CX=0為止。MOVCX,1000H;用CX作為計數(shù)器,計數(shù)初值為FFFFHNEXT:DECCX;計數(shù)器(CX)減1JNZNEXT;若CX≠0則循環(huán)

...;延時結束[top]④比較指令CMP【格式及操作】CMPdest,src;(dest)-(src)【功能】CMP指令對兩個操作數(shù)相減,但相減的結果不送回目的操作數(shù),而只是根據(jù)相減的情況設置標志位。比較指令對操作數(shù)的要求及對標志位的影響與SUB指令完成相同?!纠?】CMPBX,2100H;(BX)-2100H,修改標志位

CMPCL,DH;(CL)-(DH),修改標志位比較指令在使用時,一般在其后緊跟一個條件轉移指令,根據(jù)比較結果來決定程序轉向。【例7】比較AL、BL、CL中帶符號數(shù)的大小,將最小數(shù)放在AL中。CMPAL,BL;AL和BL比較

JLEBBB;若AL≤BL,則轉到NEXT

XCHGAL,BL;若AL>BL,則交換NEXT:CMPAL,CL;AL和CL比較

JLEL;若AL≤CL,則轉到STOP

XCHGAL,CL;若AL>CL,則交換STOP:HLT[top]⑤求補指令NEG【格式及操作】NEGdest;dest←0-(dest)【功能】目的操作數(shù)為正數(shù)時,本指令計算目的操作數(shù)的負數(shù)的補碼,結果仍然放在目的操作數(shù)中。目的操作數(shù)為負數(shù)時,本指令計算目的操作數(shù)的絕對值,結果仍然放在目的操作數(shù)中。【例8】若AL=47H,則執(zhí)行NEGAL后,AL=B9H,CF=1。

本例中,結果B9H為(-47H)的補碼。NEG指令對六個狀態(tài)標志位均有影響。但要注意以下兩點:(1)執(zhí)行NEG指令后,一般情況下都會使CF為1。因為用零減去某個操作數(shù),自然會產(chǎn)生借位,而減法的CF值正是反映無符號數(shù)運算中的借位情況。除非給定的操作數(shù)為零才會使CF為0。(2)若操作數(shù)的值為80H(-128)或為8000H(-32768),則執(zhí)行NEG指令后,其結果仍為80H或8000H,但OF置1,其它情況下OF均置0。乘法運算指令要點:?有符號數(shù)和無符號數(shù)的乘法需要使用不同的乘法指令。?乘法指令只需指出源操作數(shù)(即指令中只需指定乘數(shù)),被乘數(shù)和目的操作數(shù)隱含為累加器(和DX)。?乘法運算中乘數(shù)(被乘數(shù))的字長與積的字長的關系:8位×8位→16位乘積,16位×16位→32位乘積。乘法指令對被乘數(shù)、乘數(shù)及乘積的存放有如下規(guī)定:乘積被乘數(shù)乘數(shù)8位乘法AXAL指令中給出16位乘法DX:AXAX指令中給出①無符號數(shù)乘法指令MUL【格式及操作】MULsrc;AX←(AL)×src(8位乘法)或DX:AX←(AX)×src(16位乘法)【操作數(shù)】指令中的源操作數(shù)可以是8位(或16位)的寄存器或存儲器單元,但不能是立即數(shù)?!纠?】MULDL;AX←(AL)×(DL)MULBX;DX:AX←(AX)×(BX)MULBYTEPTR[SI];AX←(AL)×((SI))

MULW0RDPTR[DI];DX:AX←(AX)×((DI)+1):(DI))MUL10;錯誤!源操作數(shù)不能為立即數(shù)MULAL,BL;錯誤!目的操作數(shù)無需寫出【標志位】如果乘積的高8位(8位乘法)或高16位(16位乘法)不為零——即AH或DX中包含乘積的有效數(shù)字,則CF=0F=l,否則CF=0F=0。其它標志無定義?!緜渥ⅰ吭谀承┣闆r,可用左移指令來代替無符號數(shù)乘法指令(左移1位相當于乘2),請參見移位指令的說明。②有符號數(shù)乘法指令IMUL【格式及操作】IMULsrc;AX←(AL)×src(8位乘法)或DX:AX←(AX)×src(16位乘法)【操作數(shù)】與上述MUL指令的要求相同。只是此指令把操

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論