1. 程式人生 > >【組合語言】x86組合語言基礎知識

【組合語言】x86組合語言基礎知識

第二章

  • 資料儲存方式,高地址儲存資料高位
  • 位元組:8位
  • 字: 兩個位元組
  • 暫存器表示大小寫不敏感

  • 指令的錯誤表示:

    • 不能將16位暫存器與8位暫存器混合使用(add ax, bl)
    • 不能將大小超過暫存器所能儲存限制的資料傳給暫存器(mov al,100H)

2.4實體地址

所有的記憶體單元構成的儲存空間是一個一維的線性空間。

2.5 16位結構的CPU

16位結構的CPU,說明了CPU具有以下特性:
    運算器一次最多可以處理16位的資料;
    暫存器的最大寬度為16位;
    暫存器和運算器之間的資料通路是16位。

2.6 8086CPU給出實體地址的方法

8086內部採用一種機制,用兩個16位地址合成一個20位實體地址。

段相關概念

  • 實體地址 = 段地址*16+偏移地址,(段地址乘以16,就是將用16進製表示的地址,左移一位,末尾加一個0)*16突破了x86彙編16位的限制,就是說一個記憶體地址,用兩個數來儲存,並且為了突破存數大小的限制,將各個數按照一定的規則縮小比例,達到儲存足夠大的記憶體地址。 利用段地址的目的就是為了實體地址的方便儲存。
    特別注意,計算段的大小的時候,要用基礎地址(段地址*16)而不能用段地址,並且要每個段的尾基礎地址減去起始基礎地址,然後在加上1H(因為首位兩個地址都屬於該段),由於偏移地址為16位,所以定址範圍也在2^16,即一個段的最大長度不能超過64KB.

    • 段暫存器:4個CS、DS、SS、ES、
    • CS程式碼段暫存器,IP指令指標暫存器. CS中為M,IP中為N,則CPU從M*16+N的位置開始讀取指令。CPU任何時刻將CS:IP指向的內容當做指令執行。

    • 8086工作過程:

      • (1)從CS:IP指向的記憶體單元讀取指令,讀取的指令進入指令緩衝器;
      • (2)IP = IP+所讀取指令的長度,從而指向下一條指令。(IP是偏移地址,所以IP要加上指令對應的位元組數)
      • (3)執行指令。跳轉到步驟一。
  • CPU剛啟動的時候,CS:IP中的內容:
    CS:FFFFH
    IP: 0000H

    • 修改CS、IP內容的指令

      • jmp 段地址:偏移地址
      • 執行後CS = 段地址, IP = 偏移地址。
    • 如果只想修改IP中的值
      jmp 某一合法暫存器

    • 比如:
      jmp ax
      就是用ax的值修改IP的值

第三章

  • 地址都是用位元組來說的,兩個連續的記憶體單元組成一個字。
  • 低地址存低位,高地址存高位。起始地址為低地址。(特別注意豎著畫的儲存器)
  • N地址字單元,起始地址為N的字單元
  • DS和[address]
mov bx, 100H
    mov ds, bx//    8086cpu不支援直接將常數送入段暫存器
    mov al, [0] //是將後面的內容移到前面

[….]表示一個記憶體單元,方括號中的數字表示地址偏移地址。執行這條指令時,cpu會讀取DS中的地址作為段地址。然後利用段地址和偏移地址計算出實體地址在取那個實體地址中的資料到指定暫存器中。所以mov指令中只指出偏移地址,而省略段地址

  • mov指令可以有以下幾種形式

    • mov 暫存器 資料
    • mov 暫存器 暫存器
    • mov 暫存器 記憶體單元//有ds訪問過程
    • mov 記憶體單元 暫存器·//有ds訪問過程
    • mov 段暫存器 暫存器·//可以對ds進行這種操作
    • mov 暫存器 段暫存器
    • mov 記憶體單元 段暫存器//有ds訪問過程
    • mov 段暫存器 記憶體單元//有ds訪問過程
  • 資料段
    將一組大小在64KB之內的記憶體空間,專門用來存放資料,且有段地址。

push ax //直接將ax中的資料壓棧
    pop cx//將棧中最頂層資料彈出,並賦值給ax
入棧和出棧都是以字為單位進行的
任意時刻SS:SP指向棧頂元素,也就是說棧為空的時候SS:SP指向該段基礎地質的尾地址的後一位
入棧是從高地址到低地址。
push的時候,sp在減小,pop的時候,sp在增加
sp起始地址演算法,將棧最高地址加一

出棧後資料並沒有被銷燬,還在記憶體中,但已經不在棧中了。
特別注意:8086CPU沒有提供棧越界處理機制,需要我們自己程式設計時注意棧的使用。
push 暫存器
pop 暫存器
push 段暫存器
pop 段暫存器
push 記憶體單元
pop 記憶體單元

第四章 第一個程式

  • segment和ends是一對成對使用的偽指令,功能是定義一個段。segment前面是段名,ends前面也是段名。可以是一個程式碼段,用來存放程式碼。
  • 一個有意義的彙編程式,至少要有一個段。
  • 注意:ends是和segment成對使用的,而end表示一個程式的結束,一旦遇到end程式就停止編譯
  • assume假設的意思,將有特定用途的段和相關的暫存器關聯起來。
  • 段名將被編譯為一個段的段地址。
    abc這個段被當做程式碼段來處理,所以要將段暫存器cs和abc關聯起來
    assume cs:abc
  • 程式返回指令,類似於return
    mov ax, 4c00H
    int 21H
  • 語法錯誤容易發現,容易解決
    邏輯錯誤難發現

第五章 [bx]和loop指令

  • 要完整的描述一個記憶體單元,需要兩種資訊①記憶體單元的地址②記憶體單元的長度(資料型別)
  • [bx]表示一個記憶體單元,它的偏移地址在bx中
    指令
    mov al, [bx]
    將偏移地址為bx的記憶體單元中,大小為一個位元組的資料,取到al中。

  • ()的使用。括號內可以是①暫存器名②段暫存器名③記憶體單元的實體地址(一個20位資料)
    (X)表示的資料型別有兩種。位元組或字,跟據暫存器大小或者運算型別來決定

  • 用idata表示常量mov ax,idata 等

5.1 [bx]

一般在[]內可以放bx暫存器,而不放其他暫存器

5.2 loop

loop指令格式:loop 標號:
執行的時候有兩步
    ①(cx) = (CX)-1
    ②判斷cx中的值,若為零,則執行下一條指令,否則執行標號指向的指令。
loop執行迴圈,cx中存放迴圈次數
    要迴圈執行的程式碼和標號應該在loop指令的上面
    迴圈程式碼在標號和loop指令之間

    inc bx指令將bx中的資料加一

5.6段字首

可以顯式的指明段地址在哪個暫存器,若不指明則為預設暫存器
(1) mov ax,cs:[0]
(2) mov ax, ds:[2]
(3) mov ax,ss:[4]
(4) mov ax,es:[6]
(5) mov ax,cs:[bx]
其中cs:, ds:, ss:, es:稱為段字首
DOS環境下,一般在0:200~0:2ff空間中沒有系統的東西

第六章 包含多個段的程式

6.1在程式碼段中使用資料

dw,定義字型資料,define word
由於程式剛開始的時候,從程式碼段開始執行。所以CS存放著程式碼段的段地址。又dw在程
序的開始部分,所以可以直接用CS,來作為該部分資料的段地址,偏移地址為0.

用start和end start 來說明程式的入口,讓程式繞開資料段執行

6.2 在程式碼段中使用棧

直接在程式碼段中用dw開闢空間,然後將得到的空間當做棧來使用

6.3 將資料、程式碼、棧放入不同的段

用segment定義一個段,然後用段名來訪問這個段。例如
    data segment
    data ends 
    mov ax, data
    編譯的時候,data直接被編譯為一個地址數值
要用assume將相應暫存器指向對應的段
assume CS:code, ds:data, ss:stack

第七章 更靈活的定位記憶體地址的方法

7.1 and 和 or 指令

mov al, 11000110B
or al,1011010B

7.2 關於ASCII碼

7.3 以字元形式給出的資料

‘。。。。’這個形式在程式中表示字元型資料。
可以用db 'ddddd'這種形式定義字串

7.4大小寫的轉化

每個大寫字母和相應的小寫字母,相差20H.大寫字母加上20H,得到小寫字母
大於等於61H的字元是小寫字母
大小寫字母,除了第五位不一樣之外,其他各位都相同

7.5 [bx + idata]

mov ax,[bx+200]
mov ax,200[bx]
mov ax,[bx].200

7.6 用[bx+idata]的方法進行陣列的處理

利用了bx作為變數的性質

7.7 si和di

7.8 [bx + si]和[bx+di]

7.9 [bx+si+idata] 和[bx+di+idata]

可用格式:
    mov ax,[bx + si+200]
    mov ax,200[bx][si]
    mov ax, [bx].200[si]
    mov ax,[bx][si].200

7.10

注意:有兩層迴圈的時候,在第二層迴圈開始之前先要儲存第一層迴圈的cx,且儲存資料要用棧。

第八章 資料處理的兩個基本問題

reg表示一個暫存器,sreg表示一個段暫存器

8.1 bx,si,di,bp

(1)8086CPU中只能用這幾個暫存器儲存偏移地址,放在[....]中使用。
(2)在[...]中只能以如下幾種組合出現
        bx和si,bx和di,bp和si,bp和di。
        也就是說bx和bp,si和di不能同時出現
(3)只要在[...]中使用bp,且段地址沒有明確給出,那麼預設段地址在ss中。
        使用了bx的時候段地址預設在ds中

8.2機器指令處理的資料在什麼地方

mov ax,[0]//指令執行前資料在儲存器中
mov bx,ax//指令執行前資料在CPU內部暫存器ax中
mov ax,1//指令執行前資料在CPU緩衝器中

8.3組合語言中資料位置的表達

(1)立即數:直接包含在機器指令中
(2)暫存器:
(3)段地址(sa)和偏移地址(EA):資料在記憶體中

8.4定址方式

參見表

8.5指令要處理的資料有多長

(1)用暫存器說明,ax兩個位元組,al一個位元組
(2)用X ptr指明資料長度X為word或者byte。
    mov word ptr ds:[20],2
    add byte [bx],2
(3)其他方式
    push預設字操作

8.7 div指令

(1)除數:有8位和16位兩種,在一個reg或記憶體單元中
(2)被除數:放在ax或ax和dx中,若除數為8位,則被除數放在16位的ax中。若除數為16位,被除數高16位放在DX,低16位放在AX中
(3)結果:如果除數為8位,則AL存放除法操作的商,AH存放餘數。如果除數為16位,AX存放商,DX存放餘數。
所以除法只需要給出除數以及除數的位數
eg:div word ptr ds:[0]
    div byte ptr ds:[2]

8.8偽指令dd

dd用來定義雙字(double world)

8.9dup

表示重複
eg:db 3 dup (1,2,3)相當於db (1,2,3,1,2,3,1,2,3)

第九章 轉移指令的原理

9.1操作符offset

用來取得程式碼中標誌的偏移地址
    code segment
        start:mov ax,offset start;相當於mov ax,0
        s:mov ax,offset s;相當於mov ax,3

9.2jmp指令

9.3依據位移進行轉移的jmp指令

jmp short 標號
轉移到標號處的指令,且為短轉移,範圍為-128到127

9.4轉移的目的地址在指令中的jmp指令

jmp far ptr 標號。段間轉移,又稱為遠轉移。可以轉移的距離超過一個段的大小

9.5轉移地址在暫存器中的jmp指令

jmp 16位reg;注意只能是暫存器,不能是常數
(IP) = (16位reg)

9.6轉移地址在記憶體中的jmp指令

有兩種格式
(1)jmp word ptr 記憶體單元地址(段內轉移)
    jmp word ptr ds:[0]
(2)jmp dword ptr記憶體單元地址(段間轉移)
    功能,從指定位置開始,存放著兩個字。高地址處放的是段地址,低地址處放的是偏移地址。即:
    cs = (記憶體單元地址+2)
    IP = 記憶體單元地址

9.7 jcxz指令

有條件轉移指令,所有有條件轉移指令都是短轉移指令。
    指令格式:jcxz 標號(如果cx等於0,轉移到標號處執行)

9.8 loop指令

所有迴圈指令都為短轉移

第十章 CALL和RET指令

10.1 ret和retf

ret指令用棧中的資料修改IP的內容,從而實現近轉移
retf用棧中的資料修改CS和IP中的內容,從而實現遠轉移

10.2call指令

(1)將當前IP或CS和IP壓棧
(2)轉移
call指令不能實現短轉移

10.3 依據位移進行轉移的call指令

call 標號(將當前的IP壓棧後,轉到標號處執行指令

10.4 轉移的目的地址在指令中的call指令

call far ptr 標號(實現的是段間轉移)

10.5 轉移地址在暫存器中的call指令

call 16位reg

10.6 轉移地址在記憶體中的call指令

有兩種格式
(1)call word  ptr 記憶體單元地址 
(2)call dword ptr 記憶體單元地址

10.8 mul指令

乘法指令
(1)兩個相乘的數:要麼都是8位,要麼都是16位。如果都是8位,一個放在AL中,另一個放在8位reg或者記憶體單元中;如果是16位,一個預設放在AX中,另一個放在16位reg或者記憶體單元中
(2)結果:如果是8位乘法,結果預設放在AX中,如果是16位,那麼高16位放在DX中,低16位凡在ax中。

10.10引數和結果傳遞問題