一、數據表示
- 數制 16進制H 2進制B
- 編碼
- N位無符號整數范圍0~pow(2,N)-1
- 補碼:最高位為符號位,0正1負。負數補碼:全取反再加一(算上符號位在內全取反)
- 字符編碼——BCD 8421
- 壓縮的BCD:一個字節表達兩位BCD
- 非壓縮的BCD:二進制八位僅用低四位表達一個BCD
- 字符編碼——ASCII
- 標准ASC碼用7位編碼,有128個。
- 不可顯示的控制符:前三十二個和最后一個
- 可顯示和打印的字符:從20H開始的95個編碼。
- A~Z: 41H~5AH
- a~z:61H~7AH
- 大寫字母和小寫字母相差20H
- 0~9:30H~39H
- 空格:20H
- 回車:0DH
- 換行:0AH
- 字符編碼——Unicode 16位
二、常量表達
- 常數
- 十六進制常數若以字母開頭,則要添加前導0.
- 字符和字符串
- 用單引號或雙引號括起來的單個字符或多個字符,如果字符串中有單引號本身可以用雙引號,反之亦然;或者直接用ASC碼表示:單引號27H,雙引號22H
- 符號常量
- 符號定義偽指令:EQU和=
- 格式:
- 符號名 equ 數值表達式
- 符號名 equ <字符串>
- 符號名 = 數值表達式
- 字符串只能用EQU
- 使用等價偽指令EQU給符號定義一個數值或者定義一個字符串,這個字符串可以是一條處理器指令:CALLDOS EQU <INT 21H>
- EQU用於數值等價時不能重復定義符號名,等號可以
-
COUNT EQU COUNT+64H ;× COUNT = COUNT+64H ;√
-
- 數值表達式
- 真值255和-1的機器代碼都是FFH
- 128和-128都是80H
三、變量應用
- 變量
- 變量是程序運行中隨之發生變化的結果,保存在可讀可寫的主存空間。
- 實質是主存單元的數據,因而可以改變。
- 變量表達主存數據,即存儲器操作數。
- 變量定義
- 變量名 變量定義偽指令 初值表
- 變量名是用戶標識符,表示首元素的邏輯地址
- 變量定義的偽指令有DB DW DD DF DQ DT
- ?表示初值不確定,DUP為復制操作符 格式:重復次數 DUP(重復參數)
- 字節量數據
- DB 8位
- 無符號整數0~255
- 補碼表示的有符號整數:-128~+127
- 一個字符(ASC碼值)
- 壓縮的BCD碼:0~99
- 非壓縮的BCD碼:0~9
- 字量數據
- DW 16位
- 16位數據含高低兩個字節,占兩個連續的字節存儲單元
- Intel采用小端方式存儲 低對低高對高
-
WVAR6 DW 3139H,3832H BVAR6 DB 39H,31H,32H,38H DB '$' MOV DX , MOFFSET WAR6 MOV AH,09H INT 21H
- 顯示結果:91289128
- 存儲:
存儲單元 存儲器地址 38H 0035(H) 32H 0034 31H 0033 39H 0032(L) 存儲單元 存儲器地址 38H 0039(H) 32H 0038 31H 0037 39H 0036(L)
-
- 雙字量數據 略
- 變量定位
- 變量定義的存儲空間:按照書寫的先后順序一個接着一個分配
- ORG 參數:控制存放的偏移地址
- 例:
ORG 100H;從偏移地址100H處安排
- 例:
- N字節數據起始於能被N整除的地址
- ALIGN N控制對齊N字節邊界 EVEN語句指示對齊模2地址
- 例:
align 2;對齊2字節地址邊界
-
org100H bvar1 db100 ;0100 64 align 2 wvar2 dw 100 ;0102 0064 even dvar3 dd ? ;0104 00000000
;1.起始地址本應該為0,使用org控制起始於100
;2.100下一個地址為101 使用align 2控制地址能整除2 故分配在102 - 順序執行的指令之間不能使用align和even
- 例:
- 變量屬性
- 地址屬性:首個變量所在存儲單元的邏輯地址(含有段基地址和偏移地址)
- 類型屬性:變量定義的數據單位
- 地址操作符
-
-
操作符 作用 [] 將擴起的表達式作為存儲器地址指針 $ 返回當前偏移地址 OFFSET 變量名 返回變量名所在段的偏移地址 SEG 變量名 返回段地址(高十六位)
-
-
bvar db 12h,34h ;0000 12 34 org $+10 array dw 1,2,3,4,5,6,7,8,9,10 ;000C 0001 0002 0003 0004 0005 0006 0007 0008 0009 000A wvar dw 5678h,9abch ;0020 5678 9ABC arr_size = $-array ;0024 = 0022-000C = 0018 arr_len = arr_size/2 ;=000C mov al,bvar mov ah,bvar+1 mov bx,wvar[2] mov cx,arr_len mov dx,$ mov si,offset wvar mov di,[si] mov bp,wvar
- 類型操作符
-
操作符 作用 類型名 PTR 變量名 將變量名按照指定的類型使用 TYPE 變量名 返回一個字量的數值,表明變量名的類型 LENGTHOF 變量名 返回整個變量的數據項數(即元素數) SIZEOF 變量名 返回整個變量占用的字節數
-
四、數據尋址方式
指令的兩個部分:操作碼+操作數
操作碼用助記符表示,如mov; 操作數為指令執行的參與者,需要通過地址指示。
數據尋址方式:通過地址查找數據(操作數)
- 立即數尋址
- 操作數緊跟操作碼,是機器代碼的一部分。
- 操作數從指令代碼立即得到,即立即數。用常量的形式直接表達。
- 立即數尋址方式只用於源操作數,常用來給寄存器和存儲單元賦值。
- 立即數沒有類型,它的類型取決於另一個操作數的類型。
- 立即數尋址實例
mov al,12h ;十六進制常數 mov ah,'d' ;字符(ascii) labl: mov bx,-1 ;十進制負數 mov cx,const ;符號常量;const = 64 mov dx,const*4/type wvar ;表達式 mov si,offset bvar ;操作符(byte sizeof lengthof也屬於立即數尋址) mov di,labl ;標號也有地址屬性 也可以用offset mov bvar,01001100b ;二進制數 mov wvar+2,12h ;十六進制常數
- 寄存器尋址
- 使用寄存器名表示它的內容
- 絕大多數采用通用寄存器尋址(AX,BX,CX,DX,DI,SI,BP,SP)
- 部分指令支持專用寄存器,例如段寄存器
- 要注意兩個操作數的類型需要匹配(位數相同)
- 存儲器尋址
-
- 存儲器的地址使用邏輯地址(段基地址+偏移地址)
- 段寄存器有默認的使用規則,在尋址存儲器操作數時,段寄存器不用顯式說明。
-
訪問存儲器方式 默認的段寄存器 可超越的段寄存器 偏移地址 讀取指令 CS IP 堆棧操作 SS SP 一般的數據訪問(下列除外) DS CS,ES,SS EA(有效地址) BP為基地址的數據訪問 SS CS,ES,SS EA(有效地址) 串指令的源操作數 DS CS,ES,SS SI 串指令的目的操作數 ES DI - 偏移地址=有效地址
- 默認規定:
- DS數據段: [bx] [si] [di] [常數]
- SS堆棧段: [bp]
- 顯示說明:使用段超越指令前綴 例: ds:[bp]
- 主存操作數常通過變量形式引用,一般不需要使用段超越前綴指令
- 偏移地址的組成:16位有效地址=基址寄存器+變址寄存器+位移量
- 基址寄存器BX,BP
- 變址寄存器SI,DI
- 位移量 8或16位有符號值
- 直接尋址
-
mov ax,count ;也可以表示為:mov ax,[count] ;假如操作系統為變量COUNT分配的有效地址是2000H ;則反匯編的指令形式為mov ax,ds:[2000H] ;再假設DS保存段地址為1492H ;則14920H+2000H=16920H ;將地址為16920H的內容傳送給AX寄存器,高字節送給AH寄存器,低字節送給AL寄存器
- mov指令不支持兩個操作數都是存儲器操作數
-
- 寄存器間接尋址
- 有效地址存放在寄存器中(寄存器內容=偏移地址=有效地址)
- 用中括號擴起寄存器
- 可以使用BX、BP、SI和DI寄存器作為間接尋址寄存器
- 寄存器間接尋址沒有說明存儲單元類型
- 例子:
mov al,[bx] mov cx,[si] mov [di],dl mov word ptr [di],1394H ;最后一句的說明: ;寄存器間接尋址沒有說明指向的存儲單元是何種類型,如果另一個操作數也沒有類型,例如立即數,則需要使用類型操作符PTR顯式說明
- 設計寄存器間接尋址的主要目的之一是方便對數組的元素或字符串的字符進行操作。
- 值得一說的點:
mov di,si ;正確,支持兩個操作數都是寄存器操作數 mov [di],[si] ;錯誤,加了[]后為存儲器尋址 相當於存儲單元
- 寄存器相對尋址
- 只有BX、BP、SI和DI可以用作寄存器相對尋址的寄存器
- 使用BX、SI、DI默認訪問數據段數據,使用BP默認訪問堆棧段數據;但是都可以使用段超越前綴指令改變訪問的邏輯段
- 例:
mov si,[bx+4] ;也可以表示成:[4][bx]或4[bx] ;位移量:4 mov di,[bp-08h] ;也可以表達為[-08h][bp]但不能是:-08h[bp] ;位移量:-08H mov ax,count[si] ;也可以表達為[si+count]或[count][si] ;位移量:count ;eg212.asm 復制字符串 .model small .stack .data srcmsg db 'Try your best, why not.$' dstmsg db sizeof srcmsg dup(?) .code .startup mov cx,lengthof srcmsg ;CX=字符串字符個數 mov bx,0 ;EBX指向首個字符 again: mov al,srcmsg[bx] ;取源串一個字符送AL mov dstmsg[bx],al ;將AL傳送給目的串 add bx,1 ;加1,指向下一個字符 loop again ;字符個數CX減1,不為0,則轉到AGAIN標號處執行 mov dx,offset dstmsg ;顯示目的字符串內容 mov ah,9 int 21h .exit end
- 基址變址尋址
- 基址寄存器:BX BP
- 變址寄存器:SI DI
- 使用BP默認訪問堆棧段 其余默認訪問數據段 可以使用段超越
- 例:
mov al,[bx+si] ;源操作數在數據段,也可以表示為:[bx][si] mov ax,[bp+di] ;源操作數在堆棧段,也可以表示為:[bp][di] mov ax,ds:[bp+si] ;源操作數在數據段,也可以表示為:ds:[bp][di]
- 相對基址變址尋址
- 基址寄存器:BX BP
- 變址寄存器:SI DI
- 使用BP默認訪問堆棧段 其余默認訪問數據段 可以使用段超越
- 例:
mov cx,[bx+si+4] ;源操作數也可以表示為:4[bx+si] mov ax,80h[bx+di] ;源操作數也可以表示為:80h[bx][di] mov dx,count[bp][di] ;源操作數也可以表示為:[bp+du+count]
- 允許每個部分都使用中括號名單時基址寄存器要寫在變址寄存器之前
- 變量和變量名也可以不卸載中括號內,但是這種情況下中括號前和數字開頭不能使用正號或者負號。
- 數據尋址的組合
- 立即數尋址imm
- 通用寄存器尋址reg
- 存儲器操作數尋址mem
-
五、課后習題
2.1 (2)字符“F”和數值46H作為mov指令的源操作數有區別嗎?
沒區別。
(3)為什么可以把指令“MOV AX,(34+67H)*3”中的數值表達成是常量?
匯編程序在匯編過程中對數值表達式計算,得到一個確定的數值,故稱數值表達式為常量。
(4)匯編語言為什么規定十六進制數若以A~F開頭,需要在前面加個0?
與標識符區分,因為標識符要求為字母或特殊字符開頭。
(7)為什么將查找操作數的方法稱為數據"尋址"方式?
指令的操作數要通過存儲器地址或IO地址才能找到數據本身,故稱數據尋址方式
(8)為什么變量VAR在指令”MOV AX,VAR“中表達直接尋址?
變量名代表的是邏輯地址的值,VAR表達了變量在主存中的存儲單元。
2.2 判斷題
(1)對一個正整數,他的補碼與無符號數的編碼一樣。
對。
(2)常用的BCD碼為8421碼,其中的8表示D3位的權重。
對。
(3)排序一般按照ASCII碼大小,從小到大升序排列時,小字母排在大寫字母之前。
錯。a:61H A:41H
(4)用“DB”和“DW”定義變量,如果初值相同,則占用的存儲空間也一樣多。
錯。DB占用1字節,DW占用2自結
(7)某個字變量存放於存儲器地址0403H~0404H中,對齊了地址邊界。
錯。字變量為兩字節數據,應該對齊於偶數地址。
(8)立即數尋址只會存在於源操作數中。
對。
(9)存儲器尋址方式的操作數當然在主存了。
對。
(10)指令“MOV AX,VAR+2”與“MOV AX,VAR[2]”功能相同。
對
2.3 填空題
(1)計算機中有一個”01100001“編碼,如果把它認為是無符號數,它是十進制數 97 ;如果認為他是BCD碼,則表示真值 61 ;如果它是某個ASCII碼,則代表字符 a 。
(2)C語言用”\n“表示讓光標回到下一行首位,在匯編語言中需要輸出兩個控制字符:一個是回車,其ASCII碼是 ODH(13) ,它將光標移動到當前所在行的首位;另一個是換行,其ASCII碼是 OAH(10) ,它將光標移到下一行。
(3)定義字節變量的偽指令助記符是 DB ,獲取變量名所具有的偏移地址的操作符是 OFFSET 。
(4)數據段有語句”H8843 DD 99008843H",代碼段指令“MOV CX, WORD PTR H8843"執行后,CX= 8843H 。
(6)數據段有語句“AVC DB 1,2,3”,代碼段指令“MOV CL,ABC+2”執行后,CL= 3 。
(7)除外設數據外的存儲方式有三種,分別稱為 立即數尋址 、 寄存器尋址 和 存儲器尋址 。
(8)指令“MOV AX,OFFSET MSG”的目的操作數和源操作數分別采用 寄存器尋址 和 立即數尋址 。
(9)已知SI=04000H,BX=20H,指令“MOV AX,[BX+SI+8]"中訪問的有效地址是 4028H 。
(10)用BX做基地址的指針,默認采用 DS 段寄存器指向的數據段;如果采用BP作為基地址指針,默認使用 SS 段寄存器指向堆棧段。
2.6 將下列壓縮BCD碼轉換為十進制數:
(1)1001 0001 = 9 1
(2)1000 1001 = 8 9
(3) 0011 0110 = 3 6
(4) 1001 0000 = 9 0
2.7 將下列十進制數用8位二進制補碼表示:
(1)0 =0000 0000
(2)127 =0111 1111
(3)-127 =1000 0001
(4)-57 =1100 0111
2.8 進行十六進制數的加減運算,並說明是否有進位或錯位:
(1)1234H+7802H =8A36H
(2)F034H+5AB0H =4AE4H 前有進位,去掉
(3)C051H-12345H =0AEIDH 以字母開頭要有前導零
(4)9876H-ABCDH =0ECA9H
2.10 設置一個數據段,按照如下要求定義變量或符號常量:
(1)my1b為字符串變量:Personal Computer
my1b db 'Personal Computer'
(2)my2b為用十進制表示的字節變量20
my2b db 20
(3)my3b為用十六進制數表示的字節變量20
my3b db 14h
(4)my4b為用二進制表示的字節變量20
my4b db 00010100b
(5)my5w為20個未賦值的字變量
my5w dw 20 dup(?)
(6)my6c為100的常量
my6c = 100
(7)my7c表示字符串:Personal Computer
my7c equ <Personal Computer>
2.11 定義常量NUM,其值為5,數據段中定義字數組變量DATALIST,它的頭5個字單元中依次存放-10,2,5和4,最后一個單元處置不確定
NUM = 5
DATALIST DW -10,2,5,4,?
2.13寫出每條傳送指令執行后寄存器AX的內容:
org 100h varw dw 1234h,5678h varb db 3,4 vard dd 12345678h buff db 10dup(?) mess db 'hello' mov ax,offset mess ;ax=100h+(2*2+2+4+10)=100+14=114h mov ax,type buff+type mess+type vard ;1+1+4=6 mov ax,sizeof varw+sizeof buff+sizeof mess ;2*2+10+5=19=13h mov ax,lengthof varw+lengthof vard ;2+1=3
2.15 數據段有如下定義,8086處理器將以小段方式保存主存:
var dd 12345678h
現以字節為單位按地址從低到高的順序,寫出這個變量內容,並說明如下指令的執行結果:
mov bx, word ptr var ;bx=5678h mov cx, word ptr var+2 ;cx=1234h mov dl, byte ptr var ;dl=78h mov dh, byte ptr var+3 ;dh=12h
2.17 說明下列指令中源操作數的尋址方式? 假設VARW是一個字變量。
mov dx, 1234h ;立即數尋址 mov dx, varw ;直接尋址 mov dx, bx ;寄存器尋址 mov dx, [bx] ;寄存器間接尋址 mov dx, [bx+1234h] ;寄存器相對尋址 mov dx, varw[bx] ;寄存器相對尋址 mov dx, [bx+di] ;基址變址尋址 mov dx, [bx+si+1234h] ;相對基址變址尋址