匯編語言之?dāng)?shù)據(jù)處理的2個(gè)基本問題

1、bx、si、di和bp

Bx、si和di這3個(gè)寄存器我們已經(jīng)學(xué)過了,現(xiàn)在進(jìn)行一下總結(jié),并學(xué)一下bp。

1:在8086CPU中,只有這4個(gè)寄存器可以用在[…]中來進(jìn)行內(nèi)存單元的尋址。比如,下面的指令都是正確

的:

Mov ax, [bx]

Mov ax, [bx+si]

Mov ax, [bx+di]

Mov ax, [bp]

Mov ax, [bp+si]

Mov ax, [bp+di]

而下面的指令是錯(cuò)誤的:

Mov ax, [ax]

Mov ax, [cx]

Mov ax, [dx]

Mov ax, [ds]

2:在[…]中,這4個(gè)寄存器可以單個(gè)出現(xiàn),或只能以4種組合出現(xiàn):bx和si、bx和di、bp和si、bp和di。

比如,下面的指令是正確的:

Mov ax, [bx]

Mov ax, [si]

Mov ax, [di]

Mov ax, [bp]

Mov ax, [bx+si]

Mov ax, [bx+di]

Mov ax, [bp+si]

Mov ax, [bp+di]

Mov ax, [bx+si+idata]

Mov ax, [bx+di+idata]

Mov ax, [bp+si+idata]

Mov ax, [bp+di+idata]

而下面的指令是錯(cuò)誤的:

Mov ax, [bx+bp]

Mov ax, [si+di]

 
我們可以在訪問內(nèi)存單元的指令中顯式地給出內(nèi)存單元的段地址所在的段寄存器。

比如:mov ax, SS:[bx]    ;段地址在SS中。

      Mov ax, DS:[bp]    ;段地址在DS中。

      Mov ax, CS:[bp]    ;段地址在CS中。

      Mov ax, ES:[bp]    ;段地址在ES中。

在上面的指令:mov ax, ES:[bp] 中,我們接觸到了一個(gè)新的段寄存器ES,ES叫附加段寄存器,它的功能與

DS基本相同。

如果在[…]中使用寄存器bp,而指令中沒有顯式地給出段地址,段地址就默認(rèn)在SS中。比如,下面的指令:

Mov ax, [bp+200] 內(nèi)存單元[bp+200]的段地址就在SS中。

BP被稱作基址指針寄存器,它可以作SP使用,除了BP可以作為間接尋址寄存器而SP不能外,其余功能基

本相同。
 

事實(shí)上,通用寄存器除了ax、bx、cx、dx這4個(gè)外,還包括sp、bp、si、di這4個(gè)16位寄存器,以及ah、

al、bh、bl、ch、cl、dh、dl這8個(gè)8位寄存器,通用寄存器一共有以上這16個(gè)。

2、機(jī)器指令處理的數(shù)據(jù)在什么地方

絕大部分機(jī)器指令都是進(jìn)行數(shù)據(jù)處理的指令,處理大致可分為3類:讀取、寫入、運(yùn)算。在機(jī)器指令這一層來

講,并不關(guān)心數(shù)據(jù)的值是多少,而關(guān)心指令執(zhí)行前一刻,它將要處理的數(shù)據(jù)所在的位置。指令在執(zhí)行前,所要處理

的數(shù)據(jù)可以在3個(gè)地方:CPU內(nèi)部、內(nèi)存、端口,比如下圖所列的指令:

3、匯編語言中的數(shù)據(jù)位置的表達(dá)

在匯編語言中如何表達(dá)數(shù)據(jù)位置?匯編語言中用3個(gè)概念來表達(dá)數(shù)據(jù)的位置,即立即數(shù)、寄存器、地址(偏移

地址和段地址)。

1. 立即數(shù)(idata)

對(duì)于直接包含在機(jī)器指令中的數(shù)據(jù)(執(zhí)行前在CPU的指令緩沖器中),在匯編語言中稱為:立即數(shù)(idata)。

例:mov ax, 136aH    ;指令要處理的數(shù)據(jù)就是立即數(shù)136aH。

Add ax, 2000H    ;指令要處理的數(shù)據(jù)就是立即數(shù)2000H。

Sub ax, a2c7H    ;指令要處理的數(shù)據(jù)就是立即數(shù)a2c7H。

2. 寄存器

指令要處理的數(shù)據(jù)在寄存器中,在匯編指令中給出相應(yīng)的寄存器名。

例:mov ax, bx    ;指令要處理的數(shù)據(jù)在bx中。

Mov ds, ax    ;指令要處理的數(shù)據(jù)在ax中。

Push bx    ;指令要處理的數(shù)據(jù)在bx中。

Mov DS:[123a], bx    ;指令要處理的數(shù)據(jù)在bx中。

3. 段地址和偏移地址

指令要處理的數(shù)據(jù)在內(nèi)存中,在匯編指令中可用[…]的格式給出偏移地址,段地址在某個(gè)段寄存器中。比如以下

的指令:

Mov ax, [107a]

Mov ax, [di]

Mov ax, [bx+8]

Mov ax, [bx+si]

Mov ax, [bx+si+8]

指令要處理的數(shù)據(jù)偏移地址在[…]中,段地址默認(rèn)在DS中。

下面的指令:

Mov ax, [bp]

Mov ax, [bp+8]

Mov ax, [bp+si]

Mov ax, [bp+si+8]

指令要處理的數(shù)據(jù)偏移地址在[…]中,段地址默認(rèn)在SS中。

存放段地址的寄存器也可以是顯性給出的,比如以下指令:

mov ax, DS:[bp]    ;指令要處理的數(shù)據(jù),段地址在DS中。

Mov ax, ES:[bx]    ;指令要處理的數(shù)據(jù),段地址在ES中。

Mov ax, SS:[bx+si]    ;指令要處理的數(shù)據(jù),段地址在SS中。

Mov ax, CS:[bx+si+8]    ;指令要處理的數(shù)據(jù),段地址在CS中。
 

4、尋址方式


對(duì)尋址方式進(jìn)行一下總結(jié),見下表:表中EA=偏移地址,SA=段地址,寄存器加上一個(gè)小括號(hào),表示這個(gè)

寄存器中的數(shù)值,比如第二條含義:EA=(bx);SA=(ds),(bx)就表示bx中的數(shù)值,(ds)就表示ds中的數(shù)

值。

5、指令要處理的數(shù)據(jù)有多長

8086CPU的指令,可以處理兩種尺寸的數(shù)據(jù):byte和word。所以在機(jī)器指令中要指明,指令進(jìn)行的是字操

作還是字節(jié)操作,對(duì)于這個(gè)問題,匯編語言中用以下方式處理。

1. 通過寄存器名指明要處理的數(shù)據(jù)的尺寸。

例如,下面的指令中,寄存器指明了指令進(jìn)行的是字操作,因?yàn)檫@些寄存器是16位的。

Mov ax, 123H

Mov bx, DS:[210a]

Add ax, 1000H

Sub bx, 2ffH

下面的指令中,寄存器指明了指令進(jìn)行的是字節(jié)操作,因?yàn)檫@些寄存器是8位的。

Mov al, 12H

Mov bl, DS:[210a]

Add al, 10H

Sub bl, 2fH

2. 在沒有寄存器名存在的情況下,用操作符word prt或byte prt指明內(nèi)存單元的長度,前者為字單元,后者

為字節(jié)單元。

例如,下面的指令中,用word ptr指明了指令訪問的內(nèi)存單元是一個(gè)字單元。

Mov word ptr DS:[a017], 28H

Add word ptr [bx], 78H

下面的指令中,用byte prt指明了指令訪問的內(nèi)存單元是一個(gè)字節(jié)單元。

Mov byte ptr DS:[1a7], 1aH

Add byte ptr [bx], 62H

在沒有寄存器參與的內(nèi)存單元訪問指令中,用word ptr或byte ptr顯性地指明所要訪問的內(nèi)存單元的長度是

很必要的,否則,CPU無法得知所要訪問的單元是字單元還是字節(jié)單元,從而造成出錯(cuò)。

3. 其它方法。有些指令默認(rèn)了訪問的是字單元還是字節(jié)單元,比如:push [123a]和pop[123c]就不用指明訪

問的是字單元還是字節(jié)單元,因?yàn)閜ush和pop指令只進(jìn)行字操作。

6、mul指令

Mul為乘法指令,使用mul做乘法的時(shí)候,注意以下兩點(diǎn):

1. 兩個(gè)相乘的數(shù):這兩個(gè)相乘的數(shù),要么都是8位,要么都是16位,如果是8位,一個(gè)默認(rèn)放在al中,另一

個(gè)放在8位寄存器或內(nèi)存字節(jié)單元中;如果是16位,一個(gè)默認(rèn)放在ax中,另一個(gè)放在16位寄存器或內(nèi)存字單元

中。

2.結(jié)果:如果是8位乘法,結(jié)果默認(rèn)放在ax中,如果是16位乘法,結(jié)果高位默認(rèn)在dx中存放,低位在ax

中存放。

指令格式如下:

Mul 通用寄存器

Mul 內(nèi)存單元

內(nèi)存單元可以用不同的尋址方式給出,比如:

Mul byte ptr DS:[7102]    ;8位乘法。

Mul word ptr [bx+si+8]    ;16位乘法。

例1:計(jì)算100×10。

100和10都小于255,可以做8位乘法,代碼如下:

Mov al, 100

Mov bl, 10

Mul bl

結(jié)果:ax=al×bl=100×10=1000(3E8H)

例2:計(jì)算100×10000。

100小于255,可10000大于255,所以必須做16位乘法,代碼如下:

Mov ax, 100

Mov bx, 10000

Mul bx

結(jié)果:ax×bx=100×10000=1000000(F4240H)

Ax=4240H  dx=FH

7、div指令

Div是除法指令,使用div做除法的時(shí)候,應(yīng)注意以下問題:

1. 除數(shù):有8位和16位兩種,在一個(gè)寄存器或內(nèi)存單元中。

2. 被除數(shù):如果除數(shù)為8位,被除數(shù)則為16位,默認(rèn)放在ax中;如果除數(shù)為16位,被除數(shù)則為32位,在

Dx和ax中存放,dx存放高16位,ax存放低16位。

3. 結(jié)果:如果除數(shù)為8位,則al存儲(chǔ)結(jié)果的商,ah存儲(chǔ)結(jié)果的余數(shù);如果除數(shù)為16位,則ax存儲(chǔ)結(jié)果的

商,dx存儲(chǔ)結(jié)果的余數(shù)。

指令格式如下:

Div 通用寄存器

Div 內(nèi)存單元

內(nèi)存單元可以用不同的尋址方式給出,比如:

Div byte ptr DS:[21a5]    ;除數(shù)為8位的除法。

Div word ptr [bx+si+8]    ;除數(shù)為16位的除法。

例1:計(jì)算100001÷100。

被除數(shù)100001為32位,轉(zhuǎn)化成16進(jìn)制為186a1H,低16位值86a1H放在ax中,高16位值1H放在

Dx中,除數(shù)100轉(zhuǎn)化為16進(jìn)制64H后,放在一個(gè)16位寄存器中,代碼如下:

Mov dx, 1H

Mov ax, 86a1H

Mov bx, 64H

Div bx

結(jié)果:(dx×10000H+ax)÷bx=186a1H÷64H=3E8H余1。

Ax=3e8H(1000)  dx=1H

例2.計(jì)算1001÷100。

被除數(shù)1001可用ax存放,除數(shù)100可用8位寄存器存放,代碼如下:

Mov ax, 1001

Mov bl, 100

Div bl

結(jié)果:ax÷bl=1001÷100=10余1。

Al=10  ah=1 

 

 






作者:chen.yu
深信服三年半工作經(jīng)驗(yàn),目前就職游戲廠商,希望能和大家交流和學(xué)習(xí),
微信公眾號(hào):編程入門到禿頭 或掃描下面二維碼
零基礎(chǔ)入門進(jìn)階人工智能(鏈接)