用db定義的資料,每個資料占用1b的儲存器。可以出現用單或雙引號括起來的單個或多個字元,每個字元佔1b,按照它們出現的順序用ascii**儲存。dup稱為「重複定義符」,表示定義若干個相同的資料。偽指令dw用來定義字資料,每個資料占用2b,資料的高位存放在位址較大的單元裡。注意:用dw定義字串時,只能是兩個,而用db定義時,沒有這個限制。
運算元:有3種型別的運算元:暫存器運算元、立即數運算元和儲存器運算元。
暫存器運算元又包括段暫存器和通用資料、位址暫存器。段暫存器:cs,ds,ss,es。通用資料暫存器:ax,bx,cx,dx。通用位址暫存器:sp,bp,si,di。在這麼多的暫存器中,只有4個暫存器可以用來間接定址:bx,bp,si,di(在8086中)。在這之中,預設情況下,bp與段暫存器ss搭配,其餘3個與ds搭配。
立即數暫存器:二進位制、十進位制或十六進製制常數,可求值的表示式、字元、標號等都可以用作運算元。
儲存器運算元:它是由段基址和偏移位址組成。大多數情況下,指令使用ds暫存器的內容作為運算元的段基址,所以指令中不需要再指出段基址。為此,常常在程式開始處把資料段的段基址裝入ds暫存器中。段基址的問題解決了。剩下的就是偏移位址的問題了。儲存器的偏移位址可以由幾個部分組合而成,合成後得到的偏移位址稱作有效位址。指出偏移位址的方法有兩種:直接的和間接的。所謂直接位址就是在指令裡直接寫出儲存單元偏移位址。注意點:當變數名a定義之後,它的屬性就確定下來了,而直接位址[0000h]卻沒有固定的屬性,它可以代表位元組位址,也可以代表字位址甚至是雙字位址。所謂間接位址就是把儲存單元的偏移位址事先裝入某個暫存器中,需要時通過這個暫存器來找到這個儲存單元,所以也稱為暫存器間接定址。這時就要用到上面提到的知識點,只有哪4個暫存器可以用來間接定址。然後,就是還可以用兩個暫存器聯合起來定址。但是只能從(bx,bp)和(si,di)中各選出乙個使用。這時,就會有幾個專有的名詞需要知道:直接定址,暫存器間接定址,暫存器相對定址,基址變址定址和基址變址相對定址。
請注意標號和變數名的區別:標號出現在指令行前面,標號與指令之間用冒號(:)分開。進入程式後,**段暫存器cs已經由作業系統設定為**段的段基址,資料段的段基址需要由使用者裝入到ds中。注意:assume偽指令僅僅說明段和段暫存器之間的對應關係,段基址的裝入仍然需要程式設計師通過指令實現。
關於mov指令的使用有如下限制:
1.源運算元與目的運算元可以是位元組、字或雙字,但必須具有相同的型別。
2.源運算元與目的運算元不能同時為儲存器運算元。
3.目的運算元不能是立即數。
4.flags,eflags,ip,eip不要用作運算元。因為它們是專用暫存器。
5.對於段暫存器作為運算元的mov指令:
(1).源運算元與目的運算元不能同時為段暫存器;
(2).目的暫存器是段暫存器時,源運算元只能是暫存器或儲存器,不能是立即數;
(3).cs不能用作目的運算元。
當我們使用立即數作為源運算元時,該立即數會按照目的運算元的型別進行擴充套件。如果立即數本身沒有符號,進行「零擴充套件」;如果立即數本身有符號,進行「符號擴充套件」。可以用「型別 ptr」指定,或強行改變運算元的型別。
存放位址的暫存器或儲存單元稱為位址指標或指標。
擴充套件指令cbw,cwd。這兩個指令都會用到ax,dx這兩個通用資料暫存器。
堆疊也是使用者使用的儲存器的一部分,它用來存放一些臨時性的資料和其他資訊。堆疊段和資料段、**段的使用有以下不同:首先,它從較大位址開始分配合使用;然後,由sp中位址指出的儲存單元稱為棧頂,資料總是在棧頂位置存入、取出;最先進入的資料最後被彈出。
8086cpu的push指令不支援立即數運算元。
可以用equ,=來定義乙個符號。彙編時,對equ定義的符號名用對應的表示式進行替換。使用等號『=』定義符號名時,只能使用常數表示式,而且對乙個符號可以多次定義。乙個新的定義出現後原來的定義自動停止。用equ定義的符號名不允許重複定義。
用於計算有效位址表示式有3個運算子:+,-和。+,-運算子對構成有效位址的各個分量進行加、減操作。稱為索引運算子,用來括起組成有效位址的乙個分量,各個分量相加,得到最後的有效位址。
用於產生立即數運算元的表示式有4類運算子:算術運算子、邏輯運算子、關係運算子、位址運算子。在這4個中值得注意的是關係運算子,它用於兩個數的比較,結果為真(-1)或假(0)。位址運算子對變數名、標號、位址表示式進行計算,得到作為立即數的運算結果。seg取位址表示式所在段的段基址。
眾多指令的彙總:
add:加法指令。adc:帶進製的加法指令,主要用於兩個資料分段相加時高位的加法運算。inc:增量指令。
sub:減法指令。sbb:帶借位的減法指令,主要用於兩個資料段相減時高位的減法運算。dec:減量指令。neg:求補指令。
mul:無符號數乘法。這時這個源運算元不可以是立即數。這個指令又要用到ax,dx這兩個暫存器。兩個n位運算元相乘,得到2n位的乘積。imul:有符號數乘法。這條指令有3種格式。imul 源運算元、imul 目的運算元,源運算元和imul 目的運算元,源運算元1,源運算元2。注意點:第一種形式和無符號乘法用法一致,第二種和第三種形式首先源運算元可以使立即數,但不能是8位,且兩個n位運算元相乘,得到的還是n位的乘積。
div:無符號除法。idiv:有符號除法。兩個n位運算元相除,應首先把被除數零擴充套件為2n位。
loop:迴圈指令。這個指令要用到cx這個暫存器,並且把cx當做無符號數。也有標號的用法。loop 標號,cx暫存器被稱為計數器。還有就是有條件的迴圈指令(主要是看cx的值)loopz/loope、loopnz/loopne。
daa:十進位制加法調整。功能:對al中的加法結果進行bcd運算調整。das:十進位制減法調整。
aaa:非壓縮十進位制加法調整。aas:非壓縮十進位制減法調整。aam:非壓縮十進位制乘法調整。功能:對ax中的乘法結果進行非壓縮bcd數運算調整。aad:非壓縮十進位制除法調整。
and:邏輯乘指令。使用它可以對運算元有選擇地部分清零。or:邏輯加指令。xor:邏輯異或指令。not:邏輯非指令。
輸出單個字元(存放在dl中的字元):int 21h的2號功能。輸出乙個字串(dx中存放的輸出字串的首位址):int 21h的9號功能。要求字串以『$'為結束標誌,且該字元不會輸出。字元的輸入:int 21h的1號、7號、8號和6號功能。其中還有乙個10號功能,需要與乙個緩衝區搭配使用,然後將dx存放緩衝區的首位址。
移位指令:shl,shr。形如:shl 目的運算元,移位次數。其中的移位次數只能是常數1或暫存器cl。sar,sal。與上面功能相似。rol,ror:功能是將目的運算元向左或右移動指定的位數,移出的高位順序進入地位,最後移出的位同時進入cf。rcl、rcr都是帶進製的迴圈左移或右移。(cf中儲存最後移出的那一位)std,cld分別將df位置成1和0。jmp:無條件轉移指令。cmp:比較指令。目的運算元和源運算元中至少有乙個暫存器。test:測試指令。主要是用到zf這個標誌位。jcc:有條件轉移指令。cc可以被替換成1~3個字母。其中g,l,e,n是用於有符號的字母。而a,b,e,n是用於無符號的字母。
call 子程式名。呼叫指令。ret返回指令:用來從子程式返回主程式。子程式的定義要用到proc和endp這兩個關鍵字。
movsb/movsw/movsd:movs指令可以把1b,2b,4b的源資料區資料傳送到目的儲存單元,同時根據方向標誌對源變址暫存器和目的變址暫存器進行修改。這組指令的定址方式是隱含的,源運算元位址由ds:si提供,目的串運算元位址由es:di提供。
組合語言 AT T組合語言
這兩天的pwn題環境都是在linux中,採用的組合語言是 at t 格式。之前學習的是intel格式的8086彙編,今天學習了下at t組合語言。基於x86 架構的處理器所使用的彙編指令一般有兩種格式 操作intel格式at t格式 暫存器命名 push eax pushl eax 常數 立即運算元...
組合語言 第二單元 整理
以下內容以8086cpu intel系列為根據處理 8086cpu intel系列 16位微處理器 20位位址匯流排 14個16位暫存器 通用暫存器 ax accumulator register bx base register cx count register dx data register...
組合語言 彙編指令
功能 用來進行資料傳輸。以 mov a,b 為例,相當於a b。具有以下形式 mov 暫存器,資料 mov 暫存器,暫存器 mov 暫存器,記憶體單元 mov 記憶體單元,暫存器 mov 段暫存器,暫存器 功能 用來做加法。以 add a,b 為例,相當於a a b。具有的形式,和 mov 一樣。功...