X86組合語言從實模式到保護模式(一)

2021-07-17 02:38:24 字數 3528 閱讀 9417

不對請指正,歡迎交流

單位換算:

1 byte = 8 bit

1 kb = 1024 byte

1 mb = 1024 kb

1 gb = 1024 mb

8位暫存器可以容納8位元(bit), 或者說1個位元組   1byte=8bit,8個二進位制數 1111 1111 -> 0xff

16位暫存器可以存放2個位元組,也就是1個字, 從右到左數,其中0~7是低位元組,8~15是高位元組

32位暫存器可以放4個位元組也就是乙個雙字,其中0~15是低字,16~31是高位

8086內部有8個16位的通用暫存器,分別被命名為ax,bx,cx,dx,si,di,bp,sp

其中前四個ax,bx,cx,dx可以各自拆分成兩個8位暫存器,總共是8個8為暫存器,分別是ah,al,bh,bl,ch,cl,dh,dl

高低位關係是

15 8 7 0

---------------------

| ah | al | ax, ah位於高位元組,al位於底位元組

---------------------

8086內部有4個段暫存器,cs是段**暫存器,ds是資料段暫存器,es是附加暫存器,ss是棧段暫存器

ip是指令指標暫存器他只和cs一起使用,而且只有處理器才能直接改變他的內容。當一段**開始執行時,cs指向**段的起始位址,ip則指向段內偏移,這樣cs和ip共同形成的邏輯位址是處理器要執行指令的位址,並且由匯流排介面部件轉換成實體地址來取得指令,然後處理器自動根據當前指令的長度來改變ip的值,使它指向下一條指令的位址偏移。

cs中儲存的段位址是處理器開始執行指令的段位址

ds中儲存的段位址是處理器在訪問記憶體是預設的位址,例如,處理器要訪問記憶體位址0001h中的內容,會預設把0001h當作ds段中的偏移位址,如果ds是00ffh,那處理器要訪問的實體地址是00ffh:0001h

由於8086處理器提供裡20根位址匯流排,位址範圍是 00000h ~ fffffh, 但是16位段位址加上16位的偏移位址只能表示16位的實體地址

為了解決這個問題,8086在形成實體地址前,把段位址左移四位,形成20位的段位址,然後加上16位的偏移位址,這樣能夠表示20位的實體地址了

因為偏移位址是16位的,所以在保證段與段值之間不重疊的情況下,可以分成16個段(因為位址範圍最大f ffffh,乙個段偏移最大ffffh,fffffh/ffffh=fh 也就是10進製的16)

實體地址是82255h,如果段的劃分是在段之間不重疊的情況下的,他的記憶體位址可以表示為是 8000h:2255h

0x1234      ----> 立即數,字面值
mov 目的運算元, 源運算元

注意事項:

目的運算元與源運算元的的位數要一致

在目的運算元是段暫存器時,源運算元不能是立即數,但是可以先把立即數放到通用暫存器中,然把通用暫存器的值傳送給段暫存器

mov ax, 0x1234

mov ds, ax

如果不想使用預設的ds暫存器,可以指定暫存器進行偏移,例子中指定的是ex段暫存器,這種用法叫做段超越字首

mov [es:0x00], 0x4c

但是如果只是這麼執行還是會出錯,因為處理器不知道要操作空間的大小,因為兩邊都沒有指定這條指令是8位的還是16位的,所以要加乙個字首byte

mov byte [es:0x00], 0x4c

彙編位址 tag db 0, 1, 2, 3

在當前彙編位址宣告了4個位元組的空間,並且進行初始化,其中四個位元組裡的內容依次是0,1,2,3 ,並且在其他地方使用的時候可是使用tag這個標識代替當前的彙編位址

例如把第二個位元組中的內容從1變成2

mov byte [tag+1], 0x02

首先指定本次傳送的數的大小byte,指定傳送的位置tag+1,然後需要傳送的數0x02

db的意思是宣告位元組,所以他後面的運算元都會佔乙個位元組的長度,如果要宣告多個,各個運算元之間必須以逗號隔開

dw用於宣告字資料,dd用於宣告雙字資料(兩個字),dq用於宣告4字資料

16位的二進位制數除以8位的二進位制數

被除數必須事前傳送到暫存器ax中,指令執行後,商在暫存器al中,餘數在暫存器ah中

mov ax, 0x0023

div byte [0x1234]

32位的二進位制數除以16進製制的二進位制數

被除數的高16位放在dx中,低16位放到ax中,指令執行後,商在ax中,餘數在dx中

1 1 ---> 0

1 0 ---> 1

0 0 ---> 0

xr 目的運算元, 源運算元

目的運算元可以是通用暫存器和記憶體單元,一把來說兩個運算元應當具有相同的資料寬度,兩個運算元不能同時為記憶體單元

兩種形式,第乙個後面跟絕對位址

jmp 0x5000:0xf0c0 ;段位址加偏移位址

直接跳到0x5500:0xf0c0繼續執行

jmp near tag ; 相對位置

跳到tag標識處,

兩條指令都是跳轉,但編譯完成的機器碼是不一樣的,第一條是絕對位址跳轉,第二條是相對位置跳轉,指令的機器碼也不一樣

time 100 db 0

重複db 0 指令100次

movsb 傳送是以位元組為單位的

movsw 傳送是以字為單位的

傳送的顆粒:由使用的movsb(位元組)還是movsw(字)決定

傳送的次數:cx暫存器中儲存傳送的次數,每傳送一次自動減1

傳送方向: 由標誌暫存器flags中的df位來決定,df為0時,正向傳送;df為1時,反向傳送

設定df位: cld可以將df位清零---> 正向傳送

std可以將df位置1----> 反向傳送

rep指令字首:如果cx不為0,則重複執行

執行命令 rep movsb/ rep movsw

loop 目的位址

重複執行一段相同**

將暫存器cx中的內容減一

如果cx的內容不為0,轉移到指定的位置處執行,否則順序執行後面的指令

老樣子:cx裡的內容提前設定好

inc 目的運算元  ; 將目的運算元加一

dec 目的運算元 ; 將目的運算元減一

用0減去指令中指定的運算元,如果目的運算元不能明確操作的大小可以使用byte或word指定

neg [byte] 目的運算元

cbw:將暫存器al中的有符號數擴充套件到整個ax, al中的數提前設定 8位-->16位

11110001 ----> 11111111 11110001

cwd :將暫存器ax中的有符號數擴充套件到dx:ax 16位--->32位

idiv: 有符號除法,用法參考div

組合語言 基於X86 學習筆記

1.機器語言 machine language 是一種數字語言,專門設計成唄計算機處理器 cpu 理解。所有x86處理器都理解的共同機器語言。2.組合語言 assembly language 包含助記符書寫的語言。3.組合語言與機器語言是一一對應 one to one 的關係。4.彙編器 assem...

x86組合語言指令集

一 資料傳輸指令 8088 彙編跳轉 cmp a,b 比較a與b mov a,b 把b的值送給a ret 返回主程式 nop 無作用,英文 no operation 的簡寫,意思是 do nothing call 呼叫子程式 je 或jz 若相等則跳 jne或jnz 若不相等則跳 jmp 無條件跳 ...

X86組合語言中的registers相關

通常用於存放一般性的資料 cpu從何處執行是由暫存器決定的,設cs的value m,ip的value n cpu將從m 16 n 記憶體單元開始執行 因為cpu的位址加法器採用 實體地址 段位址 16 偏移位址 來表示實體地址 attention jmp 可以修改cs和ip的值 通常用來存放要訪問資...