實驗5 編寫、調試具有多個段的程序


一、預備知識

ps:這一章我同樣不分開做知識點總結了,一個是因為覺得能力不夠,沒有那么多的發現,而且掌握也不算好,還有一點是現在時間不夠,每一次作業都要花好久的時間

(1)dw:字型數據;db:字節型數據

(2)如果代碼和數據放在一個段中,反匯編時,如果從0開始,會把數據當成指令機器碼反匯編,所以反匯編時注意sp的值

(3)8086CPU不允許將一個數值直接送入段寄存器中

(4)調試時,可以通過r命令修改ip的值或在t/g命令中指定執行的起始地址

(5)end 標號:表示程序到標號處開始,到此結束,后面的標號有時候可以省略

(6)使用assume僅僅表示將某個邏輯段和某個段寄存器關聯起來;真正當做特定的段使用,需要在代碼段中設置相應的段寄存器值

 

二、實驗任務

1、將下面的程序編譯、連接、,用debug加載、跟蹤,然后回答問題

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

先用r查看各寄存器的值,CX的值為42h,前面的數據一共用了20h,剩下的一共是22h,從0~21h

接着用g命令多步執行,到程序返回前停下,所以用g 001d,接着查看data段中的數據

 

(1)CPU執行程序,程序返回前,data段中的數據為多少?

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

(2)CPU執行程序,程序返回前,cs=0772h,ss=0771h,ds=0770h

(3)設程序加載后,code段的段地址為X,則data段的段地址為X-2,stack段的段地址為X-1

 

2、將下面的程序編譯、連接,用debug加載、跟蹤,然后回答問題

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

這個程序和上面的程序一樣的方法調試

 

(1)CPU執行程序,程序返回前,data段中的數據為多少?

0123h,0456h

(2)CPU執行程序,程序返回前,cs=0772h,ss=0771h,ds=0770h

(3)設程序加載后,code段的段地址為X,則data段的段地址為X-2,stack段的段地址為X-1

(4)對於如下定義的段:

name segment

……

name ends

如果段中的數據占N個字節,則程序加載后,該段實際占有的空間為((N+15)/16)*  16

ps:這道題我確實無從下手,不知道是該怎么處理,最后沒辦法,去查了一下

N分為被16整除和不被16整除。

當N被16整除時: 占有的空間為(N/16)*16

當N不被16整除時: 占有的空間為(N/16+1)*16,N/16得出的是可以整除的部分,還有一個余數,余數肯定小於16,加上一個16。

程序加載后分配空間是以16個字節為單位的,也就是說如果不足16個字節的也分配16個字節。

兩種情況總結成一個通用的公式:((N+15)/16)*16 

 

3、將下面的程序編譯、連接,用debug加載、跟蹤,然后回答問題

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

這個程序和上面的程序一樣的方法調試

 

(1)CPU執行程序,程序返回前,data段中的數據為多少?

0123h,0456h

(2)CPU執行程序,程序返回前,cs=0772h,ss=0774h,ds=0773h

(3)設程序加載后,code段的段地址為X,則data段的段地址為X+3,stack段的段地址為X+4

 

4、如果將(1)、(2)、(3)題中的最后一條偽指令“end start”改為“end”(也就是說,不知名程序的入口),則哪個程序仍然可以正確執行?請說明原因

(3)可以,(1)、(2)的開始都是數據段,而(3)的開始是指令

(1)、(2)如果直接執行,機器會把數據當成指令才執行,而(3)指令的一開始偏移地址就是0,直接執行不會有問題

 

5、程序如下,編寫code段中的代碼,將a段和b段中的數據依次相加,將結果存到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

c1 segment

      db 0,0,0,0,0,0,0,0

c1 ends

code segment

start:

???

code ends

end start

 

源代碼:

 

接着,調試一下,看看能不能達到預期的效果

在實現數據相加前,邏輯段c中放的是原本的數據

很明顯,最后數據的確相加了,而且存在了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

c1 segment

      db 0,0,0,0,0,0,0,0

c1 ends

code segment

start:     mov ax,c1

            mov es,ax

            mov ax,b

            mov ds,ax

            mov ax,a

            mov ss,bx //問題出在這里,不應該是ss,bx,而應該是ss,ax

            mov bx,0

            mov cx,8

           

s:          mov al,ds:[bx]

            add al,ss:[bx]

            mov es:[bx],al

            inc bx

            loop s

           

            mov ax,4c00h

            int 21h

code ends

end start

我在調試的時候才發現這個程序的問題

前面都沒有什么問題,直到我用d命令查看寄存器的值的時候,很奇怪,為什么這個數據是這個樣子的

我看了一下到程序返回前各寄存器的值,一看,ss的值還是0,也就是說,數據段中的數據並沒有到棧段中去

而那些數據都是操作系統自己的數據

因此,我去看了一下程序,問題出在我上面標出來的那一行

改過來之后程序就沒有問題了

 

6、程序如下,編寫code段中的代碼,用push指令將a段中的前8個字型數據,逆序存儲到b段中

assume cs:code

a segment

      dw 1,2,3,4,5,6,7,8,9,0ah,0bh,0ch,0dh,0dh,0fh,0ffh

a ends

b segment

      dw 0,0,0,0,0,0,0,0

b ends

code segment

start:    

???

code ends

end start

 

源代碼:

這個代碼是借鑒了書上P133頁的代碼

下面是調試過程:

這里是在push操作執行前,查看邏輯段b的8個子單元

在程序返回前,再次查看邏輯段b的8個子單元

最后實現了逆序存儲

 

總結:

(1)當提到逆序存儲的時候,可以利用棧的先進后出的特點來實現這個問題

(2)可以利用寄存器cx的值來進行精確反匯編,同時可以用反匯編得到的偏移地址的值進行多步執行

(3)當程序達不到自己想要的結果時,可以通過單步執行來尋找問題,也可以利用寄存器的值來尋找問題

(4)要看清楚給的數據是字型數據還是字節型數據,用相應的寄存器去實現題目的問題

(5)前面的幾個程序,由每個段寫的位置可見,代碼段,數據段和棧段的段地址之間存在一定的關系


免責聲明!

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



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