天天看點

【實驗作業】微處理器原理與應用 CPUHomework3【子程式彙編實驗 流程圖 十六進制數轉十進制數 鍵盤錄入 螢幕顯示 閏年判斷 兩位數求和 彙編小程式】實驗報告實驗三 子程式彙編實驗學習和提高【基礎學習】【程式欣賞】

文章目錄

  • 實驗報告
  • 實驗三 子程式彙編實驗學習和提高
    • 彙編語言中的 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指令的差別

  1. P和T都是執行,像 add ax, bx,不管用哪個,都是執行此語句

    但如果是 call next, next是一個程式段,那麼用P直接就把這段程式執行完,用T則進入内部一句一句執行(與C語言的調試一樣,有的進入函數内部,有的執行完函數)

  2. 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

流程圖**(流程圖格式使用預設)**如下:

【實驗作業】微處理器原理與應用 CPUHomework3【子程式彙編實驗 流程圖 十六進制數轉十進制數 鍵盤錄入 螢幕顯示 閏年判斷 兩位數求和 彙編小程式】實驗報告實驗三 子程式彙編實驗學習和提高【基礎學習】【程式欣賞】

具體代碼測試結果如下:

【實驗作業】微處理器原理與應用 CPUHomework3【子程式彙編實驗 流程圖 十六進制數轉十進制數 鍵盤錄入 螢幕顯示 閏年判斷 兩位數求和 彙編小程式】實驗報告實驗三 子程式彙編實驗學習和提高【基礎學習】【程式欣賞】
【實驗作業】微處理器原理與應用 CPUHomework3【子程式彙編實驗 流程圖 十六進制數轉十進制數 鍵盤錄入 螢幕顯示 閏年判斷 兩位數求和 彙編小程式】實驗報告實驗三 子程式彙編實驗學習和提高【基礎學習】【程式欣賞】
【實驗作業】微處理器原理與應用 CPUHomework3【子程式彙編實驗 流程圖 十六進制數轉十進制數 鍵盤錄入 螢幕顯示 閏年判斷 兩位數求和 彙編小程式】實驗報告實驗三 子程式彙編實驗學習和提高【基礎學習】【程式欣賞】
【實驗作業】微處理器原理與應用 CPUHomework3【子程式彙編實驗 流程圖 十六進制數轉十進制數 鍵盤錄入 螢幕顯示 閏年判斷 兩位數求和 彙編小程式】實驗報告實驗三 子程式彙編實驗學習和提高【基礎學習】【程式欣賞】
【實驗作業】微處理器原理與應用 CPUHomework3【子程式彙編實驗 流程圖 十六進制數轉十進制數 鍵盤錄入 螢幕顯示 閏年判斷 兩位數求和 彙編小程式】實驗報告實驗三 子程式彙編實驗學習和提高【基礎學習】【程式欣賞】

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
           

流程圖如下:

【實驗作業】微處理器原理與應用 CPUHomework3【子程式彙編實驗 流程圖 十六進制數轉十進制數 鍵盤錄入 螢幕顯示 閏年判斷 兩位數求和 彙編小程式】實驗報告實驗三 子程式彙編實驗學習和提高【基礎學習】【程式欣賞】
【實驗作業】微處理器原理與應用 CPUHomework3【子程式彙編實驗 流程圖 十六進制數轉十進制數 鍵盤錄入 螢幕顯示 閏年判斷 兩位數求和 彙編小程式】實驗報告實驗三 子程式彙編實驗學習和提高【基礎學習】【程式欣賞】
【實驗作業】微處理器原理與應用 CPUHomework3【子程式彙編實驗 流程圖 十六進制數轉十進制數 鍵盤錄入 螢幕顯示 閏年判斷 兩位數求和 彙編小程式】實驗報告實驗三 子程式彙編實驗學習和提高【基礎學習】【程式欣賞】

複習一下:

加載有效位址(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	; 程式結束
           
【實驗作業】微處理器原理與應用 CPUHomework3【子程式彙編實驗 流程圖 十六進制數轉十進制數 鍵盤錄入 螢幕顯示 閏年判斷 兩位數求和 彙編小程式】實驗報告實驗三 子程式彙編實驗學習和提高【基礎學習】【程式欣賞】

上面的程式是在程式内部定義的資料,以下改進可以使之從鍵盤輸入

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
           

運作結果如下:

【實驗作業】微處理器原理與應用 CPUHomework3【子程式彙編實驗 流程圖 十六進制數轉十進制數 鍵盤錄入 螢幕顯示 閏年判斷 兩位數求和 彙編小程式】實驗報告實驗三 子程式彙編實驗學習和提高【基礎學習】【程式欣賞】

但顯然不能輸入和輸出兩位數:

【實驗作業】微處理器原理與應用 CPUHomework3【子程式彙編實驗 流程圖 十六進制數轉十進制數 鍵盤錄入 螢幕顯示 閏年判斷 兩位數求和 彙編小程式】實驗報告實驗三 子程式彙編實驗學習和提高【基礎學習】【程式欣賞】

接下來編寫兩位數求和的程式代碼

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

           

最終流程圖如下:

【實驗作業】微處理器原理與應用 CPUHomework3【子程式彙編實驗 流程圖 十六進制數轉十進制數 鍵盤錄入 螢幕顯示 閏年判斷 兩位數求和 彙編小程式】實驗報告實驗三 子程式彙編實驗學習和提高【基礎學習】【程式欣賞】

運作結果如下:

【實驗作業】微處理器原理與應用 CPUHomework3【子程式彙編實驗 流程圖 十六進制數轉十進制數 鍵盤錄入 螢幕顯示 閏年判斷 兩位數求和 彙編小程式】實驗報告實驗三 子程式彙編實驗學習和提高【基礎學習】【程式欣賞】

進位也沒有問題

【實驗作業】微處理器原理與應用 CPUHomework3【子程式彙編實驗 流程圖 十六進制數轉十進制數 鍵盤錄入 螢幕顯示 閏年判斷 兩位數求和 彙編小程式】實驗報告實驗三 子程式彙編實驗學習和提高【基礎學習】【程式欣賞】

【基礎學習】

棧的定義

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
           

結果如下:

【實驗作業】微處理器原理與應用 CPUHomework3【子程式彙編實驗 流程圖 十六進制數轉十進制數 鍵盤錄入 螢幕顯示 閏年判斷 兩位數求和 彙編小程式】實驗報告實驗三 子程式彙編實驗學習和提高【基礎學習】【程式欣賞】

繼續閱讀