表述了單元長度的标号
assume cs:code
code segment
a dw 1,2,3,4,5,6,7,8 ;a代表了code段的首位址code:00,由于dw,也代表了a開始的這一小段記憶體都是按照字單元存儲的。
;從code:[0]~code:[15],也就是,a[0]~a[15];a[si]代表了從code:00開始的偏移量為si的記憶體單元。
;此記憶體單元是字單元,故si的偏移量是2個位元組。
b dd 0 ;b代表了code段中緊鄰a段位址的code:[16](首位址),一個雙字的單元,它存儲位置是code:[16]~code:[19],也就是b[0]~b[3];
;剩下的空間都是真正的CPU執行的代碼了。
start:mov si,0
mov cx,8
s:mov ax,a[si] ;mov ax, a[si]代碼含義:将偏移量為si的段位址(或記憶體段首位址)為a的記憶體單元按字單元送入到ax中。
add word ptr b[0],ax ;add word ptr b[0], ax,代碼含義:将ax值與b标号的低16位做加法,結果存儲在b标号的低16位中;
;此時b代表的是雙字單元,如果add b, ax;編譯器肯定報錯,因為它們的類型不比對。
;此處必須指定b[0]是按照字單元作為存儲結構的。
adc word ptr b[2],0 ;adc word ptr b[2], 0;代碼含義:帶進位加法,将0與上一指令中的CF值相加,結果存儲在b的高16位單元中。
;目的:防止低16位值産生進位。同理:此處必須指定b[2]是按照字單元作為存儲結構的。這個執行個體就是高位不溢出加法的套路。
;對于無符号數加法它的最大允許範圍是(0000 0000H~FFFF FFFFH):0~4294967295
add si,2 ;add si, 2;代碼含義:si的偏移量,由于a的偏移量是按照字單元偏移,故si為2個位元組的偏移
loop s
mov ax,4c00h
int 21h
code ends
end start
在其他段中使用資料标号
assume cs:code, ds:data
data segment ;即使在assume這個僞指令中将ds和data聯系在一起(C語言的全局聲明意思)。
;如果沒有将data的段位址指派給ds,那麼[si]尋址的記憶體單元是錯誤的,并不是ds:[si]或a[si]。
a db 1,2,3,4,5,6,7,8
b dw 0
data ends
code segment
start: mov ax,data ;如果在assume中沒有ds:data,那麼在code段中使用a和b是不可能的。因為a和b在code段是不可以見的。
mov ds,ax
mov si,0
mov cx, 8
s: mov al, a[si] ;a[si]代表的是一個位元組(它已經代表位址和單元長度了),指派給ax是錯誤的,應該指派給al,别犯這樣的低級錯誤。
;(ah)=0,是防止高位不為零,al+ah組合成資料就是(ax)。
mov ah, 0
add b, ax
inc si
loop s
mov ax,4c00h
int 21h
code ends
end start
直接定址表
1. 自定義(映射)表
自定義(映射)表是一種巧妙的程式設計方法。在程式設計時,我們可以利用各種自定義(映射)表,在兩個資料集合之間建立一種映射關系,使得我們可以利用查表的方法,根據給出的資料(輸入)得到其在另一個集合中的對應資料(輸出)。這種設計一般來說有以下3中目的:
- 為了算法的清晰和簡潔;
- 為了加快運算速度;
- 為了使程式易于擴充。
2. 資料表
- 一個位元組可以用兩個16進制字元表示,分别表示高4位和低4位的值;
- 一個16進制的值的範圍為“0 - 15”,符号範圍為“0 - F”,建立如下一張字元表:
table db '0123456789ABCDEF'
在這張字元表(字元串)中,它的下标(index)和對應的字元(value),兩者之間有一個簡單的線性映射關系。我們通過下标運算(查表),就可以快速地從給定的數擷取對應的字元。
3. 位址表
table dw ag0,ag30,ag60,ag90,ag120,ag150,ag180 ;字元串偏移位址表
ag0 db '0',0 ;利用mov bx,table[bx]做為table的偏移,取得對應的字元串的偏移位址,放入bx中
ag30 db '0.5',0
ag60 db '0.866',0
ag90 db '1',0
ag120 db '0.866',0
ag150 db '0.5',0
ag180 db '0',0