每日一題20201113(328. 奇偶連結串列)
阿新 • • 發佈:2020-11-20
一、實驗目的
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 //與方法將字母變為大寫使用masm、link對task1.asm進行彙編、連結,得到可執行檔案task1.exe,執行並觀察結果。 使用debug工具對程式進行除錯,執行到程式返回前,即line27之前,觀察結果。 這裡u命令因為資料段用去了10個位元組,所以一共3b-20=2b個位元組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
資料段前十位元組是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 21h5個兩位數如何輸出 利用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”(不指明程式的入口),則拿個程式仍然可以正確執行?請說明原因。 task3task4
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
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位元組為單位