1. 程式人生 > 實用技巧 >每日一題20201113(328. 奇偶連結串列)

每日一題20201113(328. 奇偶連結串列)

一、實驗目的 1. 理解和掌握將資料、程式碼、棧放入不同邏輯段的程式的編寫和除錯 2. 理解具有多個段的彙編源程式對應的目標程式執行時,記憶體分配方式 3. 掌握大小寫字元的轉換方法、數字字元和數值之間的轉換方法 4. 理解並掌握各種定址方式的靈活應用 5. 掌握彙編指令loop, and, or,div, mul的用法 二、實驗準備 複習教材chapter 6-8章。 chapter 6 包含多個段的程式 chapter 7 更靈活的定位記憶體地址的方法 chapter 8 資料處理的兩個基本問題 三、實驗內容 1. 實驗任務1 編寫task1.asm,這裡直接通過記事本寫入task1.asm放入masm資料夾裡
assume cs:code, ds:data
data segment
        db 
'Nuist' db 5 dup(2) //五個2 data ends code segment start: mov ax, data mov ds, ax mov ax, 0b800H mov es, ax mov cx, 5 mov si, 0 mov di, 0f00h s: mov al, [si] and al, 0dfh mov es:[di], al mov al, [5+si] mov es:[di
+1], al inc si add di, 2 loop s mov ah, 4ch int 21h code ends end start

理論分析

總體上是db前五個位元組“Nuist”字母變成大寫,再新增顏色值都為db後五個位元組綠色

        mov cx, 5             //設定迴圈次數
        mov si, 0             //偏移資料段ds偏移地址
        mov di, 0f00h         //設定es偏移地址
s:      mov al, [si]          //將ds:[si]資料傳入al
        and al, 0dfh          //與方法將字母變為大寫
mov es:[di], al //將大寫字母傳入es:[di],這裡實際存放的是資料 mov al, [
5+si] //將ds:[5+si]資料傳入al mov es:[di+1], al //將al傳入es:[di+1],這裡應該是改變大寫字母的顏色 inc si //ds偏移地址+1 add di, 2 //es偏移地址+2(一次迴圈填入兩個位元組) loop s //進入迴圈,cx-1
使用masm、link對task1.asm進行彙編、連結,得到可執行檔案task1.exe,執行並觀察結果。 使用debug工具對程式進行除錯,執行到程式返回前,即line27之前,觀察結果。 這裡u命令因為資料段用去了10個位元組,所以一共3b-20=2b個位元組

資料段前十位元組是Nuist和22222

實際在es:0f00 前10個位元組儲存的內容(這裡的內容(20?)不是太懂)

修改line4裡5個位元組單元的值,重新彙編、連結、執行,觀察結果。
assume cs:code, ds:data
data segment
        db 'Nuist'
        db 2,3,4,5,6
data ends

code segment
start:
        mov ax, data
        mov ds, ax

        mov ax, 0b800H
        mov es, ax

        mov cx, 5
        mov si, 0
        mov di, 0f00h
s:      mov al, [si]
        and al, 0dfh
        mov es:[di], al
        mov al, [5+si]
        mov es:[di+1], al
        inc si
        add di, 2
        loop s

        mov ah, 4ch
        int 21h
code ends
end start

分析:db後五個位元組23456,分別改變為不同顏色如上圖

2. 實驗任務2 已知資料段data中定義位元組資料如下:
data segment
     db 23,50,66,71,35
data ends
編寫程式,在螢幕上以十進位制整數形式列印輸出這5個兩位數。 提示: 1個兩位數如何輸出 思路如下: 具體處理步驟如下: 第1步,利用除法指令div,計算出每個數位上的數值。 第2步,利用數值和數字字元之間ascⅡ碼的關係,把數值→ 數字字元 第3步,利用系統功能呼叫int 21h中的2號子功能,輸出單個字元。 int 21h中的2號子功能說明如下: 功能:輸出單個字元 用法:
mov ah,2
mov d1,xxx        //xxx是待輸出的字元或者ASCLL碼值
int 21h
5個兩位數如何輸出 利用loop指令,以及,靈活的定址方式 編寫task2.asm
assume cs:code, ds:data
data segment
     db 23,50,66,71,35
data ends
code segment
start:

      mov ax,data
      mov ds,ax
      mov di,0
      mov cx,5
      
  s1:mov ah,0              //存放餘數
      mov al,ds:[di]
      mov bl,10
      div bl
      mov ds:[10+di],al    //存放十位上的數
      mov ds:[11+di],ah    //存放個位上的數
      //輸出十位上的數
      mov ah,2
      mov dl,ds:[10+di]
      add dl,30h           //轉化為ASCLL碼值
      int 21h
      //輸出個位上的數
      mov ah,2
      mov dl,ds:[11+di]  
      add dl,30h           //轉化為ASCLL碼值
      int 21h
      //輸出間隔符
      mov ah,2
      mov dl," "
      int 21h
      
      inc di
      loop s1
      
      
      mov ax,4c00h
      int 21h
code ends
end start

-u 0 39反彙編

-g 36迴圈結束,輸出

ds前五個位元組(原始資料)

ds:10h~ds:19h(分別存放原始資料十位和個位)

3. 實驗任務3 教材「實驗5 編寫、除錯具有多個段的程式」(1) 程式原始碼見task3.asm。
assume cs:code, ds:data, ss:stack
data segment
  dw 0123h, 0456h, 0789h, 0abch, 0defh, 0fedh, 0cbah, 0987h
data ends

stack segment
  dw 0, 0, 0, 0, 0, 0, 0, 0
stack ends

code segment
start:  mov ax,stack
        mov ss, ax
        mov sp,16
        
        mov ax, data
        mov ds, ax
        
        push ds:[0]
        push ds:[2]
        pop ds:[2]
        pop ds:[0]
        
        mov ax,4c00h
        int 21h

code ends
end start

debug除錯

反彙編-u 0 20

-g 1d(程式返回前)

1.data資料段內容是

0123h, 0456h, 0789h, 0abch, 0defh, 0fedh, 0cbah, 0987h

2.其中,cs=076ch,ss=076bh,ds=076ah

3.設程式載入後,code段的地址為X,則data段的段地址為X-2,stack段的段地址為X-1

4. 實驗任務4 教材「實驗5 編寫、除錯具有多個段的程式」(2) 程式原始碼見task4.asm。
assume cs:code, ds:data, ss:stack
data segment
  dw 0123h, 0456h
data ends

stack segment
  dw 0, 0
stack ends

code segment
start:  mov ax,stack
        mov ss, ax
        mov sp,16
        
        mov ax, data
        mov ds, ax
        
        push ds:[0]
        push ds:[2]
        pop ds:[2]
        pop ds:[0]
        
        mov ax,4c00h
        int 21h

code ends
end start

-g 1d(程式返回前)

1.data資料段內容是

0123h, 0456h

2.其中,cs=076ch,ss=076bh,ds=076ah

3.設程式載入後,code段的地址為X,則data段的段地址為X-2,stack段的段地址為X-1

4.對於如下的定義的段:

name segment
...
name ends

如果段中的資料佔N個位元組,則程式載入後,該段實際佔有的空間為(N/16+1)*16

5. 實驗任務5 教材「實驗5 編寫、除錯具有多個段的程式」(3) 程式原始碼見task5.asm。
assume cs:code, ds:data, ss:stack

code segment
start:  mov ax,stack
        mov ss, ax
        mov sp,16
        
        mov ax, data
        mov ds, ax
        
        push ds:[0]
        push ds:[2]
        pop ds:[2]
        pop ds:[0]
        
        mov ax,4c00h
        int 21h

code ends
data segment
  dw 0123h, 0456h
data ends

stack segment
  dw 0,0
stack ends
end start

debug除錯

-g 1d(程式返回前)

1.data資料段內容是

0123h, 0456h

2.其中,cs=076ah,ss=076eh,ds=076dh

3.設程式載入後,code段的地址為X,則data段的段地址為X+3,stack段的段地址為X+4

6. 實驗任務6 教材「實驗5 編寫、除錯具有多個段的程式」(4) 對前三個實驗最後一條偽指令“end starrt”改為“end”(不指明程式的入口),則拿個程式仍然可以正確執行?請說明原因。 task3

task4

task5

分析:

前2個都有錯誤,第3個成功了,原因應該是前2個將定義data和stack的內容放在了前面,有了start就從指定cs程式碼段開始,沒有start就出錯; 而第3個本來就是從程式碼段開始,所以去掉start沒有影響。 7. 實驗任務7 教材「實驗5 編寫、除錯具有多個段的程式」(5) 程式原始碼見task7.asm。 注*: 如果在整合軟體環境下編寫、彙編這個實驗任務,請將段名為c的邏輯段,名稱改為c1或別的識別符號。由於早期一些指令集中使用c指代暫存器,如不更正,有些彙編器在彙編時會報錯。
assume cs:code
a segment
  db 1,2,3,4,5,6,7,8
a ends

b segment
  db 1,2,3,4,5,6,7,8
b ends

c segment   
  db 8 dup(0)
c ends

code segment
start:
       mov ax,a
       mov ds,ax
       mov bx,0
       mov cx,8
       s:mov al,[bx]
       add al,[16+bx]
       mov [32+bx],al
       inc bx
       loop s
       mov ax,4c00h
       int 21h
code ends
end start

debug除錯

先檢視c裡的資料

執行完再次檢視

成功執行a+b->c

8. 實驗任務8 教材「實驗5 編寫、除錯具有多個段的程式」(6) 程式原始碼見task8.asm。
assume cs:code
a segment
  dw 1,2,3,4,5,6,7,8,9,0ah,0bh,0ch,0dh,0eh,0fh,0ffh
a ends

b segment
  dw 8 dup(0)
b ends

code segment
start: 
    mov ax,a
    mov ds,ax
    mov bx,0
    
    mov ax,b
    mov ss,ax
    mov sp,10h
    
    mov cx,8
    s:push [bx]
    add bx,2
    loop s

    mov ax,4c00h
    int 21h
code ends
end start

debug除錯

先檢視b裡內容

執行完再次檢視b中內容

成功將前8個字型資料存入棧即b內

總結

1.瞭解了包含多個段的程式的結構

2.理解了start的用法以及程式碼段資料段先後的關係

3.瞭解了資料段設定位元組數預設以16位元組為單位