匯編語言的指令格式,目前有兩種不同的標(biāo)準(zhǔn):Windows下的匯編語言基本上都遵循Intel風(fēng)格的語法,比如:MASM、NASM;而Unix/Linux下的匯編語言基本上都遵循AT&T風(fēng)格的語法; [名稱[:]] 指令碼 [第一操作數(shù)][,第二操作數(shù)] ;注釋 匯編語言的指令碼的操作數(shù)的個數(shù)可以是0、1、2個;當(dāng)操作數(shù)的個數(shù)為2的時候,語句還有兩種不同的格式: Windows下Intel風(fēng)格的匯編語言語句格式為: [名稱[:]] 指令碼 目的操作數(shù)DST,源操作數(shù)SRC ;注釋 Unix/Linux下AT&T風(fēng)格的匯編語言語句格式為: [名稱[:]] 指令碼 源操作數(shù)SRC,目的操作數(shù)DST ;注釋 例如:
CYCLE: ADD AX,02H
;(AX)匯編語言語句格式中的'名稱'并不是所有語句都必需的,但是,如果語句中帶有'名稱',那么,大多數(shù)情況下,'名稱'都表示的是內(nèi)存中某一存儲單元的地址,也就是'名稱'后面各項(xiàng)在內(nèi)存中存放的第一個存儲單元的地址(包括該'名稱'所在段的段地址和段內(nèi)偏移地址);比如上面的指令中,CYCLE就是該語句的名稱,CYCLE表示的就是其后面的機(jī)器指令碼在內(nèi)存中存放的第一個地址;'名稱'與指令碼之間的分隔符可以是冒號':',也可以是空格字符'
';當(dāng)以冒號分割時,該名稱代表的是一個標(biāo)號;當(dāng)以空格分割時,該名稱代表的可能是標(biāo)號,也可能是變量;當(dāng)指令碼有多個操作數(shù)的時候,相鄰兩個操作數(shù)之間要用逗號','分割;指令碼與操作數(shù)之間必須以空格分割;匯編語言語句的注釋必須以分號';'開頭; 匯編語言中的常數(shù)有整數(shù)、字符串;二進(jìn)制、八進(jìn)制、十進(jìn)制、十六進(jìn)制;匯編語言采用不同的后綴區(qū)分: B:二進(jìn)制數(shù); O:八進(jìn)制數(shù); D:十進(jìn)制數(shù); H:十六進(jìn)制數(shù); 當(dāng)一個數(shù)值后面沒有后綴的時候,默認(rèn)為十進(jìn)制數(shù); 字符串常數(shù)是用一對單引號('')括起來的一串字符;算數(shù)運(yùn)算操作符: +、-、*、/、MOD,等;取模運(yùn)算MOD是取兩數(shù)相除的余數(shù); 邏輯運(yùn)算操作符: AND(邏輯與)、OR(邏輯或)、NOT(邏輯非)、XOR(邏輯異或); 注意:邏輯運(yùn)算符同時又可以是邏輯運(yùn)算指令的指令碼,只有當(dāng)它們出現(xiàn)在指令的操作數(shù)部分時,才是操作符;例如: ADD AL,0CH ADD 0FH ;第一個ADD是指令碼,第二個ADD是操作符; 關(guān)系運(yùn)算操作符: EQ(相等)、NE(不等)、LT(小于)、GT(大于)、LE(小于等于)、GE(大于等于); 匯編語言中的表達(dá)式不能單獨(dú)構(gòu)成語句,只能是語句的組成部分; 注意:語句中表達(dá)式的求值不是在語句執(zhí)行時完成的,而是在對源程序進(jìn)行匯編鏈接時完成的.所以,語句中各表達(dá)式的值必須在匯編或鏈接時就是確定的,也就是說,表達(dá)式中各標(biāo)識符的值在匯編或鏈接時就應(yīng)該是確定的; 標(biāo)號是由標(biāo)識符表示的指令的名稱,用于指示對應(yīng)指令的位置(地址); 標(biāo)號具有三個屬性:段地址、偏移地址和類型; 標(biāo)號的段地址和偏移地址屬性是指該標(biāo)號所對應(yīng)的指令所在段的段地址和段內(nèi)偏移地址; 標(biāo)號的類型有兩種:NEAR和FAR;標(biāo)號定義成NEAR類型,表示該標(biāo)號在段內(nèi)使用,而定義成FAR類型則表示該標(biāo)號可以在段間使用; 標(biāo)號的定義:在指令碼前面加上標(biāo)識符和冒號':'; 這條語句里面,START就是我們定義的標(biāo)號,它代表指令PUSH的地址,所以,標(biāo)號可以作為程序轉(zhuǎn)移指令的操作數(shù)(即:要轉(zhuǎn)向的地址);標(biāo)號還可以采用偽指令來定義;例如:用LABEL偽指令和過程定義偽指令來定義; 與高級語言一樣,并不是所有的操作數(shù)都是常數(shù),匯編語言也有自己的變量,變量的值在程序運(yùn)行期間是可以被改變的; A.定義變量:匯編語言中,變量的定義是通過偽指令來完成的;定義變量的偽指令格式如下: 變量名 DB 表達(dá)式 ;定義字節(jié)變量,又稱單字節(jié)變量(1個連續(xù)字節(jié)),DB-->BYTE變量名 DW 表達(dá)式 ;定義字變量,又稱雙字節(jié)變量(2個連續(xù)字節(jié)),DW-->WORD變量名 DD 表達(dá)式 ;定義雙字變量,又稱四字節(jié)變量(4個連續(xù)字節(jié)),DD-->DWORD變量名 DF 表達(dá)式 ;定義六字節(jié)變量,又稱六字節(jié)變量(6個連續(xù)字節(jié)),DF-->FWORD變量名 DQ 表達(dá)式 ;定義長字變量,又稱八字節(jié)變量(8個連續(xù)字節(jié)),DQ-->QWORD變量名 DT 表達(dá)式 ;定義十字節(jié)變量(10個連續(xù)字節(jié)),DT-->TBYTE; 其中,變量名是一個合法的標(biāo)識符,變量名后面不能加冒號':',只能用空格;變量名不是必要的,可有可無;變量的類型由關(guān)鍵字DB、DW、DD、DQ、DT來定義; 變量定義語句中的'表達(dá)式'是用于對變量進(jìn)行初始化的,可有一下幾種情況: (1).一個或多個常數(shù)或表達(dá)式;當(dāng)為多個常數(shù)或表達(dá)式時,期間要用逗號隔開;如DATA1--DATA4; 對于字節(jié)型(DB)變量,每個變量的大小為1個字節(jié),每個變量的值不能超過1個字符,每個字節(jié)內(nèi)存入一個字符的ASCII碼值,整個字符串可以在同一對單引號內(nèi)給出,這相當(dāng)于是定義了一個字符數(shù)組,如DATA5; 對于字類型(DW)變量,每個變量的大小為2個字節(jié),每個變量的值不能超過2個字符,若為2個字符時,同樣遵循高位存入高字節(jié),低位存入低字節(jié)的規(guī)則;若為1個字符,則該字符的ASCII碼值存入到低字節(jié),高字節(jié)為00,如DATA6; 對于雙字類型(DD)變量,每個變量的大小為4個字節(jié),每個變量的值不能超過2個字符,若為2個字符,同樣遵循高位存入高字節(jié),低位存入低字節(jié)的規(guī)則;但是2個字符的值被存入到雙字變量的最低2個字節(jié)中,1個字符的值被存入到雙字變量的最低1個字節(jié)中; 對于長字類型(DQ)變量,每個變量的大小為8個字節(jié),每個變量的值不能超過2個字符,若為2個字符,同樣遵循高位存入高字節(jié),低位存入低字節(jié)的規(guī)則;但是2個字符的值被存入到長字變量的最低2個字節(jié)中,1個字符的值被存入到長字變量的最低1個字節(jié)中; (3).一個問號'?',表示該變量的值不確定,即:該變量所表示的內(nèi)存單元中的內(nèi)容是不確定的,或者說是,當(dāng)表達(dá)式為問號時,變量所對應(yīng)的內(nèi)存區(qū)中并沒有存入新的值,而只是預(yù)留出了相應(yīng)的存儲空間;如DATA7、DATA8 (4).重復(fù)方式;此時的格式為: 重復(fù)次數(shù) DUP(表達(dá)式);重復(fù)方式指出表達(dá)式的值可以重復(fù)地存儲到變量對應(yīng)的內(nèi)存區(qū)中,重復(fù)的次數(shù)由偽指令給出,相當(dāng)于定義數(shù)組;如DATA9、DATA10 DATA2 DW 0204H,1000H ;2字節(jié)變量DATA3 DB (-1*3),(15/3) ;1字節(jié)變量DATA4 DD 123456H ;4字節(jié)變量DATA5 DB '0123' ;字符串變量,相當(dāng)于一個字符數(shù)組DATA6 DW 'AB','C','D' ;字符串變量,相當(dāng)于一個字符串?dāng)?shù)組;DATA7 DB ? ;1字節(jié)變量,未初始化DATA8 DD ? ;4字節(jié)變量,未初始化DATA9 DB 5 DUP(0) ;1字節(jié)變量,用5個0初始化,相當(dāng)于是一個具有5個DB型元素的數(shù)組DATA10 DW 3 DUP(?) ;2字節(jié)變量,未初始化,相當(dāng)于是一個具有3個DW型元素的數(shù)組變量定義語句中偽指令的功能是在變量名所對應(yīng)的地址開始的內(nèi)存區(qū)依次存入表達(dá)式中的各項(xiàng)值,表達(dá)式中的每項(xiàng)值所占用內(nèi)存字節(jié)數(shù)與變量的類型對應(yīng);總結(jié):一個變量的變量名實(shí)際上就代表了該變量所對應(yīng)的內(nèi)存區(qū)在內(nèi)存段中的有效地址(偏移地址);高地址是指地址值相對較大,低地址是指地址值相對較小,高地址與低地址是相對而言的; B.偏移地址(OFFSET):變量所在段內(nèi)的偏移地址;C.類型(TYPE):變量的類型定義了每個變量所占用的內(nèi)存字節(jié)數(shù),對于DB、DW、DD、DQ、DT類型定義的變量所占用的內(nèi)存字節(jié)數(shù)分別是1、2、4、8、10;通常又將DB、DW、DD類型所定義的變量分別成為BYTE類型、WORD類型、DWORD類型變量;標(biāo)識符種類 字節(jié)變量 字變量 雙字變量 近標(biāo)號NEAR 遠(yuǎn)標(biāo)號FARD.長度(LENGTH):變量定義時,一個變量名所定義的變量個數(shù);在含有DUP操作符的變量定義中,變量名所定義的變量個數(shù)為定義格式中的重復(fù)次數(shù);在其它各種變量定義中,每個變量名所定義的變量個數(shù)均為1個;E.大小(SIZE):變量定義語句中,分配給同一個變量名的所有變量的總的字節(jié)數(shù),其值為該變量的類型與長度的成績;其中,段地址、偏移地址和類型屬性是變量的主屬性,而長度和大小屬性是變量的輔助屬性;SEG SEG 變量名或標(biāo)號 取出變量名或標(biāo)號所在段的段地址OFFSET OFFSET 變量名或標(biāo)號 取出變量名或標(biāo)號所在段內(nèi)的偏移地址TYPE TYPE 變量名或標(biāo)號 取出變量名或標(biāo)號的類型(變量所占用的字節(jié)數(shù))LENGTH LENGTH 變量名 取出變量的長度這些操作符不能單獨(dú)構(gòu)成語句,只能作為表達(dá)式的組成部分,并且表達(dá)式的求值也是在匯編過程中完成的;6.強(qiáng)制類型轉(zhuǎn)換操作符PTR 格式:數(shù)據(jù)類型 PTR 地址表達(dá)式格式中的'數(shù)據(jù)類型'可以是BYTE、WORD、DWORD、NEAR、FAR;前三種類型是變量的類型,后兩種類型是標(biāo)號的類型;格式中的表達(dá)式可以是變量、標(biāo)號、其它地址表達(dá)式;PTR操作符的功能是用來重新定義已定義的變量或標(biāo)號的類型,其作用域只在當(dāng)前語句中; 例如:這條指令中,是把DATA1的類型轉(zhuǎn)換為BYTE類型,然后把AL中的內(nèi)容存放到DATA1的最低一個字節(jié)中;作用域只在這條MOV語句中,過了這條語句,DATA1仍然是DW類型,即:DATA1原來的類型并沒有被修改;符合數(shù)據(jù)類型,除了用DUP定義的重復(fù)數(shù)據(jù)類型之外,與C/C++語言一樣,匯編語言中 也有結(jié)構(gòu)體類型、聯(lián)合類型、記錄類型;結(jié)構(gòu)類型名 STRUC [對齊類型Alignment][,NONUNIQUE]說明:結(jié)構(gòu)體中的字段名可有可無;若有字段名,則字段名必須唯一,每個字段可獨(dú)立存取;若沒有字段名,則通過偏移量來存取;對齊方式Alignment:定義每個字段的字節(jié)對齊邊界,對齊值有1、2、4、8、16字節(jié)對齊,值必須是2的冪次方;對齊類似于C/C++中結(jié)構(gòu)體字段的對齊; NONUNIQUE:要求結(jié)構(gòu)體中的字段必須用全名才能訪問; 結(jié)構(gòu)體中的字段可以有字段名,也可以沒有字段名;有字段名的字段可直接使用該字段名來訪問,沒有字段名的字段可用使用該字段在結(jié)構(gòu)體中的偏移量來訪問;NAME DB 10 DUP(?) ;有名字段,偏移量為4字段值列表中的各個字段之間用逗號','分割,字段值的排列順序及類型應(yīng)該與該結(jié)構(gòu)定義時說明的各個字段相一致;如果結(jié)構(gòu)變量中某個字段的值使用定義結(jié)構(gòu)時說明的缺省值,那么可用逗號來表示;如果所有字段都使用定義結(jié)構(gòu)體時說明的各個字段的缺省值,則可省去字段值列表,只需保留一對尖括號''即可; Per1 PERSON ;所有字段都是用默認(rèn)值Per3 PERSON ;第二個字段使用默認(rèn)值;這種引用方式與高級語言中的引用方式完全一致;另外,還可以使用偏移量來訪問某個字段; 方式2:使用字段的在結(jié)構(gòu)體中的偏移量來引用 LEA SI,Per3 ;取變量Per3對應(yīng)內(nèi)存塊的有效地址 MOV AX,[SI+4] ;寄存器相對尋址,4是字段NAME的偏移量 [聯(lián)合體類型名] UNION [對齊方式Alignment][,NONUNIQUE]說明:聯(lián)合體類型中的各個字段相互覆蓋,即:同樣的存儲單元被多個不同類型的字段所對應(yīng),并且每個字段在聯(lián)合體類型中的偏移量都是0;聯(lián)合體類型所占用的字節(jié)數(shù)是其所有字段所占字節(jié)數(shù)的最大值,即:聯(lián)合體所占用的字節(jié)數(shù)是這個聯(lián)合體的所有字段中占用字節(jié)數(shù)最多的那個字段占用的字節(jié)數(shù); 對齊方式Alignment:可用1、2、4、8、16個字節(jié)來指定聯(lián)合體中各個字段字節(jié)的對齊邊界,其缺省的對齊邊界是1字節(jié);還可用使用偽指令A(yù)LIGN或EVEN來重新定界,也可使用命令行選項(xiàng)/Zp來定界; NONUNIQUE:要求聯(lián)合體類型中的字段必須使用全名才能訪問; 聯(lián)合體類型的變量只能使用第一個字段的數(shù)據(jù)類型來進(jìn)行初始化;例如:DATE1 DATE ;定義一個聯(lián)合體類型變量DATE1,并使用第一個字段的數(shù)據(jù)類型進(jìn)行初始化DATE2 DATE ;初始化錯誤,只能使用第一個字段的數(shù)據(jù)類型進(jìn)行初始化;MOV DATE1.YEAR,2012 ;給聯(lián)合體類型變量字段賦值MOV AL,DATE1.MONTH ;AL=07MOV BX,DATE1.YEAR ;BX=2012MOV DATE1.MONTH,08 ;月份置為8月匯編語言中的記錄類型與高級語言中的記錄類型不同,在匯編語言中,記錄類型是為按照二進(jìn)制位存取數(shù)據(jù)提供方便的;記錄類型的說明要用到另一個關(guān)鍵字RECORD,格式如下:其中,'字段'代表: 字段名:寬度[=初始值表達(dá)式]說明:記錄名代表該記錄類型;記錄類型可以由多個字段組成,相鄰兩個字段之間用逗號隔開;記錄類型中字段的屬性包括字段名、寬度和初始值;記錄類型中,字段的'寬度'屬性表示該字段所占用的二進(jìn)制位數(shù),它必須是一個常數(shù),并且所有字段的寬度之和不能大于16(即:有字段的寬度之和大于8,則系統(tǒng)會自動為該記錄類型分配2字節(jié)的空間,否則只分配1個字節(jié)的空間;記錄類型的最后一個字段排在所分配空間的最低位,然后對記錄中的字段依次'從右向左'分配二進(jìn)制位,左邊沒有分完的二進(jìn)制位自動補(bǔ)0;初值表達(dá)式給出的是該字段的缺省值,如果初值超過了該字段所表示的范圍,那么,在匯編時將產(chǎn)生錯誤提示信息,如果某字段沒有初值表達(dá)式,則其初值為0;COLOR RECORD BLINK:1,BACK:3=0,INTENSE:1=1,FORE:3該COLOR類型的二進(jìn)制位分布如下圖所示:該類型的各個字段寬度為:1、3、1、3,所以,該記錄占用8個二進(jìn)制位,系統(tǒng)為它分配1個字節(jié);FLOAT RECORD DSIGN:1,DATA:8,ESIGN:1,EXP:4該FLOAT類型的二進(jìn)制位分布如下圖所示:該類型的總寬度是14個二進(jìn)制位,所以,系統(tǒng)為它分配2個字節(jié)的空間;說明:變量名就是該記錄類型的變量名,它可缺省,則不能使用符號名來訪問該內(nèi)存單元;字段值列表是用于給各個字段賦初值,相鄰兩個字段值之間用逗號','隔開,其字段值的排列順序及大小應(yīng)該按照記錄類型定義時說明的各個字段的順序和大小來排列;如果記錄類型變量的某個字段使用默認(rèn)值,那么,可用逗號來表示,如果所有字段都是用默認(rèn)值,則可省去字段值列表,但必須保留一對尖括號'';操作符WIDTH和MASK是專用于記錄類型的操作符,利用它們可用得到記錄類型的不同屬性;WIDTH:用于返回記錄或其字段的二進(jìn)制位數(shù),即:記錄類型或記錄類型字段的寬度;書寫格式如下: 例如:記錄類型COLOR,那么,WIDTH COLOR的值為8,WIDTH BACK的值為3,WIDTH BLINK的值為1;MASK:它返回一個8位或16位的二進(jìn)制數(shù),在該二進(jìn)制數(shù)中,被指定記錄或字段使用的對應(yīng)位的值為1,否則,其值為0;書寫格式如下:例如:記錄類型FLOAT,那么,MASK EXP的值為000FH,MASK DATA的值為1FE0H,MASK DSIGN的值為2000H; 記錄字段:記錄字段名是一個特殊的操作符,它本身也是一個操作數(shù),其返回值是該字段移到該字段所在記錄的最低位所需要的位數(shù),即:該字段最低位在記錄中的位置;MOV CL,EXP 相當(dāng)于 MOV CL,0MOV CL,DATA 相當(dāng)于 MOV CL,5已知某一數(shù)據(jù)類型,程序員可以定義這個數(shù)據(jù)類型的別名或指針類型.表達(dá)這種定義的偽指令是TYPEDEF,其定義形式如下:新數(shù)據(jù)類型名 TYPEDEF [位距][PTR] 已知數(shù)據(jù)類型CHAR TYPEDEF BYTE ;給BYTE類型定義另外一個別名CHAR,C++中就是: typedef BYTE CHARPCHAR TYPEDEF PTR CHAR ;定義一個字符指針數(shù)據(jù)類型PCHAR,C++中就是:typedef PTR CHAR PCHAR,即:typedef char* PCHARCH1 CHAR 'ABCDEF' ;定義一個字符串常量PCH1 PCHAR CH1 ;定義一個指向字符串常量CH1的變量SEG(段地址)、OFFSET(偏移量)、TYPE(數(shù)據(jù)類型)、LENGTH(變量長度)、SIZE(變量容量)WIDTH(記錄/記錄字段的寬度)、MASK(記錄/記錄字段的屏蔽位),等等;其中,HIGH和LOW分別用于選取表達(dá)式計算結(jié)果的高8位和低8位,使用格式如下:優(yōu)先級: 高 LENGTH、SIZE、WIDTH、MASK、()、[]、.(用于結(jié)構(gòu)字段)、(用于記錄類型)↓ PTR、SEG、OFFSET、TYPE、THIS、:(用于段超越前綴)地址表達(dá)式是計算存儲器單元地址的表達(dá)式,它可由標(biāo)號、變量名和由方括號'[]'括起來的基址或變址寄存器組成;其計算結(jié)果表示一個存儲器單元的地址,而不是該存儲器單元中的值;注意:匯編語言中,對地址數(shù)值的運(yùn)算都是以字節(jié)為單位的,而不是以數(shù)據(jù)類型的大小為單位的;例如:則,地址表達(dá)式W1+1處的內(nèi)存單元中的數(shù)據(jù)是7812H,而不是5678H;W1+1表示W(wǎng)1為起始地址,其下一個字節(jié)單元的地址,W1+2表示從地址W1出開始,其后2個字節(jié)單元地址;在程序中,經(jīng)常會用到一些常數(shù)或數(shù)值表達(dá)式,并把它們直接寫在指令值,當(dāng)時當(dāng)需要修改的時候,就要對它們逐一進(jìn)行修改,這無疑就增加了維護(hù)程序的工作量,而且每個常量或表達(dá)式所代表的含義也容易忘記;于是,匯編語言提供了為常量或表達(dá)式定義一個符號名的方法;一旦定義了符號名,在指令中就可以直接使用它們了;這個功能就類似于C語言中使用宏定義指令#define定義常量的功能相似,也與C++中使用const關(guān)鍵字定義常量的功能相似;注意:等價語句不會給符號名分配存儲空間,符號名不能與其它符號名重名,即:符號名必須唯一;符號名也不能被重新定義;程序中凡是出現(xiàn)'表達(dá)式'的地方,都使用'符號名'來替換;把一個常量或表達(dá)式定義成一個具有一定含義的符號名之后,在程序中就可以用該符號名來代表該常量或表達(dá)式;例如:NUMBER EQU 100 ;給緩沖區(qū)的長度取一個符號名CR EQU 13 ;給'回車'符的ASCII碼定義一個符號名LN EQU 10 ;給'換行'符的ASCII碼定義一個符號名GREETING EQU 'How are you!'MOVE EQU MOV ;給指令碼MOV取另外一個符號名MOVECOUNTER EQU CX ;給寄存器CX取一個叫做'計數(shù)器'的符號名匯編語言提供了使用等號'='來定義符號常數(shù)的方法,即:可用符號名代表一個常數(shù);一般格式如下:數(shù)值表達(dá)式在匯編時應(yīng)該可以計算出值,它不能含有向前引用的符號名稱;用等號語句定義的符號名可以被重新定義;可把等號語句看成是高級語言中的一個賦值語句,可以被多次賦值,這一點(diǎn)是與EQU不同的地方;例如: ABC = 10 + 200*5 ;ABC的值為1010ABC1 = 5*ABC + 21 ;ABC1的值為5071COUNT = 2*COUNT + 1 ;COUNT的值為3注意:偽指令'='和偽指令'EQU'定義符號名時,凡是在程序中出現(xiàn)符號名的地方,都是用右邊的常量或表達(dá)式來替代;該語句定義一個指定的符號名,該符號名的段地址和偏移地址與下面緊跟存儲單元的相應(yīng)屬性相同,但是,該符號名的類型是新指定的; 常用的數(shù)據(jù)類型有:BYTE、WORD、DWORD、結(jié)構(gòu)類型、記錄類型、NEAR、FAR; 其中,前五中類型是變量的類型,后面兩種類型是標(biāo)號的類型;如果格式中的'數(shù)據(jù)類型'是前面五種類型之一的話,'符號名'就是變量名;如果格式中的'數(shù)據(jù)類型'是后面的兩種類型之一的話,'符號名'就是標(biāo)號名;變量名和標(biāo)號名都具有段地址和偏移地址的屬性; 這個LABEL定義語句中,WBUFFER與BUFFER具有完全相同的段地址和偏移地址,但是它們的數(shù)據(jù)類型不同,目的就是為了使用兩種不同類型的操作來訪問同一塊內(nèi)存區(qū);匯編語言的指令格式,目前有兩種不同的標(biāo)準(zhǔn):Windows下的匯編語言基本上都遵循Intel風(fēng)格的語法,比如:MASM、NASM;而Unix/Linux下的匯編語言基本上都遵循AT&T風(fēng)格的語法; [名稱[:]] 指令碼 [第一操作數(shù)][,第二操作數(shù)] ;注釋 匯編語言的指令碼的操作數(shù)的個數(shù)可以是0、1、2個;當(dāng)操作數(shù)的個數(shù)為2的時候,語句還有兩種不同的格式: Windows下Intel風(fēng)格的匯編語言語句格式為: [名稱[:]] 指令碼 目的操作數(shù)DST,源操作數(shù)SRC ;注釋 Unix/Linux下AT&T風(fēng)格的匯編語言語句格式為: [名稱[:]] 指令碼 源操作數(shù)SRC,目的操作數(shù)DST ;注釋 例如:
CYCLE: ADD AX,02H
;(AX)匯編語言語句格式中的'名稱'并不是所有語句都必需的,但是,如果語句中帶有'名稱',那么,大多數(shù)情況下,'名稱'都表示的是內(nèi)存中某一存儲單元的地址,也就是'名稱'后面各項(xiàng)在內(nèi)存中存放的第一個存儲單元的地址(包括該'名稱'所在段的段地址和段內(nèi)偏移地址);比如上面的指令中,CYCLE就是該語句的名稱,CYCLE表示的就是其后面的機(jī)器指令碼在內(nèi)存中存放的第一個地址;'名稱'與指令碼之間的分隔符可以是冒號':',也可以是空格字符'
';當(dāng)以冒號分割時,該名稱代表的是一個標(biāo)號;當(dāng)以空格分割時,該名稱代表的可能是標(biāo)號,也可能是變量;當(dāng)指令碼有多個操作數(shù)的時候,相鄰兩個操作數(shù)之間要用逗號','分割;指令碼與操作數(shù)之間必須以空格分割;匯編語言語句的注釋必須以分號';'開頭; 匯編語言中的常數(shù)有整數(shù)、字符串;二進(jìn)制、八進(jìn)制、十進(jìn)制、十六進(jìn)制;匯編語言采用不同的后綴區(qū)分: B:二進(jìn)制數(shù); O:八進(jìn)制數(shù); D:十進(jìn)制數(shù); H:十六進(jìn)制數(shù);當(dāng)一個數(shù)值后面沒有后綴的時候,默認(rèn)為十進(jìn)制數(shù);字符串常數(shù)是用一對單引號('')括起來的一串字符; 算數(shù)運(yùn)算操作符: +、-、*、/、MOD,等;取模運(yùn)算MOD是取兩數(shù)相除的余數(shù); 邏輯運(yùn)算操作符: AND(邏輯與)、OR(邏輯或)、NOT(邏輯非)、XOR(邏輯異或); 注意:邏輯運(yùn)算符同時又可以是邏輯運(yùn)算指令的指令碼,只有當(dāng)它們出現(xiàn)在指令的操作數(shù)部分時,才是操作符;例如: ADD AL,0CH ADD 0FH ;第一個ADD是指令碼,第二個ADD是操作符;關(guān)系運(yùn)算操作符: EQ(相等)、NE(不等)、LT(小于)、GT(大于)、LE(小于等于)、GE(大于等于); 匯編語言中的表達(dá)式不能單獨(dú)構(gòu)成語句,只能是語句的組成部分; 注意:語句中表達(dá)式的求值不是在語句執(zhí)行時完成的,而是在對源程序進(jìn)行匯編鏈接時完成的.所以,語句中各表達(dá)式的值必須在匯編或鏈接時就是確定的,也就是說,表達(dá)式中各標(biāo)識符的值在匯編或鏈接時就應(yīng)該是確定的; 標(biāo)號是由標(biāo)識符表示的指令的名稱,用于指示對應(yīng)指令的位置(地址); 標(biāo)號具有三個屬性:段地址、偏移地址和類型; 標(biāo)號的段地址和偏移地址屬性是指該標(biāo)號所對應(yīng)的指令所在段的段地址和段內(nèi)偏移地址; 標(biāo)號的類型有兩種:NEAR和FAR;標(biāo)號定義成NEAR類型,表示該標(biāo)號在段內(nèi)使用,而定義成FAR類型則表示該標(biāo)號可以在段間使用; 標(biāo)號的定義:在指令碼前面加上標(biāo)識符和冒號':'; 這條語句里面,START就是我們定義的標(biāo)號,它代表指令PUSH的地址,所以,標(biāo)號可以作為程序轉(zhuǎn)移指令的操作數(shù)(即:要轉(zhuǎn)向的地址);標(biāo)號還可以采用偽指令來定義;例如:用LABEL偽指令和過程定義偽指令來定義; 與高級語言一樣,并不是所有的操作數(shù)都是常數(shù),匯編語言也有自己的變量,變量的值在程序運(yùn)行期間是可以被改變的; A.定義變量:匯編語言中,變量的定義是通過偽指令來完成的;定義變量的偽指令格式如下: 變量名 DB 表達(dá)式 ;定義字節(jié)變量,又稱單字節(jié)變量(1個連續(xù)字節(jié)),DB-->BYTE變量名 DW 表達(dá)式 ;定義字變量,又稱雙字節(jié)變量(2個連續(xù)字節(jié)),DW-->WORD變量名 DD 表達(dá)式 ;定義雙字變量,又稱四字節(jié)變量(4個連續(xù)字節(jié)),DD-->DWORD變量名 DF 表達(dá)式 ;定義六字節(jié)變量,又稱六字節(jié)變量(6個連續(xù)字節(jié)),DF-->FWORD變量名 DQ 表達(dá)式 ;定義長字變量,又稱八字節(jié)變量(8個連續(xù)字節(jié)),DQ-->QWORD變量名 DT 表達(dá)式 ;定義十字節(jié)變量(10個連續(xù)字節(jié)),DT-->TBYTE;其中,變量名是一個合法的標(biāo)識符,變量名后面不能加冒號':',只能用空格;變量名不是必要的,可有可無;變量的類型由關(guān)鍵字DB、DW、DD、DQ、DT來定義;變量定義語句中的'表達(dá)式'是用于對變量進(jìn)行初始化的,可有一下幾種情況:(1).一個或多個常數(shù)或表達(dá)式;當(dāng)為多個常數(shù)或表達(dá)式時,期間要用逗號隔開;如DATA1--DATA4; 對于字節(jié)型(DB)變量,每個變量的大小為1個字節(jié),每個變量的值不能超過1個字符,每個字節(jié)內(nèi)存入一個字符的ASCII碼值,整個字符串可以在同一對單引號內(nèi)給出,這相當(dāng)于是定義了一個字符數(shù)組,如DATA5; 對于字類型(DW)變量,每個變量的大小為2個字節(jié),每個變量的值不能超過2個字符,若為2個字符時,同樣遵循高位存入高字節(jié),低位存入低字節(jié)的規(guī)則;若為1個字符,則該字符的ASCII碼值存入到低字節(jié),高字節(jié)為00,如DATA6; 對于雙字類型(DD)變量,每個變量的大小為4個字節(jié),每個變量的值不能超過2個字符,若為2個字符,同樣遵循高位存入高字節(jié),低位存入低字節(jié)的規(guī)則;但是2個字符的值被存入到雙字變量的最低2個字節(jié)中,1個字符的值被存入到雙字變量的最低1個字節(jié)中; 對于長字類型(DQ)變量,每個變量的大小為8個字節(jié),每個變量的值不能超過2個字符,若為2個字符,同樣遵循高位存入高字節(jié),低位存入低字節(jié)的規(guī)則;但是2個字符的值被存入到長字變量的最低2個字節(jié)中,1個字符的值被存入到長字變量的最低1個字節(jié)中; (3).一個問號'?',表示該變量的值不確定,即:該變量所表示的內(nèi)存單元中的內(nèi)容是不確定的,或者說是,當(dāng)表達(dá)式為問號時,變量所對應(yīng)的內(nèi)存區(qū)中并沒有存入新的值,而只是預(yù)留出了相應(yīng)的存儲空間;如DATA7、DATA8 (4).重復(fù)方式;此時的格式為: 重復(fù)次數(shù) DUP(表達(dá)式);重復(fù)方式指出表達(dá)式的值可以重復(fù)地存儲到變量對應(yīng)的內(nèi)存區(qū)中,重復(fù)的次數(shù)由偽指令給出,相當(dāng)于定義數(shù)組;如DATA9、DATA10 DATA2 DW 0204H,1000H ;2字節(jié)變量DATA3 DB (-1*3),(15/3) ;1字節(jié)變量DATA4 DD 123456H ;4字節(jié)變量DATA5 DB '0123' ;字符串變量,相當(dāng)于一個字符數(shù)組DATA6 DW 'AB','C','D' ;字符串變量,相當(dāng)于一個字符串?dāng)?shù)組;DATA7 DB ? ;1字節(jié)變量,未初始化DATA8 DD ? ;4字節(jié)變量,未初始化DATA9 DB 5 DUP(0) ;1字節(jié)變量,用5個0初始化,相當(dāng)于是一個具有5個DB型元素的數(shù)組DATA10 DW 3 DUP(?) ;2字節(jié)變量,未初始化,相當(dāng)于是一個具有3個DW型元素的數(shù)組變量定義語句中偽指令的功能是在變量名所對應(yīng)的地址開始的內(nèi)存區(qū)依次存入表達(dá)式中的各項(xiàng)值,表達(dá)式中的每項(xiàng)值所占用內(nèi)存字節(jié)數(shù)與變量的類型對應(yīng); 總結(jié):一個變量的變量名實(shí)際上就代表了該變量所對應(yīng)的內(nèi)存區(qū)在內(nèi)存段中的有效地址(偏移地址);高地址是指地址值相對較大,低地址是指地址值相對較小,高地址與低地址是相對而言的; B.偏移地址(OFFSET):變量所在段內(nèi)的偏移地址; C.類型(TYPE):變量的類型定義了每個變量所占用的內(nèi)存字節(jié)數(shù),對于DB、DW、DD、DQ、DT類型定義的變量所占用的內(nèi)存字節(jié)數(shù)分別是1、2、4、8、10;通常又將DB、DW、DD類型所定義的變量分別成為BYTE類型、WORD類型、DWORD類型變量; 標(biāo)識符種類 字節(jié)變量 字變量 雙字變量 近標(biāo)號NEAR 遠(yuǎn)標(biāo)號FAR D.長度(LENGTH):變量定義時,一個變量名所定義的變量個數(shù);在含有DUP操作符的變量定義中,變量名所定義的變量個數(shù)為定義格式中的重復(fù)次數(shù);在其它各種變量定義中,每個變量名所定義的變量個數(shù)均為1個; E.大小(SIZE):變量定義語句中,分配給同一個變量名的所有變量的總的字節(jié)數(shù),其值為該變量的類型與長度的成績; 其中,段地址、偏移地址和類型屬性是變量的主屬性,而長度和大小屬性是變量的輔助屬性; SEG SEG 變量名或標(biāo)號 取出變量名或標(biāo)號所在段的段地址 OFFSET OFFSET 變量名或標(biāo)號 取出變量名或標(biāo)號所在段內(nèi)的偏移地址 TYPE TYPE 變量名或標(biāo)號 取出變量名或標(biāo)號的類型(變量所占用的字節(jié)數(shù)) LENGTH LENGTH 變量名 取出變量的長度 這些操作符不能單獨(dú)構(gòu)成語句,只能作為表達(dá)式的組成部分,并且表達(dá)式的求值也是在匯編過程中完成的; 6.強(qiáng)制類型轉(zhuǎn)換操作符PTR 格式:數(shù)據(jù)類型 PTR 地址表達(dá)式 格式中的'數(shù)據(jù)類型'可以是BYTE、WORD、DWORD、NEAR、FAR;前三種類型是變量的類型,后兩種類型是標(biāo)號的類型;格式中的表達(dá)式可以是變量、標(biāo)號、其它地址表達(dá)式; PTR操作符的功能是用來重新定義已定義的變量或標(biāo)號的類型,其作用域只在當(dāng)前語句中; 例如: 這條指令中,是把DATA1的類型轉(zhuǎn)換為BYTE類型,然后把AL中的內(nèi)容存放到DATA1的最低一個字節(jié)中;作用域只在這條MOV語句中,過了這條語句,DATA1仍然是DW類型,即:DATA1原來的類型并沒有被修改; 符合數(shù)據(jù)類型,除了用DUP定義的重復(fù)數(shù)據(jù)類型之外,與C/C++語言一樣,匯編語言中也有結(jié)構(gòu)體類型、聯(lián)合類型、記錄類型; 結(jié)構(gòu)類型名 STRUC [對齊類型Alignment][,NONUNIQUE]說明:結(jié)構(gòu)體中的字段名可有可無;若有字段名,則字段名必須唯一,每個字段可獨(dú)立存取;若沒有字段名,則通過偏移量來存取; 對齊方式Alignment:定義每個字段的字節(jié)對齊邊界,對齊值有1、2、4、8、16字節(jié)對齊,值必須是2的冪次方;對齊類似于C/C++中結(jié)構(gòu)體字段的對齊; NONUNIQUE:要求結(jié)構(gòu)體中的字段必須用全名才能訪問; 結(jié)構(gòu)體中的字段可以有字段名,也可以沒有字段名;有字段名的字段可直接使用該字段名來訪問,沒有字段名的字段可用使用該字段在結(jié)構(gòu)體中的偏移量來訪問; NAME DB 10 DUP(?) ;有名字段,偏移量為4字段值列表中的各個字段之間用逗號','分割,字段值的排列順序及類型應(yīng)該與該結(jié)構(gòu)定義時說明的各個字段相一致;如果結(jié)構(gòu)變量中某個字段的值使用定義結(jié)構(gòu)時說明的缺省值,那么可用逗號來表示;如果所有字段都使用定義結(jié)構(gòu)體時說明的各個字段的缺省值,則可省去字段值列表,只需保留一對尖括號''即可; Per1 PERSON ;所有字段都是用默認(rèn)值Per3 PERSON ;第二個字段使用默認(rèn)值; 這種引用方式與高級語言中的引用方式完全一致;另外,還可以使用偏移量來訪問某個字段; 方式2:使用字段的在結(jié)構(gòu)體中的偏移量來引用 LEA SI,Per3 ;取變量Per3對應(yīng)內(nèi)存塊的有效地址 MOV AX,[SI+4] ;寄存器相對尋址,4是字段NAME的偏移量 [聯(lián)合體類型名] UNION [對齊方式Alignment][,NONUNIQUE]說明:聯(lián)合體類型中的各個字段相互覆蓋,即:同樣的存儲單元被多個不同類型的字段所對應(yīng),并且每個字段在聯(lián)合體類型中的偏移量都是0;聯(lián)合體類型所占用的字節(jié)數(shù)是其所有字段所占字節(jié)數(shù)的最大值,即:聯(lián)合體所占用的字節(jié)數(shù)是這個聯(lián)合體的所有字段中占用字節(jié)數(shù)最多的那個字段占用的字節(jié)數(shù); 對齊方式Alignment:可用1、2、4、8、16個字節(jié)來指定聯(lián)合體中各個字段字節(jié)的對齊邊界,其缺省的對齊邊界是1字節(jié);還可用使用偽指令A(yù)LIGN或EVEN來重新定界,也可使用命令行選項(xiàng)/Zp來定界; NONUNIQUE:要求聯(lián)合體類型中的字段必須使用全名才能訪問; 聯(lián)合體類型的變量只能使用第一個字段的數(shù)據(jù)類型來進(jìn)行初始化;例如:DATE1 DATE ;定義一個聯(lián)合體類型變量DATE1,并使用第一個字段的數(shù)據(jù)類型進(jìn)行初始化 DATE2 DATE ;初始化錯誤,只能使用第一個字段的數(shù)據(jù)類型進(jìn)行初始化; MOV DATE1.YEAR,2012 ;給聯(lián)合體類型變量字段賦值MOV AL,DATE1.MONTH ;AL=07MOV BX,DATE1.YEAR ;BX=2012MOV DATE1.MONTH,08 ;月份置為8月匯編語言中的記錄類型與高級語言中的記錄類型不同,在匯編語言中,記錄類型是為按照二進(jìn)制位存取數(shù)據(jù)提供方便的;記錄類型的說明要用到另一個關(guān)鍵字RECORD,格式如下: 其中,'字段'代表: 字段名:寬度[=初始值表達(dá)式] 說明:記錄名代表該記錄類型;記錄類型可以由多個字段組成,相鄰兩個字段之間用逗號隔開;記錄類型中字段的屬性包括字段名、寬度和初始值;記錄類型中,字段的'寬度'屬性表示該字段所占用的二進(jìn)制位數(shù),它必須是一個常數(shù),并且所有字段的寬度之和不能大于16(即:有字段的寬度之和大于8,則系統(tǒng)會自動為該記錄類型分配2字節(jié)的空間,否則只分配1個字節(jié)的空間;記錄類型的最后一個字段排在所分配空間的最低位,然后對記錄中的字段依次'從右向左'分配二進(jìn)制位,左邊沒有分完的二進(jìn)制位自動補(bǔ)0;初值表達(dá)式給出的是該字段的缺省值,如果初值超過了該字段所表示的范圍,那么,在匯編時將產(chǎn)生錯誤提示信息,如果某字段沒有初值表達(dá)式,則其初值為0; COLOR RECORD BLINK:1,BACK:3=0,INTENSE:1=1,FORE:3 該COLOR類型的二進(jìn)制位分布如下圖所示: 該類型的各個字段寬度為:1、3、1、3,所以,該記錄占用8個二進(jìn)制位,系統(tǒng)為它分配1個字節(jié); FLOAT RECORD DSIGN:1,DATA:8,ESIGN:1,EXP:4 該FLOAT類型的二進(jìn)制位分布如下圖所示: 該類型的總寬度是14個二進(jìn)制位,所以,系統(tǒng)為它分配2個字節(jié)的空間; 說明:變量名就是該記錄類型的變量名,它可缺省,則不能使用符號名來訪問該內(nèi)存單元;字段值列表是用于給各個字段賦初值,相鄰兩個字段值之間用逗號','隔開,其字段值的排列順序及大小應(yīng)該按照記錄類型定義時說明的各個字段的順序和大小來排列;如果記錄類型變量的某個字段使用默認(rèn)值,那么,可用逗號來表示,如果所有字段都是用默認(rèn)值,則可省去字段值列表,但必須保留一對尖括號''; 操作符WIDTH和MASK是專用于記錄類型的操作符,利用它們可用得到記錄類型的不同屬性; WIDTH:用于返回記錄或其字段的二進(jìn)制位數(shù),即:記錄類型或記錄類型字段的寬度;書寫格式如下: 例如:記錄類型COLOR,那么,WIDTH COLOR的值為8,WIDTH BACK的值為3,WIDTH BLINK的值為1; MASK:它返回一個8位或16位的二進(jìn)制數(shù),在該二進(jìn)制數(shù)中,被指定記錄或字段使用的對應(yīng)位的值為1,否則,其值為0;書寫格式如下: 例如:記錄類型FLOAT,那么,MASK EXP的值為000FH,MASK DATA的值為1FE0H,MASK DSIGN的值為2000H; 記錄字段:記錄字段名是一個特殊的操作符,它本身也是一個操作數(shù),其返回值是該字段移到該字段所在記錄的最低位所需要的位數(shù),即:該字段最低位在記錄中的位置;MOV CL,EXP 相當(dāng)于 MOV CL,0MOV CL,DATA 相當(dāng)于 MOV CL,5 已知某一數(shù)據(jù)類型,程序員可以定義這個數(shù)據(jù)類型的別名或指針類型.表達(dá)這種定義的偽指令是TYPEDEF,其定義形式如下: 新數(shù)據(jù)類型名 TYPEDEF [位距][PTR] 已知數(shù)據(jù)類型 CHAR TYPEDEF BYTE ;給BYTE類型定義另外一個別名CHAR,C++中就是: typedef BYTE CHAR PCHAR TYPEDEF PTR CHAR ;定義一個字符指針數(shù)據(jù)類型PCHAR,C++中就是:typedef PTR CHAR PCHAR,即:typedef char* PCHAR CH1 CHAR 'ABCDEF' ;定義一個字符串常量 PCH1 PCHAR CH1 ;定義一個指向字符串常量CH1的變量 SEG(段地址)、OFFSET(偏移量)、TYPE(數(shù)據(jù)類型)、LENGTH(變量長度)、SIZE(變量容量) WIDTH(記錄/記錄字段的寬度)、MASK(記錄/記錄字段的屏蔽位),等等; 其中,HIGH和LOW分別用于選取表達(dá)式計算結(jié)果的高8位和低8位,使用格式如下:優(yōu)先級: 高 LENGTH、SIZE、WIDTH、MASK、()、[]、.(用于結(jié)構(gòu)字段)、(用于記錄類型) ↓ PTR、SEG、OFFSET、TYPE、THIS、:(用于段超越前綴)地址表達(dá)式是計算存儲器單元地址的表達(dá)式,它可由標(biāo)號、變量名和由方括號'[]'括起來的基址或變址寄存器組成;其計算結(jié)果表示一個存儲器單元的地址,而不是該存儲器單元中的值; 注意:匯編語言中,對地址數(shù)值的運(yùn)算都是以字節(jié)為單位的,而不是以數(shù)據(jù)類型的大小為單位的;例如: 則,地址表達(dá)式W1+1處的內(nèi)存單元中的數(shù)據(jù)是7812H,而不是5678H;W1+1表示W(wǎng)1為起始地址,其下一個字節(jié)單元的地址,W1+2表示從地址W1出開始,其后2個字節(jié)單元地址; 在程序中,經(jīng)常會用到一些常數(shù)或數(shù)值表達(dá)式,并把它們直接寫在指令值,當(dāng)時當(dāng)需要修改的時候,就要對它們逐一進(jìn)行修改,這無疑就增加了維護(hù)程序的工作量,而且每個常量或表達(dá)式所代表的含義也容易忘記;于是,匯編語言提供了為常量或表達(dá)式定義一個符號名的方法;一旦定義了符號名,在指令中就可以直接使用它們了;這個功能就類似于C語言中使用宏定義指令#define定義常量的功能相似,也與C++中使用const關(guān)鍵字定義常量的功能相似; 注意:等價語句不會給符號名分配存儲空間,符號名不能與其它符號名重名,即:符號名必須唯一;符號名也不能被重新定義;程序中凡是出現(xiàn)'表達(dá)式'的地方,都使用'符號名'來替換; 把一個常量或表達(dá)式定義成一個具有一定含義的符號名之后,在程序中就可以用該符號名來代表該常量或表達(dá)式;例如: NUMBER EQU 100 ;給緩沖區(qū)的長度取一個符號名CR EQU 13 ;給'回車'符的ASCII碼定義一個符號名LN EQU 10 ;給'換行'符的ASCII碼定義一個符號名GREETING EQU 'How are you!'MOVE EQU MOV ;給指令碼MOV取另外一個符號名MOVECOUNTER EQU CX ;給寄存器CX取一個叫做'計數(shù)器'的符號名匯編語言提供了使用等號'='來定義符號常數(shù)的方法,即:可用符號名代表一個常數(shù);一般格式如下:數(shù)值表達(dá)式在匯編時應(yīng)該可以計算出值,它不能含有向前引用的符號名稱;用等號語句定義的符號名可以被重新定義;可把等號語句看成是高級語言中的一個賦值語句,可以被多次賦值,這一點(diǎn)是與EQU不同的地方;例如: ABC = 10 + 200*5 ;ABC的值為1010ABC1 = 5*ABC + 21 ;ABC1的值為5071COUNT = 2*COUNT + 1 ;COUNT的值為3注意:偽指令'='和偽指令'EQU'定義符號名時,凡是在程序中出現(xiàn)符號名的地方,都是用右邊的常量或表達(dá)式來替代;該語句定義一個指定的符號名,該符號名的段地址和偏移地址與下面緊跟存儲單元的相應(yīng)屬性相同,但是,該符號名的類型是新指定的; 常用的數(shù)據(jù)類型有:BYTE、WORD、DWORD、結(jié)構(gòu)類型、記錄類型、NEAR、FAR; 其中,前五中類型是變量的類型,后面兩種類型是標(biāo)號的類型;如果格式中的'數(shù)據(jù)類型'是前面五種類型之一的話,'符號名'就是變量名;如果格式中的'數(shù)據(jù)類型'是后面的兩種類型之一的話,'符號名'就是標(biāo)號名;變量名和標(biāo)號名都具有段地址和偏移地址的屬性; 這個LABEL定義語句中,WBUFFER與BUFFER具有完全相同的段地址和偏移地址,但是它們的數(shù)據(jù)類型不同,目的就是為了使用兩種不同類型的操作來訪問同一塊內(nèi)存區(qū);
|