1. 程式人生 > 實用技巧 >M個蘋果分給N個人,沒人至少一個,有多少種分法?

M個蘋果分給N個人,沒人至少一個,有多少種分法?

一、實驗目的

1. 理解和掌握將資料、程式碼、棧放入不同邏輯段的程式的編寫和除錯

2. 理解具有多個段的彙編源程式對應的目標程式執行時,記憶體分配方式

3. 掌握大小寫字元的轉換方法、數字字元和數值之間的轉換方法

4. 理解並掌握各種定址方式的靈活應用

5. 掌握彙編指令loop, and, or,div, mul的用法

二、實驗準備

複習教材chapter 6-8章。

chapter 6 包含多個段的程式

chapter 7 更靈活的定位記憶體地址的方法

chapter 8 資料處理的兩個基本問題

三、實驗內容

1. 實驗任務1

使用任意文字編輯器,錄入彙編源程式task1.asm。

assume cs:code, ds:data
data segment
db 'Nuist'
db 5 dup(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

閱讀源程式,從理論上分析原始碼的功能,尤其是line15-25,迴圈實現的功能是什麼,逐行理解每條指 令的功能。

使用masm、link對task1.asm進行彙編、連結,得到可執行檔案task1.exe,執行並觀察結果。

使用debug工具對程式進行除錯,執行到程式返回前,即line27之前,觀察結果。

修改line4裡5個位元組單元的值,重新彙編、連結、執行,觀察結果。

db 5 dup(2)
--> 改成:
db 2,3,4,5,6

基於觀察,分析、猜測這裡的數值作用是什麼

對檔案進行編譯、連線

debug後用u命令反彙編

用g命令執行到程式返回前

修改line4資料後

line4的作用是控制字元的顏色屬性

2. 實驗任務2

已知資料段data中定義位元組資料如下:

data segments
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 dl, ×× ; ××是待輸出的字元,或其ASCⅡ碼值
int 21h

5個兩位數如何輸出 利用loop指令,以及,靈活的定址方式

ds的偏移地址設為[10+di]的目的是保證原有資料不被覆蓋。

執行結果:

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

  1. CPU執行程式,程式返回前,data段中資料為多少?

    data段資料為:0123h,0456h,0789h,0abch,0defh,0fdeh,0cbah,0987h

  2. CPU執行程式,程式返回前,cs=076C、ss=076B、ds=076A

  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

  1. CPU執行程式,程式返回前,data段中資料為多少?     data段資料為0123h,0456h
  2. CPU執行程式,程式返回前,cs=076C、ss=076B、ds=076A
  3. 設程式載入後,code段的段地址為X,則data段的段地址為X-2,stack段的段地址為X-1
  4. 對於如下定義的段:
name segment

......

name ends

如果段中的資料佔N個位元組則程式載入後,該段實際佔有的空間為:(N/16+1)*16。(分配空間為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

  1. CPU執行程式,程式返回前,data段中資料為多少?     data段資料為0123h,0456h
  2. CPU執行程式,程式返回前,cs=076A、ss=076E、ds=076D
  3. 設程式載入後,code段的段地址為X,則data段的段地址為X+3,stack段的段地址為X+4

6.實驗任務6

如果將(1)、(2)、(3)題中的最後一條偽指令“end start”改為“end”(也就是說不指明程式的入口),則哪個程式可以正常執行?說出原因?

(3)可以正常執行,(3)題三開頭為程式碼段,不需要指明入口,而(1)(2)不指明入口會將資料段當作指令執行

7. 實驗任務7

教材「實驗5 編寫、除錯具有多個段的程式」(5) 程式原始碼見task7.asm。

程式碼:

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 cx,8
      mov bx,0

s:    mov al,[bx]
      add al,[bx+10h]
      mov [bx+20h],al
      inc bx
      loop s

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

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 ax,b
      mov ss,ax
      mov sp,16
      mov si,0

       mov cx,8

 s:   push ds:[si] 
      add  si,2
      loop s
      mov ax,4c00h
      int 21h
code ends
end start