文章目錄
- 實驗報告
- 實驗三 子程式彙編實驗學習和提高
-
- 彙編語言中的 ASSUME 僞指令和标準的彙程式設計式
- 1. 複習 Debug -P 和 -G
- 2. 将鍵盤上輸入的十六進制數轉換成十進制數,并在螢幕上顯示
- 3. 較為複雜的彙編執行個體學習:判斷該年是否為閏年
- 4. 彙編執行個體學習和改進:兩位數加法
- 【基礎學習】
-
- 棧的定義
- 顯示提示資訊方法
- 鍵盤輸入方式
-
- 從鍵盤輸入一個字元串到緩沖區(AH=0AH)
- mul 乘法指令
- 實驗心得
- 【程式欣賞】
實驗報告
課程名稱:微處理器原理與應用
實驗名稱:CPUHomework3
實驗時間:2022年10月16日
實驗三 子程式彙編實驗學習和提高
彙編語言中的 ASSUME 僞指令和标準的彙程式設計式
ASSUME僞指令,通知彙程式設計式(編譯器)代碼段,資料段,附加段以及堆棧段選擇什麼名字
沒有 ASSUME 僞指令時,彙程式設計式假設不分段,并自動把段超越字首用于所有所有尋址存儲器資料的僞指令
ASSUME 語句隻能用于完整的段定義, ASSUME 不是彙編指令,僅僅是寫給編譯軟體的,是讓編譯器知道我的程式的各個段的名字,并不産生機器碼
ASSUME 僞指令是指明變量與段寄存器的聯系,如 ASSUME DS:DATAS, 告訴編譯器以後所有在 DATAS 段中定義的變量尋址時,使用DS作為段位址,但是其不對程式作任何事(僞指令),我們必須自己對DS指派
是以,要讓機器知道實際的段位址,還需要 MOV AX,DATAS MOV DS,AX 告訴CPU資料段的位址
标準格式:
DETAS SEGMENT
;
DATAS ENDS
STACKS SEGMENT
;
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
MOV AX,DATAS
MOV DS,AX ; 告訴CPU資料段的位址
...
; 此處輸入代碼段代碼
...
MOV AH,4CH
INT 21H
CODES ENDS
END START
1. 複習 Debug -P 和 -G
debug中P指令與T指令的差別
-
P和T都是執行,像 add ax, bx,不管用哪個,都是執行此語句
但如果是 call next, next是一個程式段,那麼用P直接就把這段程式執行完,用T則進入内部一句一句執行(與C語言的調試一樣,有的進入函數内部,有的執行完函數)
- T(跟蹤)指令:執行以 cs:ip 開始的一個或幾個指令,并顯示出執行每條指令後所有寄存器中的内容
P 執行循環、重複的字元串指令、軟體中斷或子例程
執行指令 G
G [=<位址>[,<斷點>]]
等價于:
G
G=<位址>
G=<位址>,<斷點>
功能:執行記憶體中的指令序列
1. 從 CS:IP 所指出開始執行
2. 從指定位址開始執行
3. 從指定位址開始執行,到斷點自動停止
2. 将鍵盤上輸入的十六進制數轉換成十進制數,并在螢幕上顯示
編寫程式,詳細注釋并畫程式流程圖
代碼如下:
data segment ; 定義資料段
infon db 0dh,0ah,'Please input a hexadecimal number: $' ; 聲明空間存儲輸入提示資訊,其中0d回車,0a換行
wrong db 0dh,0ah,'Please input a valid hexadecimal number: $ is wrong' ; 報錯
data ends
stack segment stack
dw 10 dup(?)
stack ends ; 定義一個棧,有10個字的空間
code segment
assume cs:code,ds:data,ss:stack
start:
mov ax,data
mov ds,ax ; 将資料段的位址交給ds
lea dx,infon ; 使用lea将infon中的内容交給dx,進而在螢幕上顯示提示資訊
mov ah,09h ; 将09h交給ah
int 21h ; 輸出提示資訊
mov bx,0
input:
mov ah,01h
int 21h ; 從鍵盤上輸入一個字元,将之對應的ASCII碼交給al,并在螢幕上顯示
add dx,1
cmp al,0dh
je z ; 如果相等,則跳轉到zz
judge:
cmp al,'f' ; 比較輸入字元與'f'的ASCII碼大小
ja err ; 無符号大于跳轉到err
cmp al,'a'
jnb branch1 ; 無符号不小于跳轉到branch1
cmp al,'F'
ja err ; 無符号大于跳轉到err
cmp al,'a'
jnb branch2 ; 無符号不小于跳轉到branch2
cmp al,'9'
ja err
cmp al,'0'
jnb branch3 ; 同理
jmp err
err: ; 報錯
lea dx,wrong
mov ah,09h
int 21h ; 輸出提示語句
jmp input ; 跳轉,重新輸入
branch1:
sub al,57h ; a~f, al-57h
jmp tran
branch2:
sub al,37h ; A~F, al-37h
jmp tran
branch3:
sub al,30h ; 0~9, al-30h
jmp tran
tran:
add dx,1
mov ah,0h
je input
mov cx,04h ; 循環次數為4
shift: rol bx,1 ; bx左移4位
loop shift
add bx,ax
jmp input
z:
mov ax,bx
mov bx,10
mov cx,0
cir:
mov dx,0
add cx,1
div bx
push dx
cmp ax,0
jne cir
fin:
pop ax ; 餘數出棧
mov dl,al ; al的資料交給dl準備輸出
add dl,30h ; 餘數在1~9之間,al + 30
mov ah,2
int 21h ; 輸出十進制數
loop fin ; 根據cx的值進行循環輸出
jmp stop
stop:
mov ah,4ch
int 21h
code ends
end start
ROL:循環左移指令
ROL BX, 1 ; 将BX的二進制數全部左移1位,原最高位移入最低位,且複制至進位标志CF
例如,BX原值 =1100 1111 0000 0000 , CF=0
ROL BX, 1 結果: BX=1001 1110 0000 0001 , CF=1
流程圖**(流程圖格式使用預設)**如下:
具體代碼測試結果如下:
3. 較為複雜的彙編執行個體學習:判斷該年是否為閏年
通過注釋重點學習并了解程式,活出程式流程圖,在了解的基礎上可自行修改
代碼如下:
示例程式
data segment ; 定義資料段
infon db 0dh,0ah,'Please input a year: $' ; 聲明空間存儲輸入提示資訊,其中0d回車,0a換行
Y db 0dh,0ah,'This is a leap year! $' ; 聲明空間存儲的是閏年提示資訊,同上另起一行輸出
N db 0dh,0ah,'This is not a leap year! $' ; 聲明空間存儲不是閏年提示資訊,同上另起一行輸出
w dw 0 ; 聲明空間存儲輸入年份解析後生成的年份數字
buf db 8
db ?
db 8 dup(?) ; 聲明空間作為緩沖區,總共10個位元組,第一個表示準備接收的字元數,即8
; 第二個表示實際接受的字元數,初始為空(?)
; 後面8個位元組作為緩沖接收字元,後兩行知識做初始化工作
data ends
stack segment stack
db 200 dup(0)
stack ends ; 定義一個棧,200位元組
code segment
assume ds:data,ss:stack,cs:code
start: mov ax,data
mov ds,ax ; 指定資料段
lea dx,infon ; 在螢幕上顯示提示資訊
mov ah,9
int 21h ; 将infon開始的字元串輸出到螢幕
lea dx,buf ; 從鍵盤輸入年份字元串
mov ah,10
int 21h
mov cl,[buf+1] ; 擷取實際輸入長度
mov ch,0 ; 保證cx的值為[buf+1]對應位元組的值
lea di,buf+2 ; 擷取字元串首位址
call datacate ; 調用子程式,将輸入字元串轉化為年份數字
call ifyears ; 調用子程式,判斷是否是閏年
jc a1 ; 如果進位标記C為1則跳轉到a1
lea dx,n ; 否則輸出不是閏年的資訊
mov ah,9
int 21h
jmp exit
a1: lea dx,y ; 輸出是閏年的資訊
mov ah,9
int 21h
exit: mov ah,4ch ; 程式結束
int 21h
datacate proc near ; 指明該子程式在主程式段内
push cx ; 備份cx
dec cx ; cx自減1,保證下面的循環使si指向最後一個字元(buf中回車符前面的一個)
lea si,buf + 2 ; 将buf中第一個字元(及buf中第三個位元組資料)的位址賦給si
tt1: inc si ; 循環,使得si指向最後一個字元(即buf中回車符前面的一個)
loop tt1
pop cx ; 回複cx
mov dh,30h ; 輔助資料,用來将數字字元對應的ASCII碼轉換為其代表的數字本身
mov bl,10 ; 輔助資料,用來在每進一位時使得ax乘以10
mov ax,1 ; ax用來裝對應位的權值
l1: push ax ; 備份ax
push bx ; 備份bx
push dx ; 備份dx,下面的dx将接收乘法運算結果的高位(實際上本例中沒有任何作用,因為乘法結果不會超過ax表示的範圍)
; 之是以需要是因為有時乘數(某些權值)需要用兩個位元組來表示
sub byte ptr [si],dh ; 将的那個字元轉換為對應的數字
mov bl, byte ptr [si] ; 擷取該位數字
mov bh,0 ;因為 1. 我們要用兩個個位元組裝對應位的數字 2. 該數字不會超過一個位元組表示的範圍
mul bx ; 将該位數字乘以相應的權值,結果存儲在ax中,我們預定年份最大值不超過兩個位元組表示的範圍
add [w],ax ; 加到結果上(易知當所有位都加完時,即是我們想要的年份數字)
pop dx ; 恢複dx
pop bx ; 恢複bx
pop ax ; 恢複ax
mul bl ; 權值乘以10
dec si ; si指向更高一位數字
loop l1
ret ; 子程式傳回
datacate endp
ifyears proc near ;指明該子程式段在主程式段内,該子程式用于檢測是否是閏年,接收年份資料,改變c标記位表示不同結果
push bx ; 備份bx
push cx ; 備份cx,下面cx用于存儲原始年份資料
push dx ; 備份dx,下面dx用于存儲除法餘數
mov ax,[w] ; 擷取年份資料
mov cx,ax ; 将年份資料備份到cx,因為後面做除法時ax值将會改變
mov dx,0 ; 因為被除數要為32位元組,高位在dx,本程式中為0
mov bx,100 ; 這三行半段是否能被100整除
div bx
cmp dx,0
jnz lab1
mov ax,cx
mov bx,400
div bx
cmp dx,0
jz lab2 ;若能表示是閏年,跳轉到lab2
clc ; 否則不是閏年,将c标記位清零,并跳轉到lab3
lab1:mov ax,cx ; 不能被100整除時跳轉到此處,進一步判斷能否被4整除
mov dx,0
mov bx,4
div bx
cmp dx,0
jz lab2 ; 若不能被100整除但能被4整除時閏年,跳轉到lab2
clc ; 若不能被100整除也不能被4整除不是閏年,将c标志位置零,并跳轉到lab3
jmp lab3
lab2:stc ; 若是閏年跳轉到此處将c标志位置1
lab3: pop dx ; 相應寄存器恢複
pop cx
pop bx
ret ; 子程式傳回
ifyears endp
code ends
end start
流程圖如下:
複習一下:
加載有效位址(load effective address)指令就是lea,他的指令形式就是從記憶體讀取資料到寄存器,但是實際上他沒有引用記憶體,而是将有效位址寫入到目的的操作數,就像是C語言位址操作符&一樣的功能,可以擷取資料的位址
jc,如果CF = 1,則跳轉至指定位置
jnc,如果CF = 0,則跳轉
CF為進位或借位辨別符,被運算結果所影響
4. 彙編執行個體學習和改進:兩位數加法
學習和改程序式
不斷改造,能力進步
示例: 求和 3 + 5
datas segment
five db 5 ; 定義five為值為5的位元組變量
datas ends
stacks segment
db 128 dup(?) ; 定義一個128位元組的棧空間
stacks ends
codes segment
assume cs:codes,ds:datas,ss:stacks
start: ; 主程式
mov ax,datas ; 段位址交給段寄存器
mov ds,ax
mov al,five ; 将5交給al
add al,3 ; al與3相加并将結果交給al
add al,30h ; al與30h相加,得到ASCII碼
mov dl,al ; 将ASCII碼交給dl準備輸出
mov ah,2
int 21h ; 輸出dl
mov ah,4ch
int 21h ; 傳回DOS
codes ends ; 代碼段結束
end start ; 程式結束
上面的程式是在程式内部定義的資料,以下改進可以使之從鍵盤輸入
start:
mov ax,datas
mov ds,ax
mov bl,five
mov ah,1
int 21h
add al,bl
mov dl,al
mov ah,2
int 21h
顯然這樣不夠完善,能否實作輸入兩個變量,然後相加,我們可以使用以下代碼
data segment
x db 0
y db 0
info db 0dh,0ah,'Please input a number: $'
info2 db 0dh,0ah,'Please input another number: $'
adds db '+$'
res db '=$'
data ends
stack segment
db 128 dup(?)
stack ends
code segment
assume cs:code,ds:data,ss:stack
start:
mov ax,data ; 将data的段位址交給ds
mov ds,ax
lea dx,info ; 在螢幕上顯示提示資訊
mov ah,9
int 21h ; 将infon開始的字元串輸出到螢幕
mov ah,1
int 21h ; 從鍵盤上輸入字元
sub al,30h ; al的值-30h,轉換為對應的數字
mov x,al
lea dx,adds
mov ah,9
int 21h ; 輸出
lea dx,info2 ; 在螢幕上顯示提示資訊
mov ah,9
int 21h ; 将infon2開始的字元串輸出到螢幕
mov ah,1
int 21h ; 從鍵盤上輸入字元
sub al,30h ; al的值-30h,轉換為對應的數字
mov y,al
lea dx,res
mov ah,9
int 21h
mov al,x
add al,y
add ax,30h ; 将ax的值+30h轉換為對應的ASCII碼
mov dl,al
mov ah,2
int 21h
mov ah,4ch
int 21h
code ends
end start
運作結果如下:
但顯然不能輸入和輸出兩位數:
接下來編寫兩位數求和的程式代碼
data segment
info1 db 0dh,0ah,'Enter the first number: $'
info2 db 0dh,0ah,'Enter the second number: $'
info3 db 0dh,0ah,'Sum is: $'
buf1 db 8
db ?
db 8 dup(?) ; 聲明空間作為緩沖區,總共10個位元組,第一個表示準備接收的字元數,即8
; 第二個表示實際接受的字元數,初始為空(?)
; 後面8個位元組作為緩沖接收字元,後兩行知識做初始化工作
buf2 db 8
db ?
db 8 dup(?)
data ends
stack segment stack
db 128 dup(?) ; 定義一個128位元組的棧空間
stack ends
code segment
assume cs:code,ds:data,ss:stack
start:
mov ax,data
mov ds,ax
lea dx,info1
mov ah,9
int 21h
lea dx,buf1
mov ah,0ah
int 21h ; 輸入一個兩位數
mov bl,[buf1 + 2] ; 将十位交給bl
sub bl,'0' ; 轉ASCII碼為數字
mov bh,[buf1 + 3] ; 将個位交給bh
sub bh,'0' ; 同理轉為數字
lea dx,info2
mov ah,9
int 21h
lea dx,buf2
mov ah,0ah
int 21h ; 輸入第二個兩位數
lea dx,info3 ; 輸出結果
mov ah,9
int 21h
mov cl,[buf2 + 2] ; 将十位交給cl
sub cl,'0'
mov ch,[buf2 + 3] ; 将個位交給ch
sub ch,'0'
add bl,cl ; 十位相加
add bh,ch ; 個位相加
cmp bh,10 ; 考慮進位
jge carry1 ; 大于等于則進位
jmp carry2
carry1:
sub bh,10 ; 個位減10
add bl,1 ; 十位進1
jmp carry2 ; 判斷十位
carry2:
cmp bl,10
jge carry3 ; 大于等于則進位
jmp fin
carry3:
sub bl,10 ; 十位減10
mov dl,31h
mov ah,02h
int 21h
jmp fin
fin:
mov dl,bl
add dl,30h
mov ah,02h
int 21h ; 将十位的值轉化為ASCII碼并交給dl并輸出
mov dl,bh
add dl,30h
mov ah,02h
int 21h ; 将個位的值轉化為ASCII碼并交給dl并輸出
mov ah,4ch
int 21h ; 傳回DOS
code ends
end start
最終流程圖如下:
運作結果如下:
進位也沒有問題
【基礎學習】
棧的定義
db 位元組 dw 字 DUP(duplicate) 重複
DB (define byte) : 定義一個位元組類型的變量,其後的每個操作數均占用1個位元組
DW (define word): 定義一個字類型的變量,其後的每個操作數均占用1個字(2個位元組)
DD (define doubleword): 定義一個雙字類型的變量,其後的每個操作數均占用2個字(4個位元組)
DQ (define quadword): 定義一個四字類型的變量,其後的每個操作數
DT (define ten bytes): 定義一個十位元組類型的變量,其後的每個操作數占用5個字(10個位元組)
比如
stack segment stack
db 200 dup(0)
stack ends ; 定義一個棧,200位元組
STACKS SEGMENT STACK ; 棧段
DW 128 DUP(?) ; 注意這裡隻有128個字
STACKS ENDS
qword全稱是Quad Word
2個位元組就是1個Word(1個字,16位),q就是英文quad-這個詞根(意思是4)的首字母,是以它自然是word(2位元組)的四倍,也就是8位元組
此外,它還是 Pascal 和 nasm 語言中的關鍵字
顯示提示資訊方法
lea dx,infon ; 在螢幕上顯示提示資訊
mov ah,9
int 21h ; 将infon開始的字元串輸出到螢幕
鍵盤輸入方式
從鍵盤輸入一個字元串到緩沖區(AH=0AH)
- 功能:從鍵盤輸入一串ASCII碼字元到緩沖區,輸入結束為緩沖區的個數或者回車字元
- 入口參數: DX=緩沖區首偏移位址; DS=緩沖區段位址
- 調用方法:
MOV AX,緩沖區的首址的段位址
MOV DS,AX
MOV DX, 緩沖區的首址的偏移位址
MOV AH, 0AH
INT 21H
- 執行完上面的調用,将從鍵盤接受字元串送到記憶體的輸入緩沖區(由DS:DX指定緩沖區),需預先定義一個緩沖區
- 緩沖區的第一個位元組指定容納的最大字元個數,由使用者給出
- 第二個位元組存放實際的最大字元個數,由系統最後添入
- 從第三個位元組開始存放從鍵盤接受的字元,直到ENTER鍵結束
e.g.
DATA SEGMENT
BUF DB 20 ; 存放最大字元個數20個
DB ? ; 存放實際輸入字元個數
DB 20 DUP(?) ; 存放輸入字元
DATA ENDS
mul 乘法指令
了解 mul bx 和 mul bl
MUL 彙編語言無符号數乘法指令
MUL SRC 執行的操作:
位元組操作數: (AX)<--(AL)*(SRC)
字操作數: (DX,AX)<--(AX)*(SRC)
編寫程式從了解範例程式開始,在masm for windows 軟體中實作效果,并通過注釋進一步了解彙編語言的寫法規範,以及彙編中子程式的寫法(call 和 ret指令,詳見王爽第十章),學習 jmp 跳轉語句的使用,畫出程式實作的流程圖
實驗心得
這次的實驗比以往的都要綜合,是以也更加複雜,但通過流程圖的繪制以及不斷地報錯調試,最終可以實作完整的程式功能
這次的彙程式設計式編寫有當初學習C語言的感覺,感覺基本邏輯和架構差不多,但是彙編要更偏向于底層,我們通常在與寄存器(靜态的資料),各種指令(動态的語句),從某種程度上讓我對資料結構與算法有了更加具體的感受,也加深了對計算機以及微處理器的了解
子程式調用也很像進階語言中的函數調用,跳轉的實作使得語句(代碼塊)可以得到封裝,進而提升了程式的靈活性
【程式欣賞】
My heart beats with yours
在 masm for windows 中運作
Data segment
full db 0
buff1 db ' Welcome you to run this programme!'
db ' '
db ' *****Please press any key*****$'
buff2 db ' My heart beats with yours!'
db ' ***** Please q to quit *****$'
Data ends
code segment
assume cs: code , ds: Data
start:
push ds
sub ax,ax
push ax
mov ax, Data
mov ds, ax
mov ah, 0
mov al, 4
int 10h
mov ah,0bh
mov bh, 0
mov bl, 1
int 10h
mov ah,0bh
mov bh, 1
mov bl, 2
int 10h
mov dx,offset buff1 ;顯示提示資訊
mov ah, 9
int 21h
mov ah, 8
int 21h
call clear ;cls
sss:
call text ;display the text
mov di, 2
mov al,1 ;draw the big box
mov cx, 70
mov dx, 20
mov bx, 160
Call box
mov cx, 71
mov dx, 21
mov bx, 158
again:
mov al, 1
mov di, 0
Call box
Call delay
mov al, 0
mov di, 0
Call box
inc cx
inc dx
sub bx,2
cmp cx, 94
jnz again
mov di,0 ;draw the 2nd box
mov cx, 95
mov dx, 45
mov al, 1
mov bx, 110
Call box
mov cx, 96
mov dx, 46
mov bx, 108
again_00:
mov al, 1
mov di, 0
Call box
Call delay
Call delay
mov al, 0
mov di, 0
Call box
inc cx
inc dx
sub bx,2
cmp cx, 114
jnz again_00
mov cx,115 ;draw the 3rd box
mov dx, 65
mov al, 1
mov bx, 70
Call box
mov cx, 116
mov dx, 66
mov bx, 68
again_01:
mov al, 1
mov di, 0
Call box
Call delay
Call delay
mov al, 0
mov di, 0
Call box
inc cx
inc dx
sub bx,2
cmp cx, 129
jnz again_01
mov di, 2
mov al,1 ;draw the small box
mov cx, 130
mov dx, 80
mov bx, 40
Call box
mov di, 2
mov al,3 ;對角線
mov si, 0
mov cx, 71
mov dx, 21
mov bx, 59
Call xie_line
mov cx, 171
mov dx, 121
mov bx, 59
Call xie_line
mov si, 1
mov cx, 71
mov dx, 179
mov bx, 59
Call xie_line
mov cx, 171
mov dx, 79
mov bx, 59
Call xie_line
mov cx,150 ;十字線
mov dx, 20
mov si, 0
mov bx, 60
Call draw_line
mov cx, 150
mov dx, 120
mov bx, 60
Call draw_line
mov cx, 70
mov dx, 100
mov si, 1
mov bx, 60
Call draw_line
mov cx, 170
mov dx, 100
mov bx, 60
Call draw_line
mov si, 1
mov cx, 70
mov dx, 60
mov bx, 60
Call mid_line
mov cx, 170
mov dx, 110
mov bx, 60
Call mid_line
mov si, 2
mov cx, 110
mov dx, 20
mov bx, 30
Call mid_line
mov cx, 160
mov dx, 120
mov bx, 30
Call mid_line
mov si, 3
mov cx, 70
mov dx, 140
mov bx, 60
Call mid_line
mov cx, 170
mov dx, 90
mov bx, 60
Call mid_line
mov si, 4
mov cx, 110
mov dx, 180
mov bx, 30
Call mid_line
mov cx, 160
mov dx, 80
mov bx, 30
Call mid_line
mov di, 0
mov al,1 ;draw the big box again
mov cx, 70
mov dx, 20
mov bx, 160
Call box
mov di, 0
mov al,1 ;draw the small box again
mov cx, 130
mov dx, 80
mov bx, 40
Call box
mov di, 0
mov cx, 95
mov dx, 45
mov al, 1
mov bx, 110
Call box
mov cx, 115
mov dx, 65
mov al, 1
mov bx, 70
Call box
mov di,1 ;fill
Call fill
Call fill_2
Call fill_3
mov cx,149 ;bold
mov dx, 120
mov al, 2
mov bx, 60
mov si, 0
Call draw_line
mov cx, 151
mov dx, 120
mov al, 2
mov bx, 60
mov si, 0
Call draw_line
heart_: ;draw the heart
Call cls_box
Call heart
mov ah, 8
int 21h
cmp al,'q'
jz ok
cmp al,20h
jz heart_
Call Clear
jmp sss
ok:
ret
fill proc near ;the procedure of fill
mov full, 0
mov al, 5
mov cx, 160
mov dx, 121
mov si, 0
mov bx, 60
fill_Y:
push cx
push dx
push bx
Call draw_line
pop bx
pop dx
pop cx
sub bx,2
inc cx
Add dx, 2
inc full
cmp full, 30
jne fill_Y
ret
fill endp
fill_2 proc near
mov full, 0
mov al, 5
mov cx, 140
mov dx, 121
mov si, 0
mov bx, 60
fill_Y1:
push cx
push dx
push bx
Call draw_line
pop bx
pop dx
pop cx
sub bx,2
dec cx
Add dx, 2
inc full
cmp full, 30
jne fill_Y1
ret
fill_2 endp
fill_3 proc near
mov al, 1
mov full, 0
mov si, 0
mov cx, 140
mov dx, 121
mov bx, 60
re_fill:
push bx
push cx
push dx
Call draw_line
pop dx
pop cx
pop bx
inc cx
inc full
cmp full, 9
jne re_fill
mov full, 0
mov cx, 159
mov dx, 121
mov bx, 60
re_fill2:
push bx
push cx
push dx
Call draw_line
pop dx
pop cx
pop bx
dec cx
inc full
cmp full, 9
jne re_fill2
ret
fill_3 endp
draw_Line proc near ;the procedure of draw a line
push bx
cmp si, 0
jz V_line1
Add bx, cx
H_line:
mov ah,0ch
int 10h
cmp di, 0
jz aa0
cmp di, 1
jz aa1
Call delay
aa1:
Call delay
aa0:
inc cx
cmp cx, bx
jne H_line
jmp exit_line
V_line1:
Add bx, dx
V_line:
mov ah,0ch
cmp di, 0
jz bb0
cmp di, 1
jz bb1
Call delay
bb1:
Call delay
bb0:
int 10h
inc dx
cmp dx, bx
jne V_line
exit_line:
pop bx
ret
draw_line endp
xie_line proc near ;the procedure of draw a xie_line
Add bx, cx
cmp si, 1
jz xieline_1
xieline_0:
mov ah,0ch
int 10h
inc dx
inc cx
cmp cx, bx
jne xieline_0
jmp exit_xie
xieline_1:
mov ah,0ch
int 10h
dec dx
inc cx
cmp cx, bx
jne xieline_1
exit_xie:
ret
xie_line endp
Mid_line proc near ;draw a xie_line
Add bx, cx
cmp si, 2
jz midline_2
cmp si, 3
jz midline_3
cmp si, 4
jz midline_4
midline_1:
mov ah,0ch
int 10h
inc dx
Add cx, 2
cmp cx, bx
jne midline_1
jmp exit_lines
midline_2:
mov ah,0ch
int 10h
Add dx, 2
inc cx
cmp cx, bx
jne midline_2
jmp exit_lines
midline_3:
mov ah,0ch
int 10h
dec dx
Add cx, 2
cmp cx, bx
jne midline_3
jmp exit_lines
midline_4:
mov ah,0ch
int 10h
sub dx,2
inc cx
cmp cx, bx
jne midline_4
exit_lines:
ret
mid_line endp
box proc near ;draw a box
push cx
push dx
push cx
push dx
push cx
push dx
push cx
push dx
mov si, 1
call draw_line ;top
pop dx
pop cx
Add cx, bx
mov si, 0
call draw_line ;right
pop dx
pop cx
mov si, 0
call draw_line ;left
pop dx
pop cx
mov si, 1
Add dx, bx
call draw_line ;bottom
pop dx
pop cx
ret
box endp
space proc near ;display a space
mov ah, 2
mov dl,' '
int 21h
ret
Space endp
return proc near ;回車
mov ah, 2
mov dl,0ah
int 21h
mov dl,0dh
int 21h
ret
return endp
text proc near ;顯示文本資訊
mov bh, 0
mov dh, 0
mov dl, 0
mov ah, 2
int 10h
mov dx,offset buff2
mov ah, 9
int 21h
Text endp
heart proc near
mov cx,136 ;draw_heart
mov dx, 93
mov si, 0
mov bx, 5
mov al, 2
Call draw_line
mov cx,137 ;draw_heart
mov dx, 91
mov si, 0
mov bx, 9
Call draw_line
mov cx,138 ;draw_heart
mov dx, 90
mov si, 0
mov bx, 12
Call draw_line
mov cx,139 ;draw_heart
mov dx, 89
mov si, 0
mov bx, 14
Call draw_line
mov cx,140 ;draw_heart
mov dx, 88
mov si, 0
mov bx, 16
Call draw_line
mov cx,141 ;draw_heart
mov dx, 88
mov si, 0
mov bx, 17
Call draw_line
mov cx,142 ;draw_heart
mov dx, 87
mov si, 0
mov bx, 19
Call draw_line
mov cx,143 ;draw_heart
mov dx, 87
mov si, 0
mov bx, 20
Call draw_line
mov cx,144 ;draw_heart
mov dx, 87
mov si, 0
mov bx, 21
Call draw_line
mov cx,145 ;draw_heart
mov dx, 88
mov si, 0
mov bx, 21
Call draw_line
mov cx,146 ;draw_heart
mov dx, 88
mov si, 0
mov bx, 22
Call draw_line
mov cx,147 ;draw_heart
mov dx, 89
mov si, 0
mov bx, 22
Call draw_line
mov cx,148 ;draw_heart
mov dx, 90
mov si, 0
mov bx, 22
Call draw_line
mov cx,149 ;draw_heart
mov dx, 91
mov si, 0
mov bx, 22
Call draw_line
mov cx,150 ;1draw_heart
mov dx, 91
mov si, 0
mov bx, 22
Call draw_line
mov cx,151 ;draw_heart
mov dx, 90
mov si, 0
mov bx, 22
Call draw_line
mov cx,152 ;draw_heart
mov dx, 89
mov si, 0
mov bx, 22
Call draw_line
mov cx,153 ;draw_heart
mov dx, 88
mov si, 0
mov bx, 22
Call draw_line
mov cx,154 ;draw_heart
mov dx, 88
mov si, 0
mov bx, 21
Call draw_line
mov cx,155 ;draw_heart
mov dx, 87
mov si, 0
mov bx, 21
Call draw_line
mov cx,156 ;draw_heart
mov dx, 87
mov si, 0
mov bx, 20
Call draw_line
mov cx,157 ;draw_heart
mov dx, 87
mov si, 0
mov bx, 19
Call draw_line
mov cx,158 ;draw_heart
mov dx, 88
mov si, 0
mov bx, 17
Call draw_line
mov cx,159 ;draw_heart
mov dx, 88
mov si, 0
mov bx, 16
Call draw_line
mov cx,160 ;draw_heart
mov dx, 89
mov si, 0
mov bx, 14
Call draw_line
mov cx,161 ;draw_heart
mov dx, 90
mov si, 0
mov bx, 12
Call draw_line
mov cx,162 ;draw_heart
mov dx, 91
mov si, 0
mov bx, 9
Call draw_line
mov cx,163 ;draw_heart
mov dx, 93
mov si, 0
mov bx, 5
Call draw_line
ret
heart endp
delay proc near ;the procedure of delay
push cx
push dx
mov dx, 25
dl2:
mov cx, 2801
dl3:
loop dl3
dec dx
jnz dl2
pop dx
pop cx
ret
delay endp
clear proc near ;clear
mov al, 0
mov bx, 0
mov cx, 0
mov dx, 0
line:
mov ah,0ch
int 10h
inc cx
cmp cx, 320
jne line
mov cx, 0
inc dx
cmp dx, 200
jne line
ret
Clear endp
cls_box proc near
mov al, 0
mov bx, 0
mov cx, 131
mov dx, 81
s_line:
mov ah,0ch
int 10h
inc cx
cmp cx, 170
jne s_line
mov cx, 131
inc dx
cmp dx, 120
jne s_line
ret
cls_box endp
code ends
end start
結果如下: