8086匯編語言學習(六) 8086處理結構化數據(模擬高級語言結構體、數組)


一、8086匯編定義數據

  要處理結構化數據,必須先定義數據。8086匯編作為一門編程語言,定義數據的方式比起復雜的高級語言要簡單不少。

  匯編語言貼近機器底層,所處理的數據邏輯上都可以視為二進制數據,按照對不同大小內存單元的處理,分為三種:db、dw、dd

1.db

  db 即define byte,定義一個字節變量。例如 db 1h,代表着db指令后的值占用一個字節的內存空間 1h=>01h。

  特別的,使用db可以比較簡單的定義字符串數據,例如db "ABC",代表着定義A、B、C三個連續的字符。

2.dw

  db 即define word,定義一個字變量。例如 dw 1h,代表着dw指令后的值占用一個字/兩個字節的內存空間 1h=>0001h。

3.dd

  dd 即define doubleword,定義一個雙字變量。例如 dd 1h,代表着dw指令后的值占用兩個字/四個字節的內存空間 1h=>0000 0001h。

  在連續定義數據時,可以通過逗號進行縮寫。例如 db 1h,2h,3h等價與db 1h;db 2h;db 3h。

  同時上述三種方式都可以與dup關鍵字(duplicate)使用。例如,定義3個值為1h的字形數據,可以寫為dw 3 dup(1h),其等價於dw 1h,1h,1h。在定義復數個相同的數據時,可以簡化程序,增強可讀性。

  db、dw、dd、dup都屬於8086匯編的偽指令,由匯編器在編譯時進行處理,並沒有對應的機器指令。

二、8086匯編處理結構化數據

  之前介紹了8086各種不同方式的內存尋址方式,下面介紹8086如何利用這些多樣的尋址方式來處理結構化的數據。

  舉一個簡單的例子,假設存在一個結構化的數據(公司),擁有五個屬性。

公司屬性:

  公司名稱: BLZ
  總裁名稱: Deckard Cain
  公司排名: 15
  年收入(億元): 50
  產品: WOW

  需求是,在內存中定義該數據並且對其中的部分屬性進行修改,將公司排名修改為10,年收入修改為80,產品名稱修改為OWO。

 整理思路后的偽代碼:

  1. 先按照順序在內存中存放對應的數據結構

  2. 找到公司排名所在的內存地址,將其修改(偏移地址 0Fh)  

  3. 找到年收入所在的內存地址,將其修改(偏移地址 11h)

  4. 找到產品所在的內存地址(14h),並將產品名稱字符串中的字符逐一修改 

    令P=0h
    修改13h+P處的字符
    P=P+1h
    修改13h+P處的字符
    P=P+1h
    修改13h+P處的字符

  

根據上述偽代碼,寫出對應匯編程序:

assume cs:codesg,ds:data

data segment
    db "BLZ","Deckard Cain"; 定義公司名稱、總裁名稱
    dw 15h,50h;  定義排名、年收入
    db "WOW";  定義產品名稱
    data ends

codesg segment

    start:    
       mov ax,data;
        mov ds,ax; 設置段基址為data
        mov bx,0h; 設置數據在段中的起始位置為0h

        mov word ptr [bx+0Fh],10h;  修改排名所在的字數據為10
        mov word ptr [bx+11h],80h;    修改收入所在的子數據為80

        mov si,0;    引入si變量,遍歷產品名稱
        mov byte ptr [bx+13h+si],'O';    第一個字符設置為0
        inc si;        si自增1,bx+idata+si 指向下一個字符
        mov byte ptr [bx+13h+si],'M';    第二個字符設置為M
        inc si;        si自增1,bx+idata+si 指向下一個字符
        mov byte ptr [bx+13h+si],'O';    第三個字符設置為0
            
        mov ax,4c00H;
        int 21H;

    codesg ends

end start

   如果用C這種較高級的語言來實現,則簡單很多。

用C語言的結構體表示為:

struct company{
    char cname[3];
    char hname[12];
    int rank;
    int income;
    char product[3];
}    

用C語言實現需求:

struct company blz={"BLZ","Deckard Cain",15,50,"WOW"} // 定義數據
    int i;
    blz.rank=10; // 修改排名
    blz.income=80; // 修改收入
    i=0;
    blz.product[i] = 'O'; // 修改產品名稱
    i++;
    blz.product[i] = 'M';
    i++;
    blz.product[i] = 'O';
}    

  通過對比,可以清楚看到,C語言的實現比起匯編要來的輕松和簡潔許多。8086匯編提供了指定偏移地址的語法糖,使得尋址時的程序更像高級語言,可讀性更高。

將上述的匯編程序以類似C語言的風格進行部分重構:

assume cs:codesg,ds:data

data segment
    db "BLZ","Deckard Cain";
    dw 15h,50h;
    db "WOW";
        data ends

codesg segment

    start:    
        mov ax,data;
        mov ds,ax; 設置段基址為data
        mov bx,0h; 設置數據在段中的起始位置為0h

        mov word ptr [bx].0fh,10h;  修改排名所在的字數據為10
        mov word ptr [bx].11h,80h;    修改收入所在的子數據為80

        mov si,0;    引入si變量,遍歷產品字段
        mov byte ptr [bx].13h[si],'O';     第一個字符設置為0
        inc si;        si自增1,bx+idata+si 指向下一個字符
        mov byte ptr [bx].13h[si],'M';        第二個字符設置為M
        inc si;        si自增1,bx+idata+si 指向下一個字符
        mov byte ptr [bx].13h[si],'O';        第三個字符設置為0
            
        mov ax,4c00H;
        int 21H;

        codesg ends

end start        

  主要是對數據內存尋址的方式進行了重構。這里的ds:[bx]相當於C程序中的變量blz,[bx].0fh相當於blz的屬性rank,而[bx].11h則相當於blz的屬性income。

  [bx].14h相當於blz的屬性product,[bx].14h[si]相當於product字符數組中的某一字符項。

  使用類似高級語言語法的尋址方式優化過后的匯編程序,比標准化的尋址方式更易理解,減少了程序出錯的可能性。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM