乘法(MUL/IMUL)
目錄
- 乘法(MUL/IMUL)
- `IMUL`(signed multiply)有符號數乘法
- `MUL`(unsigned multiply)無符號數乘法
麻!屬實是被這個有符號乘法給整麻了,教材就一行例子直接不解釋了,關于標志位溢出的一概不談,屁用沒有。然后去網上查了查好像說明白了但又沒完全明白,以至于我剛剛才明白
先說這有符號乘法!
IMUL
(signed multiply)有符號數乘法
格式:MUL SRC
操作:
- 當操作數為字節時,(AX)←(AL)×(SRC)(AX)\gets (AL)\times (SRC)(AX)←(AL)×(SRC)
- 當操作數為字時,(DX,AX)←(AX)×(SRC)(DX, AX)\gets (AX)\times(SRC)(DX,AX)←(AX)×(SRC)
標志位響應:
- 當乘積的高半部分是低半部分的符號擴展時,表示未溢出,OF=CF=0OF=CF=0OF=CF=0
- 當乘積的高半部分不是低半部分的符號擴展時,表示溢出,OF=CF=1OF=CF=1OF=CF=1
符號擴展
微機系統中,有時需要將一個數據從位數較少擴展到位數較多,例如,在執行除法指令時,由于對字節除數相除要求被除數為16位,對字除數要求被除數為32位,即被除數必須為除數的倍長數據,因此就涉及數據的位數擴展問題,具體的擴展有符號擴展與零擴展兩種方法
- 當要擴展的數據是無符號數時可采用零擴展。即在最高位前擴展0,補充夠位數即可
- 當要擴展的數據是有符號數時需采用符號擴展。由于采用補碼形式表示的整數具有固定的長度,因此在匯編指令系統中,經常有一些指令需要將其中的操作數進行符號位擴展。譬如兩個8位或16位數據進行相加或者相減運算時,當有不足位數要求的數據時,需要將少位數據擴展成與位數要求相一致的數據;兩個數據相除時,被除數應必須是除數的倍數等。 符號擴展的方法是將需要擴展的數據的符號位填入到擴展的每一位,以保持其作為有符號數的值的大小不變。這里要注意,要擴展的數須是用補碼形式表示的有符號數,符號擴展后。其結果仍是該數的補碼。 因此,對于補碼表示的數,其正數的符號擴展是將其符號位0向左擴展(補0);其負數的符號擴展是將其符號位1向左擴展(補1)
有符號數相乘的步驟:
- 符號位擴展,將兩個乘數都擴展至原來的兩倍大(例如,字節數據100011011000\ 11011000?1101擴展為字數據11111111100011011111\ 1111\ 1000\ 11011111?1111?1000?1101)
- 擴展后的數據相乘
- 取有效位(即為原乘數位數的兩倍)
舉例:
F1H×F1HF1H\times F1HF1H×F1H((?15)×(?15)=(+225)(-15)\times (-15)=(+225)(?15)×(?15)=(+225))
-
符號位擴展
11110001→11111111111100011111\ 0001\to {\color{Blue} 1111\ 1111} \ 1111\ 00011111?0001→1111?1111?1111?0001 -
擴展后的數據相乘
1111111111110001×111111111111000111111111111000100000000011100001\begin{array}{r} {\color{Blue} 1111\ 1111} \ 1111\ 0001\\ \times {\color{Blue} 1111\ 1111} \ 1111\ 0001\\ \hline {\color{Gray} 1111\ 1111\ 1110\ 0010} \ 0000\ 0000\ 1110\ 0001 \end{array}1111?1111?1111?0001×1111?1111?1111?00011111?1111?1110?0010?0000?0000?1110?0001?? -
取有效位
保留低16位有效位00000000111000010000\ 0000\ 1110\ 00010000?0000?1110?0001
故AH=00HAH=00HAH=00H、AL=E1HAL=E1HAL=E1H -
判斷標志位響應
由于AHAHAH并不是ALALAL的符號擴展
0000000011100001{\color{Green} 0000\ 0000} \ {\color{Red} 1} 110\ 00010000?0000?1110?0001
AHAHAH全為0,而ALALAL最高位(符號位)為1,因此溢出,OF=CF=1OF=CF=1OF=CF=1有符號數乘積的高半部分只起到表示符號的作用,溢出時,其是無效的信息可不關注,因此對于8位有符號數相乘不溢出的結果范圍即為?128-128?128 ~ +127+127+127,這里低8位最高位為1表示結果為負數,而兩乘數均為負數,結果應為正數,故產生了溢出
-
debug測試
24H×FDH24H\times FDH24H×FDH((+36)×(?3)=(?108)(+36)\times (-3)=(-108)(+36)×(?3)=(?108))
0000000000100100×111111111111110100000000001000111111111110010100\begin{array}{r} {\color{Blue} 0000\ 0000} \ 0010\ 0100\\ \times {\color{Blue} 1111\ 1111} \ 1111\ 1101\\ \hline {\color{Gray} 0000\ 0000\ 0010\ 0011} \ {\color{Green} 1111\ 1111\ 1} 001\ 0100 \end{array}0000?0000?0010?0100×1111?1111?1111?11010000?0000?0010?0011?1111?1111?1001?0100??
這里高半部分是低半部分的符號擴展,因此未溢出,OF=CF=0OF=CF=0OF=CF=0,這里結果100101001001\ 01001001?0100即為?108-108?108的補碼形式
MUL
(unsigned multiply)無符號數乘法
格式與操作與IMUL
相同,用來作無符號數乘法
標志位響應:
- 當乘積的高半部分不為0時,表示溢出,CF=OF=1CF=OF=1CF=OF=1
- 當乘積的高半部分為0時,表示未溢出,CF=OF=0CF=OF=0CF=OF=0
很簡單就直接乘,乘就完事了!直接上例子(和有符號的第一個例子數據相同,看其對比)
舉例:
F1H×F1HF1H\times F1HF1H×F1H(241×241=58081241\times 241=58081241×241=58081)
11110001×111100011110001011100001\begin{array}{r} 1111\ 0001\\ \times 1111\ 0001\\ \hline 1110\ 0010\ 1110\ 0001 \end{array}1111?0001×1111?00011110?0010?1110?0001??
顯然這里高半部分不為0,故溢出,CF=OF=1CF=OF=1CF=OF=1
這里的溢出和有符號的溢出都是針對于低半部分范圍而言的,即對于無符號數的乘積不溢出的范圍則是000 ~ 255255255,但是由于高半部分的數據由AXAXAX的高半部分AHAHAH存儲,故雖說是“溢出”但是其總的結果是正確的、有效的;而對于有符號乘積,其AHAHAH存的只是符號擴展信息,當發生溢出時,則代表該結果是錯誤的
另外,無符號數相乘結果總是正確的,因為最大的乘積也不會超越其乘數位數的兩倍可表示的范圍
11111111×111111111111111000000001\begin{array}{r} 1111\ 1111\\ \times 1111\ 1111\\ \hline 1111\ 1110\ 0000\ 0001 \end{array}1111?1111×1111?11111111?1110?0000?0001??
FFH×FFH=FE01HFFH\times FFH=FE01HFFH×FFH=FE01H