0 前言
本文基于8086匯編語言,不過x86系列語言具備向下兼容特點,大多數情況都可以用。
與高級語言數據類型的自動轉換和強制轉換一樣,匯編語言的數據類型也有 自動匹配和手動匹配。
下面,我來介紹一下匯編語言的相關原則。
1 數據類型匹配的原則
任何時候,數據的匹配,只能是完全一樣的數據類型才能進行數據傳送。
也就是8位對8位,16位對16位,32位對32位。
比如
mov ax,bx
mov al,bl
請注意,這里的原則與操作數個數無關,指令如果涉及到數據傳送過程,至少也要有數據提供方,有數據接收方。
需要注意,這里的數據傳送,是copy,而不是remove,傳送之后原來的數據不消失,只是復制過去。
你想問為什么是copy?先明白一個問題,計算機的本質,是電子計算機,是基于電的。你可以想象一下,有兩根導線,中間有一個沒有閉合的開關,開關閉合前,左邊的是導線通電的,右邊的不帶電,現在將開關閉合,右邊的導線是不是也通電了,左邊的導線沒有因此不帶電吧?開關閉合后通電的過程,就是數據傳送的過程,我想你大概能理解為什么是copy了。
2 自動匹配
由上面的圖你可以看到,有三個部分
- 數據提供方A
- 數據傳送帶B
- 數據接收方C
自動匹配分為以下情況
- B大小固定:則A,C的大小自動固定
- 例如:指令push,pop要求必須是字傳送,也就是B的大小限定為16
- ……
- B大小不固定:則A,C只要有一方是固定,另一方自動固定
- 例如:
mov ax,1
,因為ax
固定16位,則1
也要是16位,如果不是,需要變成16位的(插一句,這就是符號擴展) mov ax,bx
,雙方都固定16位也是可以的
- 例如:
對于B固定的情況,只有很少一部分,記住即可,這里談一下不固定的部分。
A,C分別代表數據的提供方和接收方,它們不一定是兩個操作數,也可能是隱藏的,例如有的指令是單操作數,有的沒有操作數,但這都不妨礙它們都有A和C。
A或C可能是
- 寄存器
- 內存單元
當一方為寄存器,例如使用ax
,則另一方就需要是16位的數據,可以是
- 寄存器,例如
bx
- 定義為
dw
類型的數據 - 某個數據的首地址,自動按16位提取,不需要加限制條件,例如
ds:[0]
- 立即數,自動擴展為16位的
當一方為dw
類型數據,也是同理。
不可以的情況:當一方為內存單元地址,另外一方為立即數,例如mov ds:[0],1
,這就是手動匹配,看下一節。
3 手動匹配
當A和C的大小都不能確定的時候,就需要手動匹配,加上限定條件了,這通常發生在<內存單元地址>
和立即數
身上,因為它們是不固定大小的,如果它們結合,或者單獨出現,就必須加上限制條件。
例如
mov word ptr ds:[0],1
jmp word ptr ds:[0]
只能對內存單元地址做出規定,也就是word ptr
、byte ptr
、dword ptr
等,立即數是墻頭草,別人多大他多大。
4 注意事項
需要注意的是,對于數據類型匹配這件事情,取決于編譯器和CPU的設計者,大多數情況是遵循我上面所說的原則的,對于極少數特殊情況,也是完全可能的,不要因此感到驚訝。
5 小結
前面解釋了很多,不過你根本沒有必要記憶,只需要警惕一些特殊情況即可。
對于沒有限定B部分的指令
- 雙操作數指令,出現內存單元地址和立即數,地址要限定
word ptr
等類型 - 單操作數,內存單元地址要限定類型
就像賽跑,規定了起點位置和長度,就能夠得到終點位置
- 起點位置就是內存單元地址,比如
ds:[0]
代表起點位置為ds*16 + 0
- 長度就是數據類型,比如
word ptr
代表長度2個字節
對于其他指令集架構,原理上是有相通性的,請讀者自行思考。