《編譯原理教程》課件第十二章_第1頁
《編譯原理教程》課件第十二章_第2頁
《編譯原理教程》課件第十二章_第3頁
《編譯原理教程》課件第十二章_第4頁
《編譯原理教程》課件第十二章_第5頁
已閱讀5頁,還剩207頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

第十二章8086/8088小匯編的設(shè)計(jì)與實(shí)現(xiàn)12.1匯編指令系統(tǒng)的分析12.28086/8088小匯編的設(shè)計(jì)實(shí)現(xiàn)12.38086/8088小匯編實(shí)驗(yàn)12.48086/8088小匯編程序 12.1匯編指令系統(tǒng)的分析

12.1.1引言

編譯的過程是將源程序編譯成可在具體機(jī)器上執(zhí)行的機(jī)器指令程序的過程。所以,實(shí)現(xiàn)編譯的首要任務(wù)就是了解目標(biāo)機(jī)器的指令系統(tǒng)及其特點(diǎn),只有這樣才能設(shè)計(jì)好編譯程序。

任何一種微處理器(CPU)在設(shè)計(jì)時(shí),就已規(guī)定好自己特定的指令系統(tǒng),這種指令系統(tǒng)的功能也就決定了由該微處理器構(gòu)成的計(jì)算機(jī)系統(tǒng)及其基本功能。指令系統(tǒng)中所設(shè)計(jì)的每一條指令都對應(yīng)著微處理器要完成的一種規(guī)定功能操作,即這些指令功能的實(shí)現(xiàn)都是由微處理器中的物理器件完成的。要使計(jì)算機(jī)完成一個(gè)完整的任務(wù),就需要執(zhí)行一組指令,這一組指令通常稱為程序。計(jì)算機(jī)能夠執(zhí)行的各種不同指令的集合就稱為處理器(CPU)的指令系統(tǒng)。一臺計(jì)算機(jī)只能識別由二進(jìn)制編碼表示的指令,稱之為機(jī)器指令。一條機(jī)器指令應(yīng)包括兩部分內(nèi)容:一部分給出該指令應(yīng)完成何種操作,稱為指令操作碼部分;另一部分給出參與操作的操作數(shù)的值,或指出操作數(shù)存放在何處、操作的結(jié)果應(yīng)送往何處等,這一部分稱為指令的操作數(shù)部分。處理器可根據(jù)指令中給出的地址信息求出存放操作數(shù)的地址——稱為有效地址EA(EffectiveAddress),然后對存放在有效地址中的操作數(shù)進(jìn)行存取操作。指令中關(guān)于如何求出存放操作數(shù)有效地址的方法稱為操作數(shù)的尋址方式。計(jì)算機(jī)按照指令給出的尋址方式求出操作數(shù)有效地址進(jìn)行存取操作數(shù)的過程,稱為指令的尋址操作。由于計(jì)算機(jī)的主要工作是進(jìn)行數(shù)據(jù)處理,故計(jì)算機(jī)指令系統(tǒng)中的多數(shù)指令是與操作數(shù)有關(guān)的。這些操作數(shù)可以在寄存器中,也可以在內(nèi)存或I/O端口中,還可以隱含于指令碼中。對于不同的操作數(shù)有不同的方法來存取它們,特別是對于存放于存儲(chǔ)單元的操作數(shù),可以采用多種不同的方式來尋找地址以便進(jìn)行數(shù)據(jù)存取。尋址方式越多,CPU的指令功能就越強(qiáng),靈活性也就越大。但是,尋址方式多也會(huì)造成指令編碼的復(fù)雜化。因此,在設(shè)計(jì)指令系統(tǒng)的尋址方式時(shí)主要考慮以下問題:

(1)能夠滿足CPU所尋址的最大地址空間,否則將存在無法訪問的地址。

(2)從速度和存儲(chǔ)角度考慮,地址碼不能占用太多的字節(jié)。為減少地址碼占用的字節(jié)數(shù),就應(yīng)采用多種尋址方式。

(3)盡量滿足高級語言中各種數(shù)據(jù)結(jié)構(gòu)的尋址需要。以數(shù)組元素A[I]為例,位移量對應(yīng)數(shù)組A的開始地址,變址I(表示數(shù)組A的第I個(gè)元素)的位距值存放在寄存器(如SI)中,則對數(shù)組元素A[I]的訪問地址應(yīng)是“寄存器(SI)+位移”;有時(shí)位移量是在基址寄存器(如BX)中,則A[I]的訪問地址是“寄存器(BX)+寄存器(SI)”;如果A[I]出現(xiàn)在遞歸子程序調(diào)用中,則數(shù)據(jù)是以堆棧形式來逐層存儲(chǔ)的,故訪問數(shù)組元素A[I]時(shí)還需由堆棧指針(如BP)來指示是哪一層子程序調(diào)用中的A[I],其地址應(yīng)為“寄存器(BP)+寄存器(SI)+位移”。由此可見,至少要有如上所述的幾種尋址方式才能滿足程序語言的特殊使用(數(shù)組、遞歸子程序)要求。通常一條指令被分為若干字段(每個(gè)字段為幾個(gè)二進(jìn)制位),其中一個(gè)字段稱為操作碼,說明計(jì)算機(jī)該做什么,其余字段稱為操作數(shù),指出該指令在執(zhí)行中所需要的信息。一個(gè)操作數(shù)可以是一個(gè)具體數(shù)據(jù),也可以是存儲(chǔ)數(shù)據(jù)的寄存器或存儲(chǔ)器地址。一般指令格式如下:

指令可以含有若干個(gè)操作數(shù),但操作數(shù)越多指令的長度也就越長,所占用的存儲(chǔ)空間就越大,指令送入CPU所花費(fèi)的時(shí)間也越多。為了減少指令的長度,一般指令都只允許有一個(gè)或兩個(gè)操作數(shù),而且雙操作數(shù)指令中的一個(gè)操作數(shù)必須存放在寄存器中。這是由于存儲(chǔ)器和I/O空間相當(dāng)大,表示其地址必須占用較多的二進(jìn)制位,因而就勢必引起指令長度的增加。而一個(gè)計(jì)算機(jī)所具有的寄存器很少(幾個(gè)到幾十個(gè)),因此用于表示這些寄存器編碼所需的二進(jìn)制位數(shù)就少。所以,減少指令位數(shù)的方法之一是盡可能使用寄存器。操作數(shù)僅限于兩個(gè)雖然降低了許多指令的靈活性,但卻進(jìn)一步節(jié)省了指令占用的位數(shù)。例如,加法指令涉及到兩個(gè)相加的數(shù)和所需保存的結(jié)果,這就需要三個(gè)操作數(shù),可以規(guī)定把加得的結(jié)果存入到兩個(gè)相加數(shù)的位置之一,從而使操作數(shù)減少為兩個(gè),這兩個(gè)操作數(shù)就分別稱為源操作數(shù)和目的操作數(shù)。源操作數(shù)與目的操作數(shù)相加的結(jié)果最終又送回到目的操作數(shù),這意味著原來目的操作數(shù)中存放的數(shù)據(jù)丟失了,但是這種情況無關(guān)緊要,如果需要保留原來目的操作數(shù)的值,則可以在執(zhí)行這條指令之前將原目的操作數(shù)保存到其它寄存器或者存儲(chǔ)器中。兩操作數(shù)指令的方法對于由許多指令組成的程序來說,所節(jié)省的存儲(chǔ)空間和送入CPU的時(shí)間都是可觀的。12.1.28086/8088指令系統(tǒng)

雖然我們已經(jīng)在“微機(jī)原理”或“匯編語言程序設(shè)計(jì)”課程中學(xué)習(xí)了8086/8088指令系統(tǒng),但那是基于掌握匯編語言和微機(jī)的原理及使用角度來學(xué)習(xí)指令系統(tǒng)的?,F(xiàn)在,我們從編譯的角度來深入了解8086/8088指令系統(tǒng)的設(shè)計(jì)特點(diǎn)及實(shí)現(xiàn)方法。

8086/8088指令系統(tǒng)的編碼格式非常緊湊并且靈活,其機(jī)器碼指令長度為1~6個(gè)字節(jié)(不包括前綴),通常指令的第一字節(jié)為操作碼,用以規(guī)定操作的類型,第二字節(jié)規(guī)定操作數(shù)的尋址方式。

典型的單操作數(shù)指令結(jié)構(gòu)如圖12-1所示。圖12-1典型的單操作數(shù)指令結(jié)構(gòu)(a)操作數(shù)在16位寄存器內(nèi);(b)操作數(shù)在寄存器或存儲(chǔ)器內(nèi)典型的雙操作數(shù)指令結(jié)構(gòu)如圖12-2所示。圖12-2典型的雙操作數(shù)指令結(jié)構(gòu)由于雙操作數(shù)指令只有一個(gè)w位,因此兩個(gè)操作數(shù)要么都是8位,要么都是16位。然而,對于值很小的立即數(shù)操作來說,如果用16位表示就顯得有些浪費(fèi)存儲(chǔ)空間了。為了減少這種情況下立即數(shù)所占用的字節(jié)數(shù),8086/8088指令系統(tǒng)對諸如加法、減法和比較的立即數(shù)操作指令設(shè)置了符號擴(kuò)展位s。s位只對16位操作數(shù)(w=1)有效,即:

這樣對一些16位立即數(shù)操作指令,立即數(shù)的存儲(chǔ)僅是8位的,節(jié)省了存儲(chǔ)空間和取指時(shí)間,只是當(dāng)CPU執(zhí)行該操作時(shí)再將立即數(shù)擴(kuò)展為16位。

8086/8088指令格式主要由操作碼域和操作數(shù)域構(gòu)成。操作碼域指出了該指令操作的類型,僅低位的d、w位(如果有的話)隨傳送方向及字還是字節(jié)操作而變化,少量指令存在著第二操作碼。8086/8088指令格式設(shè)計(jì)的精妙之處在于操作數(shù)域,其根據(jù)尋址方式、傳送方向(d位)、字或字節(jié)操作(w位)決定了第二字節(jié)(尋址方式字節(jié))中mod字段、r/m字段以及reg字段的取值,及該條指令機(jī)器碼的長度(需特別注意機(jī)器碼長度的確定)。

由mod和r/m字段組合共同決定一個(gè)操作數(shù)的尋址方式及有效地址的計(jì)算方法見表12-1。表12-1尋址方式

由reg字段規(guī)定的寄存器或分段寄存器編碼見表12-2。表12-2寄存器表有了表12-1和表12-2,我們就可以根據(jù)傳送方向位d、字或字節(jié)操作位w的值以及所要求的尋址方式及參加操作的寄存器或存儲(chǔ)器地址來構(gòu)造包括mod、r/m和reg字段組成的字節(jié),并形成屬于操作數(shù)域的其后各字節(jié)內(nèi)容。例如,數(shù)據(jù)傳送類指令MOV所允許出現(xiàn)的指令格式有:

對于寄存器/存儲(chǔ)器與寄存器之間的傳送命令可以采用方式(1)如:

MOVAX,BX;(BX)→AX

由于d位值的不同,第二字節(jié)的編碼可以有兩種形式:

①當(dāng)d=0時(shí),reg對應(yīng)源操作數(shù)BX,即為BX的編碼011;r/m對應(yīng)目的操作數(shù)AX,即為AX的編碼000,此時(shí)mod值為11來表示操作數(shù)為寄存器,即mod值和r/m值共同決定了這個(gè)操作數(shù)的類型是寄存器并且是AX(000)。因此該指令的機(jī)器碼如下:如果指令是寄存器與存儲(chǔ)器之間的傳送,例如:MOVAX,[BX+DI+1234H],則對應(yīng)的機(jī)器指令只能有一種形式。這是因?yàn)閞eg段只能表示寄存器而無法表示存儲(chǔ)器,而由mod和r/m字段的組合并根據(jù)mod域值既可以表示寄存器又可以表示存儲(chǔ)器。故當(dāng)操作數(shù)的一方是存儲(chǔ)器時(shí)就只能用mod和r/m字段來表示了。究竟是將寄存器的內(nèi)容傳送到存儲(chǔ)器還是將存儲(chǔ)器的內(nèi)容傳送到寄存器取決于傳送方向位d的值,如果說在上一個(gè)例子中的d位無關(guān)緊要的話,那么在這里d位就是不可或缺的了。本條指令的存儲(chǔ)器地址通過查找表12-1可知:mod值為10,r/m值為001;而由表12-2得知:reg所對應(yīng)的操作數(shù)AX的值為000;并且位d值必須為1方保證是將mod和r/m指定的內(nèi)容送AX,所以此時(shí)該指令對應(yīng)機(jī)器碼為

注意,mod取值10是因?yàn)樵撝噶畹拇鎯?chǔ)器操作數(shù)中還帶有16位位移1234H,即在操作碼字節(jié)及尋址字節(jié)之后帶有16位的位移量,低8位值為34H,高8位為12H。

對于立即數(shù)傳送到寄存器/存儲(chǔ)器的操作可采用方式(2)。如:

MOVCL,12H;立即數(shù)12H→CL

這是一個(gè)字節(jié)傳送指令,即w=0;因此mod=11和r/m=001表示寄存器CL,第三字節(jié)為立即數(shù)12H,即該指令的機(jī)器碼如下:

如果用方式(3)實(shí)現(xiàn)則更加簡單,由于此時(shí)w=0,reg=001,則該指令所對應(yīng)的機(jī)器碼為:

與方式(2)的機(jī)器碼相比節(jié)省了一個(gè)字節(jié)。下面,我們看一下立即數(shù)傳送到存儲(chǔ)器的操作,這種操作只能用方式(2)實(shí)現(xiàn),例如:

MOV[BX+DI+1234H],5678H

查表12-1可知:mod=10,r/m=001;此時(shí)該指令對應(yīng)的機(jī)器碼為由mod=10可知存儲(chǔ)器操作數(shù)還帶有16位位移量,這個(gè)16位位移量是緊隨在機(jī)器碼第二字節(jié)即尋址方式字節(jié)之后的,所以位移量必須插到立即數(shù)之前,以便形成存儲(chǔ)器的有效地址。注意,此時(shí)的機(jī)器碼指令長度為6個(gè)字節(jié),這是8086/8088指令系統(tǒng)中最長的機(jī)器碼指令形式。

通過機(jī)器碼指令的形成過程可知,機(jī)器碼指令的長度是由字或字節(jié)操作以及尋址方式?jīng)Q定的。這一點(diǎn)對編譯來說很重要,因?yàn)樵诰幾g過程中必須根據(jù)源指令來確定形成的機(jī)器碼指令所應(yīng)具有的字節(jié)數(shù)(即長度)。由8086/8088指令系統(tǒng)的尋址方式和機(jī)器碼指令的尋址方式字節(jié)即mod、r/m和reg字段可以看出:雙操作數(shù)指令允許寄存器與寄存器、寄存器與存儲(chǔ)器之間的操作,此外還允許立即數(shù)到寄存器/存儲(chǔ)器的操作;但無法用mod、r/m和reg字段來同時(shí)表示兩個(gè)存儲(chǔ)器的地址。如果允許存儲(chǔ)器到存儲(chǔ)器操作的指令出現(xiàn),將會(huì)使機(jī)器碼指令變得更長更復(fù)雜,故此,8086/8088舍去了直接進(jìn)行存儲(chǔ)器之間操作的指令,使得機(jī)器指令更加簡潔有效。如果要實(shí)現(xiàn)存儲(chǔ)器到存儲(chǔ)器的操作只須經(jīng)過寄存器過渡,即先進(jìn)行存儲(chǔ)器到寄存器的操作,并將結(jié)果保存在寄存器中,然后再使用一條由寄存器傳送到存儲(chǔ)器的指令操作。 12.28086/8088小匯編的設(shè)計(jì)實(shí)現(xiàn)

我們已經(jīng)了解了8086/8088指令系統(tǒng)的特點(diǎn),下面討論如何實(shí)現(xiàn)8086/8088匯編指令到機(jī)器碼指令的翻譯過程。為了簡單起見,我們對8086/8088匯編語言加以如下限制:

(1)在匯編語言中不允許出現(xiàn)標(biāo)識符,即轉(zhuǎn)移地址必須以實(shí)際地址出現(xiàn);

(2)對8086/8088匯編中標(biāo)識字或字節(jié)操作的“WORDPTR”和“BYTEPTR”,我們只取其第一個(gè)字符“W”或“B”進(jìn)行標(biāo)識,且對存儲(chǔ)器的訪問必須指定是字(W)還是字節(jié)(B)操作,如:

MOVB[BX+SI],12

ADDAX,W[SI+1234]

(3)數(shù)字一律用不帶H的十六進(jìn)制數(shù)表示。

因此,我們所討論的是一種8086/8088小匯編的設(shè)計(jì)與實(shí)現(xiàn)。12.2.18086/8088小匯編指令的分類

1.不需變化的單、雙字節(jié)指令

對于指令系統(tǒng)中那些機(jī)器碼已經(jīng)確定,即無操作數(shù)域部分的指令,諸如XLAT、LAHF、SAHF、PUSHF、POPF、AAA、DAA、AAS、DAS、CBW、CWD、INT3、INTQ、IRET、CLC、STC、CLD、STD、CLI、STI、HLT、WAIT、LOOK等單字節(jié)指令直接產(chǎn)生機(jī)器碼指令,這類指令的處理子程序?yàn)镾UB1。此外,還有機(jī)器碼確定且無操作數(shù)域的雙字節(jié)指令A(yù)AM和AAD,由于這兩條指令的第二字節(jié)內(nèi)容相同,故只存放第一字節(jié)的操作碼,然后在子程序中再直接送入第二字節(jié)的內(nèi)容,因此這兩條指令的處理由SUB2完成。

2.算術(shù)運(yùn)算類指令

根據(jù)附錄1,我們首先分離出指令格式相同的8條指令:ADC、ADD、AND、CMP、SBB、SUB、OR、XOR,其指令編碼格式如下:

因此,我們構(gòu)造這8條指令碼見表12-3。表12-3指令碼這些參考碼要在掃描匯編助記符指令時(shí)不斷進(jìn)行修正。例如,對ADDW[BX+SI],AX指令加工過程是:當(dāng)掃描出“ADD”時(shí),我們已經(jīng)獲得了參考碼00H;再掃描到“W”時(shí),我們知道這是字操作,故參考碼加1即為01H,并且由于這個(gè)“W”出現(xiàn)在第一個(gè)操作數(shù)位置上,因而是目的操作數(shù),可知該指令一定是寄存器到存儲(chǔ)器的操作,故d位為0,因此,參考碼不再加“02H”。在操作數(shù)域主要形成機(jī)器碼第二字節(jié)中的mod字段、reg字段和r/m字段。注意,這8條指令還有區(qū)別:對立即數(shù)操作來說,ADC、ADD、CMP、SBB、SUB有符號擴(kuò)展位,而其余3條指令(AND、OR和XOR)沒有,故處理時(shí)要分別對待。對于立即操作數(shù),只有當(dāng)掃描到第二個(gè)操作數(shù)時(shí),我們才能確定其為立即數(shù)操作(如ADDAX,1234H,若寫成ADD1234H,AX則是錯(cuò)誤的)。此時(shí),如果第一操作數(shù)是AX或AL(累加器),則我們在原參考碼上加04H(此種情況下不會(huì)出現(xiàn)d位為1的情況)并且不形成尋址方式的第二字節(jié)(不產(chǎn)生mod、reg及r/m這樣的字段),立即數(shù)緊接在參考碼(此時(shí)已是該指令的機(jī)器碼指令)之后。如果第一操作數(shù)并非AX或AL,則取出參考碼的3~5位(二進(jìn)制)作為該指令的次操作碼。例如,SUB的參考碼為28H,即得到次操作碼為05H。此時(shí)指令碼應(yīng)屏蔽掉原參考碼的高6位(低兩位保存著s位和w位信息),然后再加上80H,便得到所需的80H~83H指令碼。

上述處理加工過程由子程序SUB3完成。

對子算術(shù)運(yùn)算指令的INC、DEC,由于指令格式與PUSH和POP很接近(見附錄1),故歸于PUSH和POP處理,即由子程序SUB6實(shí)現(xiàn)。

3.其他指令

其他指令的分類處理如下:

(1)?CALL、JMP跳轉(zhuǎn)指令的處理由子程序SUB5實(shí)現(xiàn)。

(2)?NOT、NEG、MUL、IMUL、DIV、IDIV指令的處理由子程序SUB7實(shí)現(xiàn)。

(3)?IN、OUT指令的處理由子程序SUB8實(shí)現(xiàn)。

(4)短跳轉(zhuǎn)類指令的處理由子程序SUB9實(shí)現(xiàn)。

(5)?LEA、LDS、LES指令的處理由子程序SUB10實(shí)現(xiàn)。

(6)?MOV指令的處理由子程序SUB11實(shí)現(xiàn);MOV指令由于比較復(fù)雜,因此單獨(dú)予以處理。

(7)移位類(RCL、RCR、ROL、ROR、SAL、SAR、SHL、SHR)指令的處理由子程序SUB12實(shí)現(xiàn)。

(8)?RET、RETF指令的處理由子程序SUB13實(shí)現(xiàn)。

(9)?TEST指令的處理由子程序SUB14實(shí)現(xiàn);TEST指令格式與算術(shù)運(yùn)算類指令類似,但又不含有d位和s位,故單獨(dú)處理。

(10)?XCHG指令的處理由子程序SUB15實(shí)現(xiàn);XCHG指令格式也無法歸到某一類指令中,因而單獨(dú)處理。

(11)?DW、DB(定義字、字節(jié)空間)指令的處理由子程序SUB4實(shí)現(xiàn)。在8086/8088指令系統(tǒng)中無此指令,它們是根據(jù)8086/8088匯編中的設(shè)置而增加的。12.2.28086/8088小匯編的狀態(tài)表及主控程序設(shè)計(jì)與實(shí)現(xiàn)

為了實(shí)現(xiàn)由匯編指令到機(jī)器指令的編譯,我們將8086/8088匯編助記符分為兩個(gè)域:操作碼域和操作數(shù)域。操作碼與機(jī)器指令幾乎是一一對應(yīng)的(少量指令存在第二操作碼);操作數(shù)域主要確定機(jī)器碼第二字節(jié)的mod域、r/m域、reg域的值以及傳送的方向d位、字還是字節(jié)操作w位和符號擴(kuò)展s位,并根據(jù)d、w、s值(如果有的話)修改狀態(tài)表中該指令對應(yīng)的參考碼。此外,操作數(shù)域還需根據(jù)mod的值(mod=01時(shí),mod和r/m域的操作數(shù)是存儲(chǔ)器地址,它還帶有一字節(jié)的位移;mod=10時(shí),mod和r/m域的操作數(shù)帶有一字長的位移)、w值、s值來調(diào)整并放置操作碼單元之后尋址方式字節(jié)(如果有的話)以及操作數(shù)的位移字或字節(jié);如果一操作數(shù)是立即數(shù),則后面還要有字或字節(jié)的立即數(shù)。整個(gè)機(jī)器碼的長度在掃描匯編的同時(shí)還在不斷進(jìn)行修改,直到掃描完該匯編指令,對應(yīng)的機(jī)器碼長度就完全確定了(機(jī)器碼長度在第四部分的程序中記錄在變量m0中)。為了使形成機(jī)器碼指令加工操作更加簡便,我們設(shè)置了一個(gè)工作數(shù)組如下:

work數(shù)組是用來暫存加工處理中的機(jī)器碼指令的。由于8086/8088的機(jī)器碼指令長度最多為6個(gè)字節(jié),因而work數(shù)組的元素也是6個(gè)(以字節(jié)為單位)。這樣,對匯編指令的加工處理都是在work數(shù)組中進(jìn)行的,直至最終形成完整的機(jī)器碼指令。由于機(jī)器碼指令的長度記錄于m0中,因而最后再按m0指示的長度取出work數(shù)組中的機(jī)器碼指令即可。

在處理中,還設(shè)置了d0、w0、w1、reg、mod1、rm變量來記錄方向標(biāo)志,第一和第二操作數(shù)的字或字節(jié)形式以及產(chǎn)生尋址方式字節(jié)所需的reg、mod1、rm值。為了控制操作碼域以及操作數(shù)域的掃描和加工處理,我們分別為操作碼域和操作數(shù)域設(shè)計(jì)了相應(yīng)的狀態(tài)表。對應(yīng)于操作碼域的是狀態(tài)表1(見表12-4)。由于狀態(tài)表1較長,因而我們只進(jìn)行原理性的示意。

表12-4中,字符欄的字符與掃描指針當(dāng)前掃描到的字符進(jìn)行匹配,若相等,則根據(jù)對應(yīng)的參考碼值來決定是轉(zhuǎn)向下一個(gè)狀態(tài)還是轉(zhuǎn)加工子程序處理。當(dāng)參考碼值為0FH時(shí),一律根據(jù)轉(zhuǎn)向/子程序欄的偏移值轉(zhuǎn)下一狀態(tài)繼續(xù)掃描;若參考碼值非0FH,則轉(zhuǎn)向/子程序欄之值即為加工處理子程序的編號。由于轉(zhuǎn)向與加工處理兩者不同時(shí)存在,故為了節(jié)省狀態(tài)表的存儲(chǔ)空間將這兩者共用一欄,即轉(zhuǎn)向/子程序欄。該欄的值究竟是狀態(tài)轉(zhuǎn)向的偏移量還是加工子程序的編號由參考碼的值來判別,因此,參考碼欄擔(dān)負(fù)著存放指令參考碼并判別是轉(zhuǎn)向還是加工處理的雙重職責(zé)。表12-4狀態(tài)表1例如,對指令A(yù)DD由狀態(tài)表1控制掃描的過程如下:

首先由S1狀態(tài)開始掃描指令A(yù)DD的第一個(gè)字符“A”,而狀態(tài)S1所對應(yīng)的字符恰好也是“A”,即匹配;查參考碼欄值為0FH,故轉(zhuǎn)向/子程序欄存放的是狀態(tài)轉(zhuǎn)向的偏移值,據(jù)此偏移值轉(zhuǎn)到狀態(tài)A0。

接下來掃描AAD的第二個(gè)字符“A”,而狀態(tài)A0所對應(yīng)的字符也是“A”,這兩者匹配,查參考碼欄值仍為0FH,故繼續(xù)按轉(zhuǎn)向/子程序欄中的偏移值轉(zhuǎn)到狀態(tài)A1。最后掃描到AAD的第三個(gè)字符“D”,而狀態(tài)A1當(dāng)前所對應(yīng)的字符是“A”,兩者不匹配,此時(shí)應(yīng)由狀態(tài)表的當(dāng)前位置下移一行,即指向狀態(tài)A1的下一行(注意,不匹配時(shí),由當(dāng)前狀態(tài)下移一行,若最終仍不能匹配則表明匯編指令書寫有錯(cuò)),此時(shí)所對應(yīng)的字符是“D”,與指令A(yù)AD的第三個(gè)字符匹配,仍查參考碼欄,此時(shí)的值為D5H(非0FH),即為該指令的參考碼,而轉(zhuǎn)向/子程序欄的值為加工處理子程序的編號值,即系統(tǒng)按此編號轉(zhuǎn)向相應(yīng)的子程序進(jìn)行加工處理。那么,如何發(fā)現(xiàn)輸入的匯編指令書寫有錯(cuò)呢?假如誤將指令A(yù)DD寫成ABD,那么在狀態(tài)A0掃描到ABD的第二個(gè)字符“B”時(shí),由于A0當(dāng)前所對應(yīng)的字符是“A”,故不匹配,由當(dāng)前狀態(tài)繼續(xù)下移一行,再用當(dāng)前新狀態(tài)所對應(yīng)的“D”與“B”進(jìn)行匹配,仍不成功,則狀態(tài)繼續(xù)下移一行,此時(shí)用“N”與“B”匹配也不成功,到此認(rèn)為輸入的匯編指令格式書寫有錯(cuò)。這里,我們使用了一個(gè)小技巧,因?yàn)樽帜复笮懙腁SCII碼差異僅在高4位上,大寫字母為“0100”,小寫字母為“0110”,所以為了掃描判別的簡便,對輸入的字母我們都將其屏蔽為大寫字母,而在狀態(tài)表中,對每一類狀態(tài),除該類狀態(tài)的最后一行的字母為小寫外,其余均為大寫字母。實(shí)際的比較過程是取出當(dāng)前狀態(tài)下對應(yīng)的字符(字母),然后屏蔽為大寫字母,再與當(dāng)前掃描的大寫字母比較,若不匹配再看當(dāng)前狀態(tài)下的這個(gè)字母值是否為小寫(判斷其值是否大于60H)。若為小寫,則是該類狀態(tài)下所允許出現(xiàn)的最后一個(gè)字母;若仍不匹配,則轉(zhuǎn)出錯(cuò)處理子程序執(zhí)行。

根據(jù)上述思想,現(xiàn)在可以得出掃描狀態(tài)表1的主控程序了。依照上面的例子,我們將主控程序用框圖描述如圖12-3所示。圖12-3主控程序框圖主控程序在實(shí)現(xiàn)時(shí)要略加修改,這是因?yàn)閷λ械?086/8088匯編指令,在掃描第一個(gè)字符時(shí)不可能產(chǎn)生操作碼(操作碼字符至少為兩個(gè)),而當(dāng)由掃描的第一個(gè)字符轉(zhuǎn)向下一個(gè)狀態(tài)時(shí),卻由于轉(zhuǎn)向的地址可能大于FFH(256個(gè)字節(jié)),因而使轉(zhuǎn)向/子程序欄無法用一個(gè)字節(jié)來表示。因此,將第一個(gè)字符掃描處理的狀態(tài)表改為如表12-5所示的形式。表12-5修改后的第一個(gè)字符掃描處理狀態(tài)表表12-5省去了參考碼欄而增加了狀態(tài)轉(zhuǎn)向欄的長度(為一個(gè)字)。對于第二個(gè)及以后字符的掃描則同前述狀態(tài)表1所示,沒有變化。

為了加工處理的方便,對操作數(shù)域的掃描我們設(shè)置了3個(gè)狀態(tài)表,其中主要的狀態(tài)表2見表12-6。

表12-6狀態(tài)表2大多數(shù)加工處理子程序都使用狀態(tài)表2來掃描匯編指令中的操作數(shù)域,一方面檢查操作數(shù)書寫格式的正誤;另一方面根據(jù)掃描所獲得的信息來形成機(jī)器碼指令的尋址方式字節(jié)以及后繼各數(shù)據(jù)字節(jié),同時(shí)也對存放在work1中的指令參考碼進(jìn)行修正。

進(jìn)入狀態(tài)表2的初始入口是S1。若在當(dāng)前狀態(tài)下,對應(yīng)的符號欄中的字符與匯編指令中的操作數(shù)掃描指針?biāo)赶虻淖址ヅ?,則取出參考碼單元D的內(nèi)容相加后再送入D,即(D)+參考碼D;然后根據(jù)加工處理欄指示的子程序編號轉(zhuǎn)向相應(yīng)的子程序進(jìn)行加工處理,處理結(jié)束后再根據(jù)狀態(tài)表的狀態(tài)改變欄所指示的狀態(tài)轉(zhuǎn)向下一個(gè)狀態(tài)繼續(xù)進(jìn)行掃描加工;如果此時(shí)狀態(tài)欄的內(nèi)容為0FFH,則意味著對操作數(shù)域的掃描加工結(jié)束而跳出狀態(tài)表2返回。如果當(dāng)前狀態(tài)對應(yīng)的符號欄中的字符與匯編指令操作數(shù)掃描指針?biāo)甘镜淖址黄ヅ?,則狀態(tài)表下移一行繼續(xù)尋求匹配,直至符號欄中出現(xiàn)0FFH,即表示所輸入的匯編指令操作數(shù)格式有錯(cuò)。

在進(jìn)行操作數(shù)加工處理時(shí),寄存器與寄存器之間的操作或立即數(shù)與寄存器之間的操作相對容易些,麻煩的是存儲(chǔ)器與寄存器或存儲(chǔ)器與立即數(shù)之間的操作。對于前者,參考碼直接給出該寄存器所對應(yīng)的reg值或r/m值(mod=11),見表12-7;而對于后者,在查狀態(tài)表過程中參考碼是累加的,我們將可能的結(jié)果與對應(yīng)的寄存器尋址方式列于表12-8中。表12-7存儲(chǔ)器與寄存器操作的狀態(tài)表表12-8存儲(chǔ)器與立即數(shù)操作的狀態(tài)表因此,通過查狀態(tài)表的過程我們能夠確定reg、r/m的值。如果是立即數(shù)與寄存器操作,則根本不需要mod值(見附錄1);如果是寄存器之間的操作,則mod值必為11。對于存儲(chǔ)器與寄存器或立即數(shù)之間的操作,如果在狀態(tài)表掃描到“]”之前沒有立即數(shù)(即位移量)出現(xiàn),則mod=00;如果有立即數(shù)出現(xiàn)且為8位,則mod=01;如果立即數(shù)為16位,則mod=10。注意,當(dāng)r/m=110,mod=00時(shí),可知這是直接存儲(chǔ)器尋址,即方括號“[”和“]”中是一個(gè)立即數(shù),這與我們表12-8所給出的形式不符。由于這是一個(gè)特例,故在狀態(tài)表2中當(dāng)掃描到“[”匹配時(shí),則調(diào)用一個(gè)處理子程序預(yù)讀匯編指令中“[”后面的部分,如果是16位立即數(shù)即為直接存儲(chǔ)器尋址,則處理加工過程由該子程序完成,即置r/m=110,mod=00;如果不是立即數(shù),則該子程序的操作作廢,繼續(xù)按狀態(tài)表2控制處理加工過程。

由附錄2可知,INC、DEC、PUSH和POP的操作數(shù)只有一個(gè)16位寄存器,故對此情況我們使用狀態(tài)表3來掃描處理。狀態(tài)表3見表12-9。表12-9狀態(tài)表3此外,對段寄存器的操作還設(shè)置了狀態(tài)表4,這里就不再列舉了。

狀態(tài)表2、狀態(tài)表3、狀態(tài)表4的格式都是一樣的,因此可以共用一個(gè)查找程序,實(shí)際設(shè)計(jì)也是如此。

到此為止,我們已經(jīng)對如何將一條匯編指令編譯為機(jī)器碼指令的各個(gè)階段及在各階段中所應(yīng)加工處理的操作有了較深入的了解。要了解8086/8088小匯編的具體實(shí)現(xiàn)細(xì)節(jié),請參閱12.4節(jié)。 12.38086/8088小匯編實(shí)驗(yàn)

12.3.1實(shí)驗(yàn)一8086/8088小匯編操作過程

1.實(shí)驗(yàn)?zāi)康?/p>

掌握DEBUG調(diào)試工具的使用方法,了解8086/8088小匯編的編譯過程。

2.實(shí)驗(yàn)內(nèi)容

用工具軟件DEBUG跟蹤調(diào)試8086/8088小匯編編譯匯編指令A(yù)AA和AADAL,02的全部過程,并記錄在匯編查找狀態(tài)表1以后所得到的指令參考碼,數(shù)據(jù)區(qū)DATA中的變量mod1、rm、d0、d1、w0、w1、t0、s0、m0,以及work1~work6中存放的數(shù)據(jù)值。當(dāng)編譯生成該指令的全部機(jī)器碼并返回到主控程序時(shí),再記錄上述各變量的值。

3.實(shí)驗(yàn)要點(diǎn)及其說明

注意使用DEBUG調(diào)試工具調(diào)試8086/8088小匯編程序的方法,特別應(yīng)掌握DEBUG中G、T、U等命令的使用以及調(diào)試到DOS功能調(diào)用(如INT21)時(shí)應(yīng)用G命令跳過該執(zhí)行過程,以免調(diào)試過程的復(fù)雜化。

4.示例

以下是使用DEBUG調(diào)試工具調(diào)試8086/8088小匯編程序的示例:注意,我們這里的小匯編程序是為16位教學(xué)機(jī)開發(fā)的,目前已在幾十所高校得到應(yīng)用。為了適應(yīng)實(shí)驗(yàn)教學(xué),我們?nèi)〉袅藢⒄麄€(gè)匯編程序翻譯成機(jī)器指令程序的功能,而是輸入一條匯編指令就得到與其對應(yīng)的機(jī)器指令代碼。這樣,條件轉(zhuǎn)移指令所要求的地址環(huán)境就不存在了,故條件轉(zhuǎn)移指令的翻譯不能進(jìn)行(但其翻譯子程序本身是正確的,并仍保留在小匯編程序中)。12.3.2實(shí)驗(yàn)二8086/8088的XCHG指令的編譯

溫馨提示

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

評論

0/150

提交評論