1. 程式人生 > >組合語言——標號與變數詳解

組合語言——標號與變數詳解

當程式中要跳轉到另一位置時,需要有一個標識來指示新的位置,這就是標號,通過在目標地址的前面放上一個標號,可以在指令中使用標號來代替直接使用地址。 使用變數是任何程式語言都要遇到的工作。變數是計算機記憶體中已命名的儲存位置,在大部分的語言中都有很多種類的變數,如整數型、浮點型和字串等,不同的變數有不同的用途和尺寸,比如說雖然長整數和單精度浮點數都是32位長,但它們的用途不同。 顧名思義,變數的值在程式執行中是需要改變的,所以它必須定義在可寫的段內,如 .data和 .data?,或者在堆疊內。按照定義的位置不同,MASM中的變數也分為全域性變數和區域性變數兩種。 詳細地~~~~~ 標號:標號(LABEL)是為一組機器指令所起名字.標號可有可無,只有當需要用符號地址來訪問該語句時,才給此語句賦予標號.標號是程式目標標誌,總是和某地址相聯絡,供轉移或迴圈指令控制轉移使用.

  1 標號屬性

  因標號表示是指令地址,所以它有三個屬性,即段屬性、偏移屬性和型別屬性.段屬性即段地址,標號段必須在CS中.偏移屬性是表示該標號到段首地址距離,單位是位元組,是16位無符號整數.型別屬性是距離屬性,指標號和轉移指令距離,該標號在本段內引用,距離在-128~ 127之間時稱短標號,距離屬性為SHORT,當標號在本段,距離在-32768~ 32767之間時稱近標號,距離屬性為NEAR,當引用標號指令和標號不在同一段時稱遠標號,距離屬性為FAR.

計算機組合語言的一個突出優點就是利用符號(Symbol)來代替目標碼,也即大量的二進位制程式碼用符號來表示,使組合語言源程式容易理解,便於記憶。

  在巨集組合語言中所有變數名、標號名、記錄名、指令助記符和暫存器名等統稱符號.這些符號可通過彙編控制語句的偽操作命令重新命名,也可以通過指令給它定義其它名字及新的型別屬性,因而給程式設計帶來很大的靈活性.符號是程式設計師在程式中用來代表某個儲存單元、資料、表示式和名字等所定義的識別符號,可分為暫存器、標號、變數、數字、名字五類. 彙編語句形式: START: ADD AX,BUFFER DATA SEGMENT   BUFFER DB 01H, 02H DATA  ENDS       JMP START其中START,BUFFER,DATA均為符號,它們分別表示標號,變數名,段名,它們具有完全不同的特定含意. 

  標號 標號(LABEL)是為一組機器指令所起的名字.標號可有可無,只有當需要用符號地址來訪問該語句時,才給此語句賦予標號.標號是程式的目標標誌,總是和某地址相聯絡,供轉移或迴圈指令控制轉移使用. 2 1 標號的屬性   因標號表示的是指令地址,所以它有三個屬性,即段屬性、偏移屬性和型別屬性.段屬性即段地址,標號的段必須在CS中.偏移屬性是表示該標號到段首地址的距離,單位是位元組,是16位無符號整數.型別屬性是距離屬性,指標號和轉移指令的距離,該標號在本段內引用,距離在-128~+127之間時稱短標號,距離屬性為SHORT,當標號在本段,距離在-32768~+32767之間時稱近標號,距離屬性為NEAT,當引用標號的指令和標號不在同一段時稱遠標號,距離屬性為FAR. 2 2 標號的定義   標號的定義有三種方法: 2 2 1 隱含說明標號距離屬性為SHORT和NEAR的標號可以使用隱含說明,即在程式碼段中定義,識別符號後加冒號,放在一條彙編指令的操作符前面.例: NEXT: MOV  AX,BX       ----------      LOOP NEXT    - - - - - - - - -      ? NEXT1: CMP  AX,BX       JA  NEXT1  其中NEXT和NEXT1都是標號名. 2 2 2 用LABEL定義標號 對於屬性為NEAR和FAR的標號均可以用這種定義.格式是: 標號名 LABEL   NEAR/FAR 例如:NEXT LABEL NEAR/FAR             - - - - - - - - -   ?       LOOP   NEXT 2 2 3 用EQU定義標號  對於屬性為NEAR和FAR的標號也可用EQU定義.格式是: 標號名 EQU THIS NEAT/FAR 例如: NEXT EQU THIS NEAR       - - - - - - - - -       ?        LOOP  NEXT 2 3 標號的使用 2 3 1 無條件轉移指令中標號作為轉移地址 格式: JMP   標號 其中標號可以是短標號,近標號或遠標號 . 2 3 2 迴圈指令中,標號作為轉移地址 格式:LOOP   標號 其中標號只能是短標號 2 3 3 條件轉移中標號作為轉移地址 格式: 條件轉移指令   標號 其中標號只能用短標號 2 3 4 屬性分離符 2 .3. 4. 1 取段地址算符SEG 例如:MOV AX,SEG NEXT SEG NEXT 就是取標號NEXT所在段的段地址.  2 3 4 2 取偏移量算符OFFSET 例如:MOV BX, OFFSET NEX 其中OFFSET NEXT就是取標號NEXT的有效地址,該語句等效於:LEA BX, NEXT 2 3 4 3 取型別算符TYPE 例如: MOV AX, TYPE NEXT 若NEXT為近標號,則TYPE NEXT值為FFFFH(-1),若NEXT為遠標號TYPE NEXT值為FFFEH(-2).其中-1和-2無真正的物理意義,僅以數值表示標號型別而已. 

變數   變數(Variable)代表存放在某些儲存單元的資料,這些資料在程式執行期間可以隨時被修改.變數是通過變數名在程式中引用,變數名實際上是儲存區中一個數據區的名字,以變數名資料的方式供程式設計師使用,作為指令或偽.指令的運算元,大大方便了程式設計者.

由於變數是在邏輯段中定義.這就決定了變數和標號一樣具有段屬性、偏移屬性和型別屬性,前兩個和標號的屬性相同,而型別屬性是指出資料區的資料項的存取單位是位元組(BYTE),字(WORD)或數字(DWORD)等.可見變數和標號的主要區別在於變數指的是資料,而標號則對應的是指令。

.3 1 變數的定義 變數通常也有三種定義法 .3 1 1 用偽指令DB,DW,DD等來定義 格式:[變數名] 定義資料偽指令〈表示式〉 其中變數名可有可無,若沒有名字則該變數為無名變數.表示式可以是常數、保留符號"?"、ASCII碼字串(只能用DB定義)、地址表示式(不能用DB定義)、預置資料表格和用DUP定義的重複值.變數名可在任一邏輯段中定義,其後邊不緊跟冒號而是加一空格。 .例如:A DB 100;A為一個位元組,值為100. B DB 100,2 3;B值為100,B+1的值為6. C DB 'ABC';C的值為41H,C+1的值為42H,C+2的值為43H.D DB ?; D是一個位元組,預留一個位元組,可以置入任何內容. E DB 23 DUP(0);定義23個0,每一個0佔一個位元組. F DB 3 DUP(1,2 DUP(0));定義9個數,順序為:1,0,0,1,0,0,1,0,0. G DW 'AB','CD';G的值為4142H,G+2的值為4344H. H DW 2 3;H為一個字,存放順序為06,00H I DW ? 預留一個字,佔兩個位元組單元, 3 1 2 用偽指令LABEL定義變數 格式: 變數名 LABEL BYTE/WORD/DWORD 例如: BUF LABEL BYTE DB 21 它等價於 BUF DB 21 3 1 3 用偽指令EQU定義變數 格式:變數名 EQU THIS BYTE/WORD/DWORD

THIS是定義任意型別算符,它同LABEL一樣用於建立變數或標號型別屬性,而其段屬性為語句所在段的段地址,偏移屬性為所在位置的下一個能分配到的可用偏移地址.例如: STACK SEGMENT DW 100 DUP(? TOP EQU THIS WORD(或TOP LABEL WORD) STACK END 變數TOP被定義為字型別,它的偏移量應為STACK段定義100個字後的下一個字的偏移量,它恰就是堆疊指標SP的初值,因此經常用這種方法為SP賦初值. 3 1 4 雙重定義變數名利用隱含方式和顯示方式的雙重方式,可以對同一位置定義為雙重變數. 格式 〈變數名〉 EQU THIS〈型別〉 〈變數名〉 DB/DW/DD… 例如: AB EQU THIS BYTE (或AB LABEL BYTE) AW DW 50 DUP(0)AW定義為字變數,在AW前使用了THIS BYTE,定義了一個位元組型別變數,訪問同一個位置,用AB按位元組訪問,用AW則按字訪問. 3 2 變數的訪問 3 2 1 變數名作為儲存單元的直接地址 變數名用直接定址時,變數的型別必須與指令的要求相符合. 例如:AB已定義位元組變數,AW定義為字變數,用變數名作直接定址形式如下: MOV AH,AB MOV AX,AW 3 2 2 用合成運算子PTR臨時改變變數型別 接上例用 MOV CX,WORD PTR AB MOV CL,BYTE PTR AW 則可臨時把AB變為字型別,AW變為位元組型別,但段和偏移屬性不變. 3 2 3 變數名作為相對定址中的偏移量 例如: MOV AX,AB〔SI〕 MOV AX,AW[BX][SI] 在這裡AB,AW分別表示它們的偏移量而不是它們所表示的資料,常用於陣列或表格操作中,AB[SI]就表示AB陣列中第SI個元素.

3 2 4 屬性分離符 其中SEG和OFFSET用法和標號相同,分別表示取變數所在段的段地址和變數的偏移地址.而TYPE運算子,將回送該變數型別所表示的位元組數. 例如:設AB為位元組變數,AW為字變數,則: MOV AH,TYPE AB即MOV AH,1 MOV AX,TYPE AW即MOV AX,2 3 2 5 取變數資料項個數運算子LENGTH對於變數定義時使用DUP的情況,彙編程式將回送DUP前的重複次數,即分配給該變數的單元數,若表示式有多個DUP,則取第一個DUP項,其它情況則回送1. 例如:ARRAY DW 50 DUP(0)則 MOV CX,LENGTH ARRAY即MOV CX,50 ARRAY1,DW1,2,3 則 MOV CX,LENGTH ARRAY1 即MOV CX,1 可見LENGTH表示陣列元素個數,而不管其型別. 3 2 6 取變數資料項長度算符SIZE SIZE算符,彙編程式將回送分配給該變數的位元組數,即 SIZE=LENGTH TYPE 例如: ARRAY DW 50 DUP(0) 則 SIZE ARRAY=50 2=100 要注意:對字串變數求其長度,使用SIZE不能達到目的. 例如: ST DB 'ABCDEFG' 則 SIZE ST值為1而不是7,欲求字串長可用COUNT EQU $-ST,則COUNT值為7,其中$為定義ST一串字元後下一個可用的偏移地址. 3 2 7 變數名僅對應資料區第一個資料項 例如: WORD DW 20 DUP(?) MOV AX,WORD;第一個元素送AX, MOV AX,WORD+38;第20個元素送AX. 

其它符號 除標號和變數外,符號還可表示常量、段名、過程名、暫存器名和指令助記符等. (1)符號常數常數也常以符號形式出現,使之更具有通用性且便於修改.例: COUNT EQU 100 則COUNT就表示常數100. (2)符號表示指令助記符.例: MOV EQU MOV則MOVE就表示指令MOV (3)符號表示暫存器,例:COUNT EQU CX則COUNT就代表暫存器CX. (4)符號作為段名,例: DATA SEGMENT - - - -- - - - - - - - - - - DATA ENDS DATA 是段名,引用DATA表示段地址. (5)符號作為過程名,例:SUBR PROC NEAR/FAR? - - - -- - - - - - - - - - -  SUB ENDP SUB為過程名,它同樣具有段、偏移量和距離型別三個屬性 .(6)符號作為巨集指令名 巨集定義格式巨集指令名 MACRO [形式引數] - - - -- - - - - - - - - - - ?      ENDM 巨集呼叫格式: 巨集指令名 [實引數] 每當引用巨集指令名則彙編程式對巨集呼叫作巨集展開,就是用巨集定義體取代源程式中的巨集指令並用實引數取代巨集定義中的形式引數