第五章 匯編語言程序設(shè)計(jì) - 浙江廣播電視大學(xué)玉環(huán)學(xué)院_第1頁
第五章 匯編語言程序設(shè)計(jì) - 浙江廣播電視大學(xué)玉環(huán)學(xué)院_第2頁
第五章 匯編語言程序設(shè)計(jì) - 浙江廣播電視大學(xué)玉環(huán)學(xué)院_第3頁
第五章 匯編語言程序設(shè)計(jì) - 浙江廣播電視大學(xué)玉環(huán)學(xué)院_第4頁
第五章 匯編語言程序設(shè)計(jì) - 浙江廣播電視大學(xué)玉環(huán)學(xué)院_第5頁
已閱讀5頁,還剩161頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

獻(xiàn)給正為信息化建設(shè)事業(yè)作出杰出貢獻(xiàn)的人們。計(jì)算機(jī)組成原理與匯編語言“四個(gè)現(xiàn)代化,哪一化也離不開信息化?!苯瓭擅瘛璓art2

匯編語言程序設(shè)計(jì)1、概述2、語句3、數(shù)據(jù)4、偽指令語句6、順序程序設(shè)計(jì)7、分支程序設(shè)計(jì)8、循環(huán)程序設(shè)計(jì)9、子程序設(shè)計(jì)10、實(shí)例11、匯編語言程序的開發(fā)5、宏指令語句

匯編語言部分目錄第五章匯編語言程序設(shè)計(jì)5.1概述匯編語言程序是把機(jī)器語言程序“符號化”,且用匯編語言書寫的符號指令(亦稱匯編指令)與用機(jī)器語言書寫的二進(jìn)制代碼指令(亦稱機(jī)器指令)有一一對應(yīng)關(guān)系。但是,用匯編語言編制的程序仍不能直接由汁算機(jī)識別與執(zhí)行,必須經(jīng)過“匯編”(即翻譯)轉(zhuǎn)換成機(jī)器語言指令代碼(即目標(biāo)程序),再由計(jì)算機(jī)識別并執(zhí)行。例5--l(P170)

求S=(A+B)*C/(A-B)

上述匯編語言源程序經(jīng)匯編后獲得機(jī)器語言目標(biāo)代碼,如圖5-1所示。從圖中可以看出源程序中匯編指令與機(jī)器語言目標(biāo)代碼(即機(jī)器措令)有一一對應(yīng)關(guān)系。

從這個(gè)例子可以看出,一個(gè)匯編語言源程序是由若干邏輯段組織的。每個(gè)邏輯段由偽指令SEGMENT開始,以偽指令ENDS作結(jié)束。DATA,STACK,CODE等是一個(gè)邏輯段的段名。每一個(gè)邏輯段可有若干語句,在本例子中僅有指令語句和偽指令語句兩種。指令浯句表示要計(jì)算機(jī)完成的一個(gè)具體運(yùn)算或操作、而偽指令語句是用于指示匯編程序如何“翻譯”(即匯編)源程序。偽指令語句是本章要重點(diǎn)介紹的內(nèi)容之一。從這個(gè)例子的源程序可以看出Iintel8086/88匯編語言源程序的框架結(jié)構(gòu)如下:段名1

SEGMET…段名1ENDS

段名2SEGMET…

段名2ENDS

段名3SEGMET…

段名3ENDS…ENDS(標(biāo)號)一個(gè)匯編語言源程序有幾個(gè)邏輯段完全由編程人員根據(jù)需要確定,每個(gè)邏輯段的大小是任意的。5.2匯編語言語句同高級語言程序一樣,一個(gè)匯編語言源程序是不能由計(jì)算機(jī)直接運(yùn)行的。它必須經(jīng)過匯編程序(assemble)的匯編(即翻譯)生成一個(gè)目標(biāo)程序(即機(jī)器語言程序),目標(biāo)程序再通過連接、裝配形成可執(zhí)行文件,然后載入內(nèi)存中才能執(zhí)行它。匯編程序是計(jì)算機(jī)系統(tǒng)軟件之一。MASM(macroassembler)就是支持InteI8086/88系列微機(jī)的,含有宏功能的宏匯編程序。MASM提供了構(gòu)造匯編語言源程序的語法規(guī)則。除有定義數(shù)據(jù)、符號、標(biāo)號、變量、邏輯段、過程等多種偽指令外,還規(guī)定了源程序的基本語句種類和格式。語句(statment)乃是匯編語言程序的基本組成單位。一個(gè)匯編語言源程序有3種基本語句即指令語句、偽指令語句和宏指令語句(或稱宏調(diào)用語句)。前兩種是最常見最基本的語句。有關(guān)宏指令語句將在本章5.9節(jié)中討淪。指令語句和偽指令語句有相同的語句格式,但是在程序中所起的作用和實(shí)現(xiàn)的功能是不相同的。而且這兩種語句作用與功能的實(shí)現(xiàn)方式和時(shí)間也是不相同的。指令語句就是第4章所述指令系統(tǒng)的各條指令,每一條指令語句在源程序匯編時(shí)都要產(chǎn)生可供計(jì)算機(jī)執(zhí)行的指令代碼(即目標(biāo)代碼),所以指令語句又叫可執(zhí)行語句。每一條指令語句表示計(jì)算機(jī)將要完成的一個(gè)運(yùn)算或操作,如傳送數(shù)據(jù),兩數(shù)據(jù)的加、減、乘、除運(yùn)算等,而這種運(yùn)算或操作是在目標(biāo)程序(即指令代碼)運(yùn)行時(shí),依賴于計(jì)算機(jī)內(nèi)的中央處理器(CPU)、存儲器、I/O接口等硬設(shè)備來實(shí)現(xiàn)的。偽指令語句是指示(命令)匯編程序如何匯編源程序,所以這種語句又叫命令語句。偽指令語句是由偽指令和相關(guān)操作數(shù)組成,它的功能是由匯編程序在匯編源程序時(shí),通過執(zhí)行一段程序來實(shí)現(xiàn)的,而不是在運(yùn)行目標(biāo)程序時(shí)完成的。源程序中的偽指令語句是用于指示匯編程序:源程序中定義了哪些數(shù)據(jù)、符號,存儲單元如何分配,如何設(shè)置堆棧,程序中如何劃分邏輯段,哪些是當(dāng)前段,它們分別由哪個(gè)段寄存器指向,等等。在匯編源程序時(shí),偽指令語句除定義與預(yù)置的具體數(shù)據(jù)要生成目標(biāo)代碼外,其他均沒有對應(yīng)的目標(biāo)代碼(偽指令本身均沒有對應(yīng)的目標(biāo)代碼)。指令語句和偽指令語句有相同的語句格式,每個(gè)語句均由4個(gè)字段(Fields)組成:

名字操作符操作數(shù);注釋

每個(gè)字段意義如下:1.名字字段(NameField)

在指令語句中,這是一個(gè)任選字段,它叫標(biāo)號,且一定是用“:”作為標(biāo)號的結(jié)束符。標(biāo)號是一條指令的符號地址。通常是一個(gè)程序段或子程序的入口指令語句選用標(biāo)號。當(dāng)需要轉(zhuǎn)入這個(gè)程序段或調(diào)用子程序時(shí),就可以直接引用這個(gè)標(biāo)號。在偽指令語句中,對于不同的偽指令,這個(gè)字段有不同的名字。它們可以是常量名、變量名、段名和過程名等。這個(gè)字段是任選的還是必需的,要視偽指令而定。例如定義邏輯段和過程的偽指令語句,這個(gè)字段(分別叫段名和過程名)就是必需的;而定義數(shù)據(jù)的偽指令語句,這個(gè)字段就是任選的。偽指令語句中名字字段后面用空格作結(jié)束符,不得使用冒號,這是它與指令語句的-個(gè)主要區(qū)別。

2.操作符字段(OperatorField)這是一個(gè)語句不可缺少的主要字段,它體現(xiàn)了該語句的功能與操作要求。在指令語句中,這個(gè)字段就是指令助記符,如MOV,ADD,SUB等指令,它表示目標(biāo)程序在運(yùn)行時(shí)中央處理器CPU應(yīng)完成的功能。在偽指令語句中,這個(gè)字段就是本章后面即將介紹的各種偽指令,如:數(shù)據(jù)定義偽指令DB,DW,DD,段定義偽指令SEGMENT/ENDS,過程定義偽指令PROC/ENDP等,這些偽指令告訴匯編程序如何匯編(翻譯)源程序各語句。它們的操作要求都是在匯編源程序時(shí)由匯編程序具體實(shí)現(xiàn)的。3.操作數(shù)字段(OperandField)一個(gè)語句中,本字段是否需要,需要幾個(gè),需要什么形式的操作數(shù)等都由該語句操作符字段(指令助記符/偽指令)確定。如果需要本字段,那么本字段與操作符字段用空格或制表符TAB作分界符。如果本字段有兩個(gè)或兩個(gè)以上操作數(shù),那么各操作數(shù)之間用逗號,或空格分隔。4.注釋字段(CommentField)這是一個(gè)任選字段。如選用本字段,必須以分號作為字段的開始符。本字段可由任意字符串(含中文)表示,它通常是對某些程序段或指令加以注解,說明它們的功能及意義。這個(gè)字段的內(nèi)容不影響程序和指令/偽指令的功能,它也不出現(xiàn)在目標(biāo)代碼中。這個(gè)字段是為提高程序的可讀性和可維護(hù)性而加入的。當(dāng)需要作較多的文字說明時(shí),可以讓一個(gè)語句只有注釋字段,這時(shí)本語句的第一個(gè)有效字符必須是分號。名字字段的名字(如標(biāo)號、常量名、變量名、段名和過程名等)是由若干字符構(gòu)成的。組成名字(“名字”有時(shí)稱謂符號或標(biāo)識符)的規(guī)則是:①字符個(gè)數(shù)是1~31個(gè);②名字的第一個(gè)字符必須是字母、問號、@或下劃線(“_”)等4種字符之一;③不得使用屬于系統(tǒng)專用的保留字。保留字主要包括:中央處理器中各寄存器名(如AX,BX,CS,DS等),指令助記符(如MOV,ADD,SUB等),偽指令(如DB,DW、SEGMENT,PROC等),各種運(yùn)算操作符(如GE,EQ,PTR,OFFSET,SEG等)。5.3匯編語言數(shù)據(jù)5.3.1符號定義語句為便于編制和調(diào)試程序,程序設(shè)計(jì)人員常用一些容易理解和記憶的符號來表示某些常數(shù)或表達(dá)式。為此就使用符號定義偽指令,這種偽指令有以下兩種:1.等值偽指令格式:符號EQU表達(dá)式/符號

其中,EQU是等值偽指令,它把右邊(表達(dá)式/符號)的值或符號賦給EQU左邊的符號。通常,(表達(dá)式/符號)有如下幾種:

(1)常數(shù)或數(shù)值表達(dá)式例如:COUNTEQU15COMPUTEREQU15*5+46(2)地址表達(dá)式

例如:ADDR1EQUDS:[BP]ADDR_WEQUWORDPTR[BX]ADDR_B

EQUBYTE

PTR[BX]

其中PTR是屬性修改運(yùn)算符(詳見53.4)。(3)變量名、標(biāo)號或指令助記符為已定義的變量名、標(biāo)號或指令助記符另取一個(gè)“別名”。例如:

NUM1EQUCOUNT1;為變量名COUNT1另定義一個(gè)別名

BEINGEQUSTART;為標(biāo)號START另定義一個(gè)別名

BTODEQUDAA;為指令助記符DAA另定義一個(gè)別名等值偽指今語句僅在匯編源程序時(shí),作為替代符號用,不產(chǎn)生任何目標(biāo)代碼,也不分配存儲單元。在同一源程序中,同一符號不能用EQU偽指令重新定義。例如:

BTODEQUDAANUMEQU100H…BTODEQUAAANUMEQU200H上述語句中,后兩條語句因符號重新定義而出現(xiàn)語法錯(cuò)誤。2.等號偽指令格式:符號=表達(dá)式/符號這種偽指令的含義和作用與EQU等值偽指令相同。但是它們兩者有如下差異:(1)等號偽指令可以重新定義符號。例如:

COUNT=15HNUM=100H…COUNT=3OHNUM=NUM+100H(2)等號偽指令可以為已定義的變量名或標(biāo)號定義另一別名,但不能為指令助記符定義另一別名。例如:

NUMI=COUNT1;為變量名COUNT1定義另一別名

BEING=START;為標(biāo)號START定義另一別名而BTOD=DAA;為指今助記符DAA定義別名出錯(cuò)。5.3.2數(shù)據(jù)定義語句為在存儲區(qū)中,設(shè)置常數(shù)、數(shù)據(jù)或保留若干存儲單元,應(yīng)使用數(shù)據(jù)定義偽指令DB(定義字節(jié)數(shù)據(jù))、DW(定義字?jǐn)?shù)據(jù))和DD(定義雙字?jǐn)?shù)據(jù))等(DF,DQ,DT分別定義6,8,10字節(jié)數(shù)據(jù)偽指令,可查閱有關(guān)資料)。用這些偽指令構(gòu)成數(shù)據(jù)定義語句的格式如下:變量名DB表達(dá)式1,表達(dá)式2,…變量名DW表達(dá)式1,表達(dá)式2,…變量名DD表達(dá)式1,表達(dá)式2,…這些偽指令要求匯編程序分配若干存儲單元,并用表達(dá)式1、表達(dá)式2等數(shù)據(jù)分別載入這些存儲單元。數(shù)據(jù)定義語句中,變量名是任選的。如果選用變量名,那么這個(gè)變量名就是分配的若干存儲單元中首字節(jié)單元的符號地址。在程序中,對這些存儲單元存取數(shù)據(jù)時(shí),就可直接引用變量名。數(shù)據(jù)定義語句必須出現(xiàn)在某個(gè)邏輯段中。SEGMENT/ENDS表示邏輯段的開始/結(jié)束(SEGMENT/ENDS偽指令詳見5.4.1)。例如:

DATASEGMENTVAR1DB12HVAR2DWI234H

VAR3DDI2345678H

DATAENDS

上述邏輯段中有3個(gè)數(shù)據(jù)定義語句。經(jīng)過定義的變量,每個(gè)變量均有3個(gè)屬性:(1)段屬性(SEG)

它表示變量存放在哪個(gè)邏輯段中,且用這個(gè)邏輯段的段基值表示。例如上述定義的VAR1,VAR2,VAR3等3個(gè)變量是在段名為DATA的邏輯段中,它們的段屬性就是DATA段的段基值。(2)偏移量屬性(OFFSET)

它表示變量在邏輯段中離段起始單元(段基址)的距離(字節(jié)數(shù))。例如VAR1的偏移量為0,VAR2的偏移量為1,VAR3的偏移量為3。上述段和偏移量兩個(gè)屬性就構(gòu)成一個(gè)變量的邏輯地址。(3)類型屬性(TYPE)它表示變量的數(shù)據(jù)大?。鹤止?jié)數(shù)據(jù),字?jǐn)?shù)據(jù),雙字?jǐn)?shù)據(jù)。這個(gè)類型屬性是依據(jù)DB,DW,DD偽指令來確定的。例如VAR1是字節(jié)數(shù)據(jù),VAR2是字?jǐn)?shù)據(jù),VAR3是雙字?jǐn)?shù)據(jù)。數(shù)據(jù)定義語句按照偽指令DB,DW和DD所確定的數(shù)據(jù)大小來分配相應(yīng)數(shù)量的存儲單元,同時(shí)給這些存儲單元預(yù)置由對應(yīng)表達(dá)式確定的初值。表達(dá)式有如下幾種情況:

1.數(shù)值表達(dá)式例如:

DA_BI

DB50

DA_B2

DB12H,34H,56H

DA_W1DW1234H

DA_W2DW1234H,5678H,9ABCH一個(gè)數(shù)據(jù)定義語句可以只設(shè)置一個(gè)字節(jié)、字或雙字?jǐn)?shù)據(jù),也可以設(shè)置多個(gè)字節(jié)、字或雙字?jǐn)?shù)據(jù)。在設(shè)置多個(gè)數(shù)據(jù)時(shí),各個(gè)數(shù)據(jù)依次按字節(jié)、字或雙字連續(xù)存儲單元存放,其變量名是這一連續(xù)存儲單元的首字節(jié)單元的符號地址。存放第二個(gè)數(shù)據(jù)(字節(jié)、字或雙字?jǐn)?shù)據(jù))的存儲單元地址應(yīng)分別是該變量名+1,+2或+4。存放第三個(gè)數(shù)據(jù)的單元地址分別是該變量名+2,+4,+8,其余依次類推。例如DA_B2字節(jié)存儲單元中存放的數(shù)據(jù)是12H;DA_B2+1,DA_B2+2字節(jié)存儲單元中存放的數(shù)據(jù)是34H,56H。DA_W2字存儲單元中存放的數(shù)據(jù)是1234H,而數(shù)據(jù)5678H,9ABCH則分別存放在DA_W2+2,DA_W2+4字存儲單元中。在存放字、雙字?jǐn)?shù)據(jù)時(shí),仍遵循低字節(jié)存故低8位,高字節(jié)存放高8位的原則。數(shù)據(jù)定義語句中表達(dá)式可以用二進(jìn)制、八進(jìn)制、十進(jìn)制或十六進(jìn)制數(shù)表示,但存放在存儲單元中一定是二進(jìn)制數(shù)。為便于人們觀察、記憶,都用十六進(jìn)制數(shù)表示。例如第一個(gè)數(shù)據(jù)定義語句設(shè)置數(shù)據(jù)初值是十進(jìn)制數(shù)50,但存放在DA_B1字節(jié)單元中是32H。2.?表達(dá)式不帶引號的?表示可頂置任意內(nèi)容。?表達(dá)式通常是用于保留一個(gè)或多個(gè)存儲單元.以備程序運(yùn)行時(shí),作工作單元或保存結(jié)果用。例如:

VAR_BDB?,?

VAR_WDW?,?

上述兩語句要求匯編程序分別分配兩個(gè)字節(jié)存儲單元和兩個(gè)字存儲單元,且這些存儲單元中可以是任意內(nèi)容(通常是00H)。3. 字符串表達(dá)式當(dāng)表達(dá)式為字符串時(shí),字符串必須用引號(單引號或雙引號)括起來。字符串中各字符均是以ASCII碼形式存放在相應(yīng)存儲單元中。對于DB,DW,DD偽指令,字符串在程序中的表示形式和字符ASCII碼的存儲順序有一些差異。對于DB偽指令,每一個(gè)字符串中字符個(gè)數(shù)不得超過256個(gè),-個(gè)字符分配一個(gè)字節(jié)存儲單元,按地址遞增的排列順序依次存放字符串自左至右的每一個(gè)字符的ASCII碼。例如:

STRING1DB`ABCDEF`

這字符串在存儲器的存儲情況如圖5-2(a)所示。對于DW偽指令,每一個(gè)字符串只能由1~2個(gè)字符組成,并分配兩個(gè)字節(jié)存儲單元。例如:

STRING2DW`AB`,`CD`,`EF`若是兩個(gè)字符組成,那么前一個(gè)字符(如A,C,E)的ASCII碼放在高字節(jié)中,后一個(gè)字符(如B,D,F(xiàn))的ASCII碼存放在低字節(jié)中。若僅是一個(gè)字符,那么該字符的ASCII碼存放在低字節(jié)中,高字節(jié)以00填充。DW偽指令語句中字符串表達(dá)式的存儲惰況如圖5-2(b)所示。對于DD偽指令,每一個(gè)字符串只能由1~2個(gè)字符組成,并分配4個(gè)字節(jié)存儲單元。其中1~2個(gè)字符的ASCII碼存儲在兩個(gè)低字節(jié)(存儲順序與DW偽指令相同)中,兩個(gè)高字節(jié)均存放00H。例如:

STRING3DD`AB`,`CD`

圖5-2(c)顯示了DD偽指令語句字符串表達(dá)式的存儲惰況。4.帶DUP表達(dá)式

DUP(Duplication)是定義重復(fù)數(shù)據(jù)操作符。在表達(dá)式中,使用DUP操作符格式如下:變量名DB

表達(dá)式1DUP(表達(dá)式2)變量名DW表達(dá)式1DUP(表達(dá)式2)變量名DD

表達(dá)式1DUP(表達(dá)式2)其中表達(dá)式1是數(shù)據(jù)的重復(fù)次數(shù),表達(dá)式2是重復(fù)數(shù)據(jù)的內(nèi)容。例如:

NU_B1DB10HDUP(?)

NU_B2DB20HDUP(`ABCD`)

NU_W1DW20HDUP(1OH)上面第1個(gè)語句表示保留10H個(gè)字節(jié)單元,每個(gè)字節(jié)單元可預(yù)置任意內(nèi)容。第2個(gè)語句表示重復(fù)20H個(gè)字符串`ABCD`,共占有4*20H=80H個(gè)字節(jié)存儲單元。第3個(gè)語句重復(fù)20H個(gè)字存儲單元,每個(gè)單元預(yù)置數(shù)據(jù)為10H,共占有20H*2=40H個(gè)字節(jié)存儲單元。NU_B1,NU_B2,NU_W1分別是這3個(gè)重復(fù)數(shù)據(jù)存儲區(qū)中首字節(jié)的符號地址。

DUP操作符可以嵌套使用,即表達(dá)式2可以又是一個(gè)帶DUP的表達(dá)式。例如:

NU_B3DB10HDUP(5DUP(4),10H)

這數(shù)據(jù)定義語句表示數(shù)據(jù)序列“4,4,4,4,4,10H”重復(fù)10H次,它共占有6*10H個(gè)字節(jié)存儲單元。5.3.3數(shù)據(jù)一個(gè)語句操作數(shù)字段的主要內(nèi)容是數(shù)據(jù)。程序中數(shù)據(jù)除常數(shù)(數(shù)值常數(shù)和字符常數(shù))外,有大量的數(shù)據(jù)是在寄存器(即寄存器操作教)和存儲單元(即存儲器操作數(shù))中。一個(gè)數(shù)據(jù)有它的數(shù)值和屬性兩部分,這兩部分對一個(gè)語句匯編成機(jī)器目標(biāo)代碼都有直接關(guān)系。

一.常數(shù)常數(shù)是沒有任何屬性的純數(shù)值。在匯編期間,它的值已能完全確定,且在程序運(yùn)行中,它也不會發(fā)生變化。常數(shù)分為數(shù)值常數(shù)和字符常數(shù)。1.?dāng)?shù)值常數(shù)

在程序中,可以用不同進(jìn)位制數(shù)的形式表示一個(gè)數(shù)值常數(shù)。(1)二進(jìn)制數(shù)以字母B結(jié)尾的0和1組成的數(shù)字序列,如01101011B。(2)八進(jìn)制數(shù)以字母O或Q結(jié)尾的0~7數(shù)字序列組成的數(shù),如123O,7501Q。(3)十進(jìn)制數(shù)0~9數(shù)字序列,可以用字母D結(jié)尾,也可以沒有結(jié)尾字母,如1999D或1999。(4)十六進(jìn)制數(shù)以字母H結(jié)尾的0~9和A~F(或a~f)的數(shù)字字母序列,如3BC7H,0ABCDH。為便于區(qū)分由A~F(或a~f)組成的數(shù)字字母序列是一個(gè)十六進(jìn)制數(shù)還是-個(gè)符號(名字),規(guī)定凡以A~F(或a~f)為起始的一個(gè)十六進(jìn)制數(shù),必須在前面冠以數(shù)字0,否則匯編程序?qū)⑵湔J(rèn)作標(biāo)識符(符號)。2.字符常數(shù)用單引號或雙引號括起來的-個(gè)或多個(gè)字符組成的字符序列稱為字符常數(shù)。這些字符是用它的ASCII碼形式表示的。例如字符`A`的值是4IH,字符串`AB`的值是4142H。

在程序中,常數(shù)主要應(yīng)用于:⑴在指令語句的源操作數(shù)中作立即數(shù)操作數(shù)。它可以是8位或16位數(shù)值常數(shù),也可以是1~2字符常數(shù)。例如:

MOVAL,0ABH

MOVBX,78FCH

MOVAL,`A`

MOVBX`AB`⑵在指今語句的尋找存儲器操作數(shù)的各種尋址方式中作位移量。例如:

MOVAL,DS:[140H];直接尋址方式

MOVBX,45H[SI];變址尋址方式

MOV0FFH[BP],AL;基址尋址方式

MOV1234H[BX][DI],AX;基址變址尋址方式⑶在某些偽指令語句的操作數(shù)字段中,賦值數(shù)據(jù)。如數(shù)據(jù)定義偽指令中,為分配的存儲單元預(yù)置初值數(shù)據(jù),在符號定義偽指令語句的操作數(shù)字段中,為定義符號賦值數(shù)據(jù)。例如:

COUNTEQU100;為符號COUNT賦值

DB12H;定義一個(gè)字節(jié)數(shù)據(jù)

DW1234H;定義一個(gè)字?jǐn)?shù)據(jù)

DB`ABCDEF`;定義6個(gè)字符的字符常數(shù)二.寄存器操作數(shù)

CPU中通用寄存器和段寄存器的內(nèi)容可作操作數(shù)來使用,其數(shù)據(jù)可以是8位或16位。除CS僅可作源操作數(shù)外,其他寄存器既可存放源操作數(shù),也可存放目的操作數(shù)。指令指針I(yè)P不可作寄存器操作數(shù)使用。當(dāng)某寄存器的內(nèi)容作操作數(shù)的數(shù)據(jù)時(shí),用寄存器名表示即可。但是,當(dāng)某寄存器(如BX,BP,SI,DI)作地址指針時(shí),用方括號把寄存器名括起來表示。當(dāng)使用16位寄存器(如AX,BX,CX,DX)時(shí),這時(shí)一定是字操作數(shù);使用8位寄存器(如AL,AH,BL,BH,CL,CH,DL,DH)時(shí),這時(shí)一定是字節(jié)操作數(shù)。三、存儲器操作數(shù)存儲器操作數(shù)是指存儲單元中的內(nèi)容。變量、標(biāo)號及地址表達(dá)式是這種操作數(shù)的主要表示形式。1.變量在一個(gè)邏輯段中,用數(shù)據(jù)定義語句定義并預(yù)置數(shù)據(jù)初值后,變量名就作為存儲單元的符號地址,代表了存放在存儲單元的數(shù)據(jù)。引用變量名就是使用變量。在程序的其他語句中,使用變量分兩種情況:

(1)在指令語句的操作數(shù)字段中,變量名作為地址表達(dá)式的組成部分之一。在尋找存儲器操作數(shù)的幾種尋址方式中,除寄存器間接尋址方式不使用變量名外,其他幾種尋址方式均可使用變量名。例如在某數(shù)據(jù)段已定義一變量:

VARDB40HDUP(12H)那么,幾種含有變量名的地址表達(dá)式為:直接尋址:VAR

VAR+10H

變址尋址:VAR[SI]VAR+5[DI]

基址尋址:VAR[BX]VAR+10H[BP]

基址變址尋址:VAR[BX][SI]

VAR+20[BX][DI]-個(gè)地址表達(dá)式的值表示了存放操作數(shù)的存儲單元偏移量。在上述地址表達(dá)式中直接尋址方式直接由變量的偏移量或再加減一個(gè)常數(shù)獲得該指令操作數(shù)的存儲單元偏移量。其他尋址方式表達(dá)式的值由變量的偏移量與1~2個(gè)寄存器的內(nèi)容相加獲得,在相加時(shí)也可另外加減某些常數(shù)。這些地址表達(dá)式(除直接尋址)的意義是:指令要訪問的存儲單元是相對這個(gè)變量偏移一個(gè)距離,這個(gè)距離由1~2個(gè)寄存器(如BX,BP,SI,DI)的內(nèi)容和常數(shù)相加來確定的。所以它們是一種相對尋址。帶變量名的地址表達(dá)式的類型屬性(即數(shù)據(jù)的大小:字節(jié)、字、雙字)和該變量名的類型屬性一致。(2)在用DW或DD的數(shù)據(jù)定義語句中,如果操作數(shù)字段是引用的變量名,那么在DW或DD偽指令分配的存儲單元中,將預(yù)置被引用變量的地址部分段基值和偏移量。如使用DW,則僅有被引用變量的偏移量;如使用DD,則前兩個(gè)字節(jié)存放偏移量,后兩個(gè)字節(jié)存放段基值。在這種情況下,不能在DB數(shù)據(jù)定義語句中引用變量名。例如,在某數(shù)據(jù)段有如下數(shù)據(jù)定義語句:…

VAR1DB10HDUP(0)

VAR2DW10HDUP(`AB`)

ADR1DWVAR2

ADR2DDVAR2…

上述示例中,變量ADR1的內(nèi)容(即字存儲單元內(nèi)容)是變量VAR2的偏移量,而ADR2雙字存儲單元的內(nèi)容是變量VAR2的偏移量和段基值。用這種方法可以很方便地構(gòu)造存放地址指針的變量,這在程序設(shè)計(jì)中是很有用的。2.標(biāo)號指令語句的名字字段上的名字叫標(biāo)號,它是一條指令的符號地址。標(biāo)號常作為轉(zhuǎn)移類指令(如無條件轉(zhuǎn)移指令、條件轉(zhuǎn)移指令、循環(huán)指令和子程序調(diào)用指令等)的操作數(shù),表示轉(zhuǎn)移的目標(biāo)地址。在程序中引入標(biāo)號后,使得程序的編寫更加方便,程序閱讀和維護(hù)更加容易。與變量一樣,每個(gè)標(biāo)號也有3個(gè)屬性:

(1)段屬性(SEG)

段屬性表示標(biāo)號所在指令在哪個(gè)邏輯段中,且用這個(gè)邏輯段的段基值表示。(2)偏移量屬性(OFFSET)

偏移量屬性表示標(biāo)號所在指令離段起始單元之間的字節(jié)數(shù)(準(zhǔn)確地講,是指這條指令目標(biāo)代碼的首字節(jié)單元與段起始單元之間相距的字節(jié)數(shù))。同樣,上述兩個(gè)屬性就構(gòu)成了這條指令的邏輯地址。

(3)類型屬性(TYPE)類型屬性表示了它的轉(zhuǎn)移特性,即是作為段內(nèi)轉(zhuǎn)移還是段間轉(zhuǎn)移的目標(biāo)地址。標(biāo)號的類型屬性有兩種:

NEAR(近):段內(nèi)轉(zhuǎn)移。本標(biāo)號只能作為標(biāo)號所在段轉(zhuǎn)移類指令的目標(biāo)地址。

FAR(遠(yuǎn)):段間轉(zhuǎn)移。本標(biāo)號可作為其他段(不是標(biāo)號所在段)轉(zhuǎn)移類指令的目標(biāo)地址。標(biāo)號的類型屬性可以用下面兩個(gè)辦法來設(shè)置:①隱含方式。當(dāng)某指令選定一標(biāo)號后,該標(biāo)號就隱含為NEAR屬性。例如:

NEXT:MOVAX,1234H

這時(shí)標(biāo)號

NEXT就具有NEAR的類型屬性。隱含方式不能沒置FAR屬性。②用標(biāo)識偽指令LABEL設(shè)置類型屬性。LABEL偽指令語句格式是:名字LABEL類型

LABEL偽指令的意義是:指定名字(如標(biāo)號、變量名)的類型屬性。它通常是與指令語句、數(shù)據(jù)定義語句配合使用,以補(bǔ)充設(shè)置類型屬性。

當(dāng)與指令語句連用時(shí),LABEL語句中的名字就是一個(gè)新的標(biāo)號,其類型可選擇NEAR或FAR。當(dāng)與數(shù)據(jù)定義語句連用時(shí),LABEL語句中的名字就是新的變量名,其類型可選擇BYTE,WORD,DWORD。這個(gè)新的標(biāo)號或變量名與同它們連用語句的標(biāo)號或變量名有相同的段和偏移量屬性,即同連用的語句有相同的邏輯地址。下面分兩種情況說明它的使用:

a.LABEL語句與指令語句連用例如:

SUB1_FARLABELFAR

SUB1:MOVAX,789AH

上述指令語句“MOVAX,789AH”有二個(gè)相同段和偏移量屬性的標(biāo)號,即SUB1和SUB1_FAR。但它們有不同的類型屬性,標(biāo)號SUB1是NEAR,而標(biāo)號SUB1_FAR是FAR。假如這指令是某程序段的入口處,那么,當(dāng)段內(nèi)程序要轉(zhuǎn)移到此程序段時(shí),可用SUB1作程序段的入口;當(dāng)其它段的程序要轉(zhuǎn)移到此程序段時(shí),就用SUB1_FAR作程序段的入口。

b.LABEL語句與數(shù)據(jù)定義連用例如:

DA_B1LABELBYTEDA_W1DW10HDUP(1234H)

上述變量DA_W1的數(shù)據(jù)類型為字,因此每次對它的存取是按字(二個(gè)字節(jié))進(jìn)行。如“MOVAX,DA_WI+4”指令就是把DA_Wl起始的第5,6個(gè)字節(jié)組成的第3個(gè)字送AX。欲想只取出第5個(gè)字節(jié)的內(nèi)容,這時(shí)可用“MOVAL,DA_B1+4”指令。又如:DA_W2LABELWORDDA_B2DB10HDUP(12H,34H)

這時(shí),“MOVAL,DA_B2+6”是取出DA_B2起始的第7個(gè)字節(jié),而“MOVAX,DA_W2+6”指令是取出DA_B2起始的第7,8兩個(gè)字節(jié)組成的第4個(gè)字。

5.3.4運(yùn)算符表達(dá)式是操作數(shù)常見的形式,它是由常數(shù),變量和標(biāo)號通過運(yùn)算符連接而成的。任一表達(dá)式的值是在程序匯編過程中進(jìn)行計(jì)算確定的,不是在程序運(yùn)行時(shí)求得的。這里介紹的MASM宏匯編語言的運(yùn)算符有算術(shù)運(yùn)算符、邏輯運(yùn)算符、關(guān)系運(yùn)算符、數(shù)值返回運(yùn)算符和屬性運(yùn)算符等5種。

1.算術(shù)運(yùn)算符

P183表5-1列出算術(shù)運(yùn)算符。表中所列前兩個(gè)運(yùn)算符是單項(xiàng)運(yùn)算符,表示數(shù)的正負(fù)。+,-,*,/,MOD是常用的運(yùn)算符,舉加運(yùn)算的數(shù)和運(yùn)算的結(jié)果均是整數(shù)。減法可用于同段內(nèi)兩個(gè)以變量名表示的存儲單元地址(偏移量)相減,其結(jié)果是一個(gè)常數(shù),表示這兩個(gè)存儲單元之間的相距字節(jié)數(shù)。例如:

ORG30H

;下面定義數(shù)據(jù)的起始偏移量是30HDA1DB`ABCDEFGH`DA2DW1234H,`EF`COUNT=DA2-DA1;38H-30H=8

上述COUNT是兩個(gè)變量(DA1,DA2)的偏移量相減,其結(jié)果正好是以DA1為首址占用的單元字節(jié)數(shù)。表5-1中最后兩個(gè)是邏輯移位運(yùn)算符。SHR進(jìn)行右移時(shí),最左邊以0填之;SHL進(jìn)行左移時(shí),最右邊以0填之,移位的位數(shù)由運(yùn)算符中的“次數(shù)”決定。移位運(yùn)算符與移位指令是完企不同的兩回事。移位運(yùn)算符是對某一具體數(shù)(常數(shù))在匯編時(shí)完成移位的,而移位指令是對一個(gè)寄存器操作數(shù)或存儲器操作教,在程序運(yùn)行時(shí)執(zhí)行移位的。根據(jù)它們在一條語句中出現(xiàn)的位置可以判斷出它是移位運(yùn)算符還是移位指令。2.邏輯運(yùn)算符

P184表5-2給出4個(gè)邏輯運(yùn)算符,參加運(yùn)算的數(shù)和運(yùn)算結(jié)果均是整數(shù),邏輯運(yùn)算是按位進(jìn)行的。同移位運(yùn)算符一樣,邏輯運(yùn)算符與邏輯運(yùn)算指令是完全不同的兩回事。邏輯運(yùn)算符是在匯編源程序時(shí),對一個(gè)具體數(shù)(常數(shù))進(jìn)行邏輯運(yùn)算,不能對一個(gè)寄存器操作數(shù)或存儲器操作數(shù)進(jìn)行邏輯運(yùn)算。且它一定是出現(xiàn)在一個(gè)語句的操作數(shù)字段中。而在語句的操作符字段上出現(xiàn)的是邏輯運(yùn)算指令,它在程序運(yùn)行時(shí),對一個(gè)寄存器操作數(shù)或存儲器操作數(shù)進(jìn)行按位邏輯運(yùn)算。3.關(guān)系運(yùn)算符

P184表5-3列出了6個(gè)關(guān)系運(yùn)算符。這些運(yùn)算符是用于比較兩個(gè)表達(dá)式值的大小。如果比較關(guān)系成立,則用全1表示為真,否則用全0表示為假。這兩個(gè)表達(dá)式可以是常數(shù)或同段的變量。若是常數(shù),按無符號數(shù)比較;若是變量則比較它們的偏移量大小。

4.數(shù)值返回運(yùn)算符這種運(yùn)算符的運(yùn)算對象是存儲器操作數(shù)即由變量名或標(biāo)號組成的地址表達(dá)式。運(yùn)算的結(jié)果是一個(gè)數(shù)值。運(yùn)算符的格式為

(運(yùn)算符)(地址表達(dá)式)

數(shù)值返回運(yùn)算符共有5

個(gè),其中2個(gè)(SEG,OFFSET)反映存儲器操作數(shù)的地址部分,另外3個(gè)(TYPE,LENGTH,SIZE)反映定義存儲器操作數(shù)的某些特征。⑴SEG運(yùn)算符和OFFSET運(yùn)算符這兩個(gè)運(yùn)算符出現(xiàn)在變量名或標(biāo)號的前面,返回這個(gè)變量名或標(biāo)號所在段的段基值或在段內(nèi)的偏移量。P185

例子

(2)TYPE運(yùn)算符

TYPE運(yùn)算符是用數(shù)字形式表示變量和標(biāo)號的類型屬性,如P185表5-4所示。其中,對變量的TYPE運(yùn)算結(jié)果正好反映定義變量時(shí),每個(gè)數(shù)據(jù)占有的存儲單元字節(jié)數(shù)。但對標(biāo)號的TYPE運(yùn)算結(jié)果沒有什么物理意義。(3)LENGTH運(yùn)算符和SIZE運(yùn)算符這兩個(gè)運(yùn)算符僅加在變量名的前面,它返回的是數(shù)組變量的元素個(gè)數(shù)(LENGTH)和數(shù)組變量所占的總字節(jié)數(shù)(SIZE)。LENGTH和SIZE運(yùn)算符的具體運(yùn)算規(guī)則是:如果變量是用重復(fù)操作符DUP定義的,那么運(yùn)算符LENGTH的運(yùn)算結(jié)果是外層DUP的給定值(即外層重復(fù)次數(shù)),如果沒有用DUP定義的變量,運(yùn)算結(jié)果總是1。而運(yùn)算符SIZE是LENGTH和TYPE兩個(gè)運(yùn)算結(jié)果的乘積。P186

例子

5.屬性運(yùn)算符屬性運(yùn)算符PTR是用來臨時(shí)對存儲器操作數(shù)的類型進(jìn)行沒定、說明。運(yùn)算符的格式如下:(類型)PTR(地址表達(dá)式)在某指令語句中使用PTR運(yùn)算符時(shí),把地址表達(dá)式確定的存儲單元臨時(shí)沒定為PTR運(yùn)算符左邊的類型(BYTE,WORD,DWORD或NAER,F(xiàn)AR)。這種類型屬性的設(shè)定僅在含有這運(yùn)算符的語句內(nèi)有效。P186

例子前兩條雙操作數(shù)指令語句中,由于其中一個(gè)操作數(shù)已分別是16位和8位的寄存器操作數(shù),為使一條指令中兩個(gè)操作數(shù)大小一致,所以用PTR運(yùn)算符臨時(shí)重新沒定另一個(gè)存儲器操作數(shù)的類型。第3條是單操作數(shù)指令語句,由于地址指針BX指向的存儲器操作數(shù)應(yīng)明確是字單元還是字節(jié)單元,所以在地址表達(dá)式前用PTR運(yùn)算符說明它的類型。第四條指令語句中常數(shù)30H可以是字常數(shù)0030H,也可能是字節(jié)常數(shù)30H,所以用PTR運(yùn)算符對目的操作數(shù)給予說明來確定此常數(shù)的大小。6.運(yùn)算符優(yōu)先級

當(dāng)一個(gè)表達(dá)式中同時(shí)有幾個(gè)運(yùn)算符時(shí),按運(yùn)算符優(yōu)先級順序執(zhí)行。P187表5-5給出各種運(yùn)算符的優(yōu)先級別。匯編源程序時(shí),按照以下規(guī)則計(jì)算表達(dá)式的值:(1)先執(zhí)行優(yōu)先級別高的運(yùn)算符;(2)優(yōu)先級別相同的運(yùn)算符,按照從左至右的順序進(jìn)行;(3)可用圓括號改變運(yùn)算的順序。5.4偽指令語句5.4.1段定義語句編制一個(gè)Intel8086/8088匯編語言源程序,段是基礎(chǔ)。這有兩個(gè)方面的含義:一是必須按段來構(gòu)造程序,二是程序的執(zhí)行,要憑借4個(gè)段寄存器對各段的存儲單元進(jìn)行訪問。一、段定義偽指令(SEGMENT/ENDS偽指令)當(dāng)程序需要設(shè)置一個(gè)段(邏輯段)時(shí),就必須使用段定義偽指令。它的格式是:段名

SEGMENT[定位類型][組合類型][`類別名`]…;本段語句序列(指令或數(shù)據(jù))段名ENDS每一個(gè)段都是用SEGMENT偽指令開始。用ENDS偽指令結(jié)束。其中:1.段名這是定義一個(gè)段不可少的部分,且段的開始和結(jié)束的段名必須一致。在程序中,當(dāng)需耍引

用某邏輯段時(shí),就用段名表示。段名的選取由用戶自己設(shè)定,通常選用與本段內(nèi)容相關(guān)的名字,如DATA1,DATA2,STACKI,CODE等名字作段名。2.定位類型定位類型表示對段的起始邊界的要求。它有4種選擇:(1)PAGE(頁)表示本段從一個(gè)頁的邊界開始。從存儲器0號單元開始,256個(gè)字節(jié)為一頁。所以段的起始地址一定是能以256整除。段起始單元地址(段基址)的最后8位二進(jìn)制數(shù)一定為0(即十六進(jìn)制數(shù)地址最后2位為00H)。(2)PARA(節(jié))如果定位類型未選,則隱含為PARA。它表示本段從一個(gè)小節(jié)的邊界開始。從存儲器0號單元開始,16個(gè)字節(jié)為一個(gè)小節(jié),所以段的起始單元最后4位二進(jìn)制數(shù)一定是0。如08370H,00510H等。

(3)WORD(字)表示本段從一個(gè)偶字節(jié)地址開始。如08732H,00514H,9915AH等。(4)BYTE(字節(jié))表示本段起始單元可以從任-地址升始。3.組合類型

組合類型表示段與段之間怎樣連接和定位的。它有6種選擇:(1)NONE這是隱含選擇,表示本段與其他段無連接關(guān)系。在裝入存儲器時(shí),本段有自己的物理段和段基址。(2)PUBLIC在滿足定位類型的前提下,本段與同段名且亦用PUBLIC說明的段鄰接在一起,形成一個(gè)新的邏輯段。它們公用新邏輯段的段基址,所有偏移量調(diào)整為相對于新邏輯段的段基址。(3)COMM○N產(chǎn)生一個(gè)覆蓋段,表示本段與其他同段名且亦用COMMON說明的段共享相同的存儲區(qū),有相同的段基址。共享存儲區(qū)的長度由同名段中最大的段確定。(4)STACK自動產(chǎn)生一個(gè)堆棧段。所有同段名的段連接成一個(gè)連續(xù)段,且系統(tǒng)自動對段寄存器SS和堆棧指針SP初始化在這個(gè)連續(xù)段。用戶程序中至少有-個(gè)段用STACK說明,否則需要用戶程序自己設(shè)置SS和SP。組合類型(5)AT表達(dá)式表示本段可定位在表達(dá)式所指示的小節(jié)邊界上。如AT0958H,表示本段從物理地址09580H開始。(6)MEMORY表示本段在存儲器中應(yīng)定位在所有其它段的最高地址。4.類別名類別名必須用單引號括起來。在連接處理時(shí),LINK把類別名相同的所有段放在連續(xù)的存儲區(qū)內(nèi),但是他們?nèi)允歉髯元?dú)立的段。定義一個(gè)邏輯段時(shí),段名是必選項(xiàng),而定位類型、組合類型和類別名三個(gè)參數(shù)是任選的,各參數(shù)之間用空格分隔。任選時(shí)可只選其中1~2個(gè),但是不能改變它們的失后順序關(guān)系。二、段尋址偽指令(ASSUME偽指令)

ASSUME偽指令格式如下:

ASSUME段寄存器名:段名,段寄存器名:段名,其中,段寄存器名是指4個(gè)段寄存器CS,DS,ES,SS中的一個(gè),段名是指用SEGMENT/ENDS偽指令語句中給定的段名,段寄存器名與段名之間必須用“:”分隔。ASSUME偽指令是告訴匯編程序已定義的段與段寄存器之間的對應(yīng)關(guān)系。P189例子

在上述程序段中,ASSUME偽指令語句告訴匯編程序,假設(shè)段寄存器CS,DS和ES分別存放CODE段,DATA1段和DATA2段的段基址,匯編程序在匯編每條指令語句時(shí),如有要訪問存儲器的操作(如取指令,存取操作數(shù))時(shí),就要進(jìn)行邏輯地址到物理地址的轉(zhuǎn)換,這時(shí)應(yīng)該知道使用哪個(gè)段寄存器,否則無法完成這條指令的匯編。例如上述程序段中兩條MOV指令中均要取出存儲器操作數(shù)VAR1和VAR2。變量VAR1是在DATA1段,它的段基值已在段寄存器DS中,這是對段寄存器DS的隱含使用。所以第一條MOV指令可直接匯編目標(biāo)代碼。而第二條M○V指令中變量VAR2是在DATA2段,它的段基值是在ES中。因此在獲取VAR2存儲單元內(nèi)容時(shí),段寄存器的使用就應(yīng)該用ES替代(超越)。故匯編程序把這條指令匯編成MOV,BL,ES:VAR2(在目標(biāo)代碼中增加一個(gè)字節(jié)的段前綴標(biāo)記代碼26H)。

一條ASSUME語句不一定設(shè)置全部段寄存器、可以只設(shè)置1~3個(gè)段寄存器。在一個(gè)代碼段中,可隨時(shí)用一條ASSUME語句修改或撤除1~4個(gè)段寄存器與已定義段之間的關(guān)系。例如:

ASSUMEES:NOTHING

;撤消對ES的設(shè)置

ASSUMENOTHING

;撤消全部段寄存器的設(shè)置

ASSUME偽指令語句不產(chǎn)生任何目標(biāo)代碼,且僅表示匯編源程序時(shí)按照ASUME語句所設(shè)置的關(guān)系處理。而匯編后的目標(biāo)程序運(yùn)行期間段寄存器內(nèi)容是否與ASSUME語句的設(shè)置-致,匯編程序是不能認(rèn)定的,必須由用戶程序自行通過執(zhí)行程序的辦法對段寄存器內(nèi)容進(jìn)行設(shè)置和加載。三、段寄存器的加載段寄存器用于存放段基值。至于如何將段基值分別加載到相應(yīng)的4個(gè)段寄存器中,具體的實(shí)施辦法略有不同。

1.DS和ES的加載在程序中,引用段名就是以立即數(shù)形式獲取該段的段基值,而立即數(shù)又不能直接傳送給段寄存器,所以要借助于通用寄存器傳送段基值給DS,ES。P190

例子

上述程序中代碼段CODE中第1,3條是以立即數(shù)形式把DATA_DS段和DATA_ES段的段基值分別送給通用寄存器AX,緊接著在第2,4條把AX中的內(nèi)容(段基值)分別傳送給段寄存器DS和ES。這樣就完成了DS和ES段基值的加載。2.SS的加載

SS是堆棧段寄存器,對它加載段寄存器就是設(shè)置堆棧。堆棧的設(shè)置還離不開堆棧指針SP的初始化。對SS的加載有兩種辦法:⑴自動加載在段定義偽指令(SEGMENT)的組合類型中選擇“STACK”參數(shù).就表明這個(gè)段是堆棧段。例如:

STACK1SECMENTpARASTACKDW20HDUP(0)STACKENDS

當(dāng)含有這個(gè)段的目標(biāo)代碼裝入存儲器后,SS就自動設(shè)置STACk1段的段基值,同時(shí)堆棧指針SP也自動初始化為這個(gè)段最大地址+1單元的偏移量。(在上面例子中,初始化后(SP)=40H。

(2)用執(zhí)行程序的辦法加載如在程序運(yùn)行中要調(diào)換另一個(gè)堆棧段,這時(shí)可用類似于DS和ES的加載辦法,對SS和SP進(jìn)行即時(shí)修改。P191例子

假設(shè)STACK2段是待調(diào)換的另一個(gè)堆棧段。先用二條指令把STACK2段的段基值裝入段寄存器SS中,緊接著必須用一條指令初始化堆棧指針SP(在上面的例子中,(SP)=80H),中間不要插入另外的指令。3.CS的加載我們知道,CS和IP提供了當(dāng)前執(zhí)行目標(biāo)代碼的段基值和偏移量。為保證程序的正確執(zhí)行,CS和IP的裝入新值必須一起完成。如采用DS,ES的加載辦法,那么裝入CS和IP新值需要執(zhí)行幾條指令,而執(zhí)行指令又必須依據(jù)CS和IP來尋找指令,且又不能用指令直接傳送數(shù)據(jù)給IP。因此,用執(zhí)行幾條指令的辦法來完成CS和IP的加載是行不通的。對CS和IP的設(shè)置、修改通常有兩個(gè)途徑:(1)用結(jié)束偽指令END加載程序的起始地址。任何一個(gè)源程序最后一個(gè)語句必須是結(jié)束偽指令語句,它的格式是:END地址表達(dá)式

其中,地址表達(dá)式通常是一個(gè)巳定義的標(biāo)號或一個(gè)標(biāo)號加減一個(gè)常數(shù)。地址表達(dá)式是這個(gè)程序執(zhí)行的第一條指令語句的地址。例如:…

CODESEGMENTASSUMECS:CODS,…START:MOVAX,DATA

CODSENDSENDSTART

結(jié)束偽指令END有兩個(gè)作用:①源程序到此結(jié)束,后面的任何語句均被匯編程序略去,②將地址表達(dá)式所確認(rèn)的存儲單元的段基值和偏移量分別自動裝入CS和IP中。上述示例中把標(biāo)號START的段基值和偏移量分別裝入CS和IP中。(2)在程序運(yùn)行期間如執(zhí)行程序轉(zhuǎn)移類指令,實(shí)現(xiàn)從一個(gè)段轉(zhuǎn)移到另一個(gè)段時(shí),它的指令功能就是修改CS和IP。例如段間無條件轉(zhuǎn)移指令JMP、段間調(diào)用指令CALL和段間返回指令RET等。如執(zhí)行的僅是段內(nèi)轉(zhuǎn)移指令(如段內(nèi)無條件轉(zhuǎn)移指令、條件轉(zhuǎn)移指令、循環(huán)控制指令、段內(nèi)調(diào)用指令和段內(nèi)返回指令等),那么指令功能僅修改IP值。5.4.2過程定義語句MASM宏匯編程序用“過程”來構(gòu)造子程序。過程偽指令語句格式如下;過程名PROC[NEAR/FAR]…RET…

過程名ENDP其中,過程名不能省略,且定義過程的開始(PROC)與結(jié)束(ENDP),應(yīng)使用同一過程名。過程名就是子程序名,也是子程序調(diào)用指令(CALL)的目標(biāo)操作數(shù)。過程必須出現(xiàn)在邏輯段內(nèi),過程名也有3個(gè)屬性段、偏移量和類型,類型分為NEAR(近)和FAR(遠(yuǎn))兩種。如果沒有選擇類型屬性,則隱含為NEAR。對過程的調(diào)用也是一種程序轉(zhuǎn)移。具有NEAR屬性的過程,僅供過程所在段的其它程序調(diào)用,即段內(nèi)轉(zhuǎn)移。具有FAR屬性的過程,可供其他段(不是過程所在段)調(diào)用,即段間轉(zhuǎn)移。一個(gè)過程(子程序)的程序,執(zhí)行的最后一條指令一定是返回指令(RET)。返回指令RET有段內(nèi)返回和段間返回的區(qū)別。在NEAR類型過程中的返回指令RET必定是段內(nèi)返回;在FAR類型過程中助返回指令RET就必定是段間返回。5.4.3定位語句和位置計(jì)數(shù)器在匯編源程序時(shí),為了指示下一個(gè)數(shù)據(jù)或指令在對應(yīng)段中的偏移量,匯編程序使用一個(gè)位置計(jì)數(shù)器,用于記載匯編時(shí)的當(dāng)前偏移量。符號$代表位置計(jì)數(shù)器的現(xiàn)行值。定位偽指令ORG就是對位置計(jì)數(shù)器的現(xiàn)行值進(jìn)行設(shè)置與修改。定位偽指令語句格式如下:

ORG

表達(dá)式語句功能是把表達(dá)式的值賦值給位置計(jì)數(shù)器。在這語句下面的目標(biāo)代碼(指令代碼或數(shù)據(jù))以表達(dá)式給定值作起始偏移量。其中表達(dá)式是以65536為模進(jìn)行計(jì)算的無符號整數(shù)。表達(dá)式中可包括位置計(jì)數(shù)器的現(xiàn)行值$。例如:

DATA

SEGMENT

ORG20H

DB1DBI2H,34H

ORG$+30H

STRING

DB`ABCDEF`

COUNTEQU$-STRING

DATAENDS

上面數(shù)據(jù)段中,變量DB1在DATA數(shù)據(jù)段內(nèi)的偏移量為20H(不是0H)。第二個(gè)ORG偽指令語句表示把位置計(jì)數(shù)器的現(xiàn)行值加上30H。由于該語句中$的現(xiàn)行值是22H,所以22H+30H=52H是變量STRING的偏移量。而“ORG$+30H”語句的作用是保留30H個(gè)字節(jié)單元。等值語句中“$-STRING”表示兩個(gè)偏移量之差,其差值正好是以變量STRING為首址的連續(xù)字節(jié)單元數(shù)(本例中正好是STRING存儲區(qū)中的字符個(gè)數(shù))。5.4.4偶地址控制語句偶地址偽指令EVEN也是對位置計(jì)數(shù)器的一個(gè)控制命令,它把位置計(jì)數(shù)器調(diào)整為偶數(shù)。EVEN偽指令的格式如下:

EVEN

對存儲器字單無(16位)進(jìn)行存取時(shí),如是偶地址,那么存取速度較快(如8086CPU就是如此)。所以EVEN偽指令主要是應(yīng)用于定義字?jǐn)?shù)據(jù)前,用以調(diào)整位置計(jì)數(shù)器為偶數(shù)。5.4.5程序標(biāo)題語句

標(biāo)題偽指令TITLE的格式是:

TITLE文本

TITLE偽指令是指定一個(gè)標(biāo)題,以便在列表文件中每一頁的第一行都顯示這個(gè)標(biāo)題。TITLE偽指令的文本可以是用戶任意選用的名字或字符串,但字符個(gè)數(shù)不超過60個(gè)。5.5宏指今語句在程序中,有的程序段在整個(gè)程序中要多次出現(xiàn),這種出現(xiàn)可能是完全不修改的再現(xiàn);有的可能是僅修改部分內(nèi)容,而程序段功能并無大的變化。為了減少源程序中重復(fù)編寫工作,這時(shí)可以用宏指令。能處理宏指令功能的匯編程序叫宏匯編程序。MASM就是宏匯編程序。宏指令的使用過程是:宏定義,宏調(diào)用和宏展開。1.宏定義宏指令必須先進(jìn)行宏定義。MACRO和ENDM是宏定義的開始和結(jié)尾偽指令。宏定義格式有兩種:(1)不帶參數(shù)宏定義:

宏名MACRO

…ENDM(2)帶參數(shù)宏定義:

宏名MACRO

形式參數(shù)1,形式參數(shù)2,……

ENDM

上述兩種宏定義中,宏名是宏定義的符號名,也是后面宏調(diào)用時(shí)引用的符號名,宏名是必選項(xiàng)。宏名在整個(gè)程序中應(yīng)是惟一的。宏體是由若干語句序列組成的。宏定義可以不在邏輯段中。不帶參數(shù)的宏定義,每次宏調(diào)用時(shí),宏體內(nèi)各語句序列不作任何修改。

2.宏調(diào)用在宏指令定義后,在源程序的任意位置上可以使用宏指令語句(即宏凋用)。宏凋用的格式有兩種:(1)無參數(shù)宏調(diào)用:宏名

(2)帶參數(shù)宏調(diào)用;宏名實(shí)參1,實(shí)參2,...例如對前面兩個(gè)宏定義進(jìn)行宏調(diào)用:…

MULTAX10…MULT10AX,BX…

對帶參數(shù)的宏指令語句,宏匯編程序?qū)⒂脤?shí)參替代宏體中形參位置。多個(gè)實(shí)參的排列順序要與形參一致,且每個(gè)實(shí)參應(yīng)滿足對應(yīng)形參的要求。通常實(shí)參的個(gè)數(shù)與形參的個(gè)數(shù)相同。如實(shí)參個(gè)數(shù)多于形參,則多余實(shí)參自動被略去,如實(shí)參個(gè)數(shù)少于形參,那么剩余的形參自動用“空白串”替代。3.宏展開當(dāng)宏匯編程序掃描到宏指令語句(宏凋用)時(shí),就把宏定義中宏體的程序段目標(biāo)代碼插入宏指令語句的位置上,這就是宏展開。若是帶參數(shù)的宏調(diào)用,則同時(shí)用相應(yīng)的實(shí)參替代宏定義的宏體中對應(yīng)形參的位置,并對原有宏體代碼作修改。下面是一個(gè)匯編語言源程序的部分列表文件,它展示了宏定義、宏調(diào)用和宏展開的全過程。在列表文件中,左邊有“+”號(隨MASM版本不同,`+`可能用其它符號表示)的指令是宏匯編程序在宏展開時(shí)自動插入宏定義中宏體的指令序列,這指令序列同時(shí)生成目標(biāo)代碼。而宏指令語句(即宏調(diào)用)本身不生成目標(biāo)代碼,它僅表示宏調(diào)用出現(xiàn)的位置。宏定義中宏體的指令序列本身不產(chǎn)生目標(biāo)代碼。詳見P1955.6順序程序設(shè)計(jì)順序程序是最簡單的,也是最常用的程序結(jié)構(gòu)形式。這種程序結(jié)構(gòu)形式的主要特點(diǎn)是:程序運(yùn)行時(shí),完全按照編寫的指令順序執(zhí)行,且每條指令僅執(zhí)行一次。試編制一源程序,計(jì)算下列公式的值,并將結(jié)果存放在Fl(商)和F2(余數(shù))兩存儲單元中。(P197)

其中X.Y.Z的值分別存放在VARX,VARY,VARZ3個(gè)字存儲單元中,且假設(shè)計(jì)算過程的中間值和最后結(jié)果仍在16位二進(jìn)制數(shù)的范圍內(nèi)。源程序編制如P197-198

上述程序代碼段中從第3條指令(MOVAX,VARX)起,至倒數(shù)第3條指令(MOVF2,DX)止是實(shí)現(xiàn)公式計(jì)算的程序段。程序中最后用除法指令獲得計(jì)算結(jié)果的商和余數(shù),并分別存入F1和F2存儲單元中。在源程序的代碼段中,第1,2條指令是把數(shù)據(jù)段DATA的段基值裝入DS。最后兩條指令是終止用戶程序,并返回操作系統(tǒng)DOS。其中“MOVAH,4CH”是把功能號4CH送入寄存器AH中,然后使用軟中斷指令I(lǐng)NT21H。

在較早的DOS版本中,終止用戶程序,返回操作系統(tǒng)是借用程序段前綴(programsegmentprofix,簡稱PSP)中前兩個(gè)字節(jié)組成的指令“INT20H”來實(shí)現(xiàn)的。用這種辦法時(shí),用戶程序的代碼段(如果用戶程序比較大或由多個(gè)模塊構(gòu)成時(shí),則在主控程序模塊的代碼段)的框架格式應(yīng)是:程序框架格式CODESEGMENTASSUMECS:CODE,DS:DATA,SS:STACK1PROC1PROCFARPUSHDS;準(zhǔn)備返回信息

XORAX,AXPUSHAXMOVAX,DATA

;預(yù)置DSMOVDS,AX…RET

:段間返回…CODEENDS

ENDPROC1上述程序框架中“準(zhǔn)備返回信息”和“段間返回”的作用是什么?每當(dāng)一個(gè)用戶程序的可執(zhí)行文件(.EXE)裝入內(nèi)存后,用戶程序的目標(biāo)代碼一定是加載在程序段前綴PSP的后面。PSP段(100H個(gè)字節(jié))給出了用戶可執(zhí)行文件的若干控制信息。在用戶程序結(jié)束時(shí)如何跳轉(zhuǎn)到PSP段中第1,2個(gè)字節(jié)組成的“INT20H”指令呢?首先把用戶程序設(shè)置成一個(gè)過程,且類型屬性沒置為FAR。當(dāng)用戶程序的可執(zhí)行文件裝入內(nèi)存后,段寄存器DS,ES是指向PSP段的,所以用戶程序第1條指令是“PUSHDS”,即把PSP段的段基值壓入堆棧.緊接著用2條指令把常數(shù)0壓入堆棧。這樣,在執(zhí)行段間返回指令RET時(shí),自動把原先壓入堆棧中的PSP段的段基值和偏移量(即00H)分別送入CS和IP中。因此,執(zhí)行完RFT指令后,便開始執(zhí)行PSP段的INT20H指令,結(jié)束用戶程序,返回DOS操作系統(tǒng)。上面介紹的結(jié)束用戶程序,返回操作系統(tǒng)的兩種方法,編程人員可任意選用。例5—3用查表的方法將一位十六進(jìn)制數(shù)轉(zhuǎn)換成它相應(yīng)的ASCII碼。既然指定用查表的方法,那么首先建立一個(gè)表TABLE。在表中按照十六進(jìn)制數(shù)從小到大的順序存入它們對應(yīng)的ASCII碼值。編制的源程序如P199上述查表程序中指令“MOVAL,[BX]“是使用寄存器間接尋址。如果要使用基址(或變址)尋址(即改為MOVAL,TABLE[BX]),則應(yīng)相應(yīng)修改程序。類似這種查表,可使用換碼指令XLAT,以使程序更加精練。換碼指令格式:XLAT

表首址或XLAT

指令功能:AL←((BX)+(AL))

使用這條指令時(shí),通常把表首址的偏移量送入BX中,把待查表內(nèi)單元的位移量(0~255)送入AL中。這樣上述查表程序可修改如P200

在程序設(shè)計(jì)中常常使用程序流程圖,把解題的方法、步驟用框圖的形式表示出來。如果問題比較復(fù)雜,那么可以逐步細(xì)化.直到每一框圖可以很容易編制程序?yàn)橹?。流程圖不僅便于程序的編制,也便于查找和修改程序邏輯上的錯(cuò)誤。流程圖主要是由P200圖5-3所示幾種框圖符號組成:(a)處理框。用于說明一程序段(或一條指令)所完成的功能。這種通常是一個(gè)入口,一個(gè)出口。(b)判別框。表示進(jìn)行程序的分支的流向判別,框內(nèi)記入判別條件。這種框圖通常是一個(gè)入口,兩個(gè)或兩個(gè)以上的出口。在每個(gè)出口上要注明分支流向條件。(c)起止框。表示一個(gè)程序或一個(gè)程序模塊的開始和結(jié)束。起始框內(nèi)通常用程序名(如過程名)、標(biāo)號或“開始“字符來表示,它僅有-個(gè)出口。終止框內(nèi)通常用”結(jié)束“,“返回”等字符來表示,它僅有一個(gè)入口o(d)連接框。當(dāng)一個(gè)程序比較復(fù)雜,需要分布在幾張紙上或者雖然在一張紙上就能給出一個(gè)程序框圖,但是流程圖中連線較多,且常??v橫交錯(cuò),這時(shí)可用連接框表示兩根流向線的連接關(guān)系。連按框中常用字母或數(shù)字來表示??騼?nèi)有相同字母或數(shù)字就表示它們有連線關(guān)系。它只有一個(gè)入口或出口o(e)流向線。它表示程序的流向,即程序執(zhí)行的順序關(guān)系。如程序的流向是從上向下或從左向右,通??梢圆划嫾^,其余情況需用箭頭指明程序的流向。5.7分支程序設(shè)計(jì)

在實(shí)際應(yīng)用中,常常需要在程序運(yùn)行過程中依據(jù)不同情況在幾個(gè)程序段中選擇其一,這就是分支程序結(jié)構(gòu)。為實(shí)現(xiàn)分支結(jié)構(gòu)的程序設(shè)計(jì),Iintel8086/8088指令系統(tǒng)提供了許多程序流向控制和轉(zhuǎn)移的指令。轉(zhuǎn)移指令是實(shí)現(xiàn)分支程序設(shè)汁的必要條件。為此,首先需要了解各種程序轉(zhuǎn)移指令的功能與使用,然后再學(xué)習(xí)分支結(jié)構(gòu)的程序設(shè)計(jì)。5.7.1轉(zhuǎn)移指令由于執(zhí)行指令的順序是由CS和IP決定的.所以程序流向的控制和轉(zhuǎn)移、主要反映在對CS和IP的修改與設(shè)置。若程序轉(zhuǎn)移僅在同一段內(nèi)進(jìn)行,則只需修改IP;若是在兩個(gè)段之間進(jìn)行,則CS和IP都需要修改。轉(zhuǎn)移指令按功能可分為兩種:無條件轉(zhuǎn)移指令和條件轉(zhuǎn)移指令。這兩種轉(zhuǎn)移指令的執(zhí)行均不影響任何標(biāo)志位。一.無條件轉(zhuǎn)移指令指令格式:JMP

目標(biāo)

JMP指令的執(zhí)行使程序無條件地轉(zhuǎn)移到“目標(biāo)”處。在執(zhí)行JMP指令后程序就從“目標(biāo)”處的指令開始執(zhí)行。目標(biāo)處的指令可能與這條JMP指令同在一個(gè)段內(nèi)(段內(nèi)轉(zhuǎn)移),也可能不在同一段內(nèi)(段間轉(zhuǎn)移)。無淪是段內(nèi)轉(zhuǎn)移還是段間轉(zhuǎn)移,目標(biāo)有兩種地址表達(dá)方式:1.直接尋址方式:在JMP指令的“目標(biāo)”處,直接給出目標(biāo)地址。通常是用目標(biāo)處的標(biāo)號表示。如果是段內(nèi)轉(zhuǎn)移,有如P202圖5-4所示的兩種情況。這兩種轉(zhuǎn)移都是相對轉(zhuǎn)移,即目標(biāo)處指令地址與當(dāng)前JMP指令相對偏移一個(gè)位移量。這位移量是以JMP指令的下一條指令與目標(biāo)處指令之間相距字節(jié)數(shù)來計(jì)算。如果目標(biāo)處指令地址高于JMP指令地址,這種轉(zhuǎn)移叫正向轉(zhuǎn)移;如果目標(biāo)處指令地址低于JMP指令地址,叫負(fù)向轉(zhuǎn)移。轉(zhuǎn)移的相對位移量圖5-4中的RD1是正向轉(zhuǎn)移的相對位移量,RD2是負(fù)向轉(zhuǎn)移的相對位移量。相對位移量是以補(bǔ)碼形式表示的帶符號數(shù)。在執(zhí)行JMP指令時(shí),由于IP已指向它的下一條指令.所以對IP的修改就是把相對位移量加在IP上。即:

IP←(IP)+相對位移量如果相對位移量(RD1和RD2)在-128~+127范圍內(nèi),這種轉(zhuǎn)移叫短轉(zhuǎn)移。在指令書寫時(shí)可以加SHORT給予說明,如JMPSHORTTARGET。對于這種短轉(zhuǎn)移JMP指令,將產(chǎn)生2字節(jié)目標(biāo)代碼,其中1個(gè)字節(jié)存放補(bǔ)碼形式的相對位移量。如果相對位移量超過這范圍,那么指令目標(biāo)代碼就是3字節(jié)長,其中2個(gè)字節(jié)存放補(bǔ)碼形式的相對位移量。對于段間轉(zhuǎn)移,執(zhí)行JMP指令時(shí),就把目標(biāo)處指令地址的段基值和偏移量直接送入CS和IP即可,如圖P2025-5所示。2.間接尋址方式

JMP指令的目標(biāo)地址在一個(gè)通用寄存器/存儲器字單元內(nèi)(段內(nèi)轉(zhuǎn)移)或在存儲器的雙字單元內(nèi)(段間轉(zhuǎn)移)。例如:段內(nèi)轉(zhuǎn)移:JMPCX

;目標(biāo)地址的偏移量在CX中或JMPWORDPTR「BX];目標(biāo)地址的偏移量在一個(gè)字單元中

JMP「BX]段間轉(zhuǎn)移:JMPDWORDPTR「BX];目標(biāo)地址在一個(gè)雙字單元中在執(zhí)行段內(nèi)轉(zhuǎn)移的JMP指令時(shí),就把存放在通用寄存器或字單元中的偏移量送入IP中,CS不變,實(shí)現(xiàn)段內(nèi)的程序轉(zhuǎn)移。在執(zhí)行段間轉(zhuǎn)移的JMP指令時(shí),把存放在雙字單元中前2個(gè)字節(jié)單元的偏移量送入IP,后2個(gè)字節(jié)單元的段基值送CS實(shí)現(xiàn)段間的程序轉(zhuǎn)移。二、條件轉(zhuǎn)移指令

Intel8086/8088指令系統(tǒng)中條件轉(zhuǎn)移指令共有18條。條件轉(zhuǎn)移指令基本格式為:Jxx

目標(biāo)其中字母“J”后面是由1~3個(gè)字母表示的轉(zhuǎn)移條件。若指定條件成立,則轉(zhuǎn)移至目標(biāo)處指令,否則順序執(zhí)行。這18條指令都是以標(biāo)志寄存器中某-個(gè)或幾個(gè)標(biāo)志位作為判斷條件。條件轉(zhuǎn)移指令只能是段內(nèi)轉(zhuǎn)移。同JMP指令段內(nèi)轉(zhuǎn)移的直接尋址方式類似,條件轉(zhuǎn)移指令也是相對轉(zhuǎn)移,相對位移量是當(dāng)前條件轉(zhuǎn)移指令的下一條指令與目標(biāo)處指令之間的相對字節(jié)數(shù)。相對位移量是一個(gè)用補(bǔ)碼形式表示的8位二進(jìn)制的帶符號數(shù),因此轉(zhuǎn)移范圍是-128~+127個(gè)字節(jié)。條件轉(zhuǎn)移指令的目標(biāo)代碼均是2字節(jié)長。在使用條件轉(zhuǎn)移指令前,通常是由一些算術(shù)運(yùn)算、邏輯運(yùn)算或某種比較、測試指令的執(zhí)行結(jié)果設(shè)置有關(guān)標(biāo)志位,然后根據(jù)轉(zhuǎn)移要求,選擇適當(dāng)?shù)模瓧l或幾條條件轉(zhuǎn)移指令。條件轉(zhuǎn)移指令分為三大類。

1.簡單條件轉(zhuǎn)移指令根據(jù)單個(gè)標(biāo)志位的狀態(tài)判斷轉(zhuǎn)移條件。這類指令共有18條,見P203。2.無符號數(shù)條件轉(zhuǎn)移指令假設(shè)在條件轉(zhuǎn)移指令前用比較指令CMP對兩個(gè)無符號數(shù)A,B進(jìn)行比較,執(zhí)行A-B的操作。這類指令共有4條,見P203。3.帶符號數(shù)條件轉(zhuǎn)移指令假設(shè)在條件轉(zhuǎn)移指令前用比較指令CMP對兩個(gè)帶符號數(shù)A,B進(jìn)行比較,執(zhí)行A-B的操作。這類指令共有4條,見P204。5.7.2分支

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(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

提交評論