王爽《匯編語言》(第三版)實驗10解析


1、顯示字符串

assume cs:code
data segment
        db 'welcome to masm!',0
data ends

code segment
start:  mov dh,8
        mov dl,3
        mov cl,2
        mov ax,data
        mov ds,ax
        mov si,0
        call show_str
        mov ax,4c00h
        int 21h
show_str:   push dx
			push cx
			push si     ; 保護子程序寄存器中用到的寄存器
						; 由於主程序的限定
						; 這里由CPU自動為我們分配棧空間
						
			
			mov di,0	;顯示緩存區中的偏移量
			mov bl,dh	
			dec bl		; bl-1才是真正的行,因為行號從0開始計數
			mov al,160  
			mul bl		; 每行160字節 用 行數*每行偏移量 得到目標行的偏移量
			mov bx,ax   ; mul bl之后,乘積存儲在ax中,這里要轉存入bx中
			mov al,2	; 列的偏移量為2,兩個字節代表一列!!!
			mul dl		; 與行偏移量同理
			add bl,al	;將列偏移量與行偏移量相加,得到指定位置的偏移量。
			
			mov ax,0b800h
			mov es,ax	;指定顯示緩存區的內存位置
			
			mov al,cl	; 由於后面jcxz語句的判斷要用到cx,所以我們要將
						; cl(顏色)先存下來。
	 s:     mov ch,0
			mov cl,ds:[si] ;首先將當前指向字符串的某個字符存入cx中
			jcxz ok			; 如果cx為0,則轉移到ok標號執行相應代碼
			mov es:[bx+di],cl	;將字符傳入低地址
			mov es:[bx+di+1],al	; 將顏色傳入高地址
			add di,2	; 列偏移量為2
			inc si		; 字符串的偏移量為1
			loop s		; 不為0,繼續復制
	
	ok:     pop dx		
			pop cx
			pop si		; 還原寄存器變量
			ret			; 結束子程序調用
code ends
end start

2、解決除法溢出的問題

這里要注意,把一個數放在了dx,高位寄存器中,那么就相當於 65536。
例如:int(H/N)
65536 就相當於把int(H/N)放在了dx中。

divdw:
	;先計算高位,再計算低位。低位先入棧
	push ax		; 先將低位數據入棧,因為后面的div需要占用ax寄存器
	mov ax,dx	; 將被除數(X的高16位)放入被除數的低16位ax中
	mov dx,0    ; 將被除數的高十六位dx清零
				
	div cx	    ; int(H/N), 存入ax(商)中,rem(H/N)存入dx(余數)中
	mov bx,ax   ; 臨時保存ax
	  
	pop ax      ; 取出先前入棧的X的低位
 
	div cx		; L\N
	mov cx,dx   ; 余數保存在cx里
	mov dx,bx   ; dx保存的是最終結果的高位

3、數值顯示

投機取巧之法,不過相對簡單。

assume cs:code

data segment
        db 10 dup (0)
data ends

stack segment
    dw 8 dup(0)
stack ends

code segment
start:  mov ax,12666
		mov bx,data
		mov ds,bx
		mov bx,stack
		mov ss,bx
		mov sp,10h
		mov si,0
		call dtoc

		mov dh,8
        mov dl,3
        mov cl,2
        call show_str
		
        mov ax,4c00h
        int 21h

dtoc:    push ax
		push bx
		push si
		mov bx,10
		mov si,0
    
  s0:    
		mov dx,0
		div bx		; ax/bx
		add dx,30h  ; 余數加30
		push dx		; 入棧
		mov cx,ax	; 商-->cx
		inc si		; 記錄循環次數
		inc cx		; 當商為0時,也要加 1 ,方便loop判斷
		loop s0  	; 首先 cx = cx -1,再判斷 cx 是否為0
    
		mov cx,si	; cx 為循環次數	
		mov si,0	; si 指向 ds:[0]
  s1:    
		pop ds:[si]	; 將棧中轉化好了的數據放到內存中
		inc si
		loop s1

		pop si
		pop bx
		pop ax
		ret
    

show_str:   push dx
			push cx
			push si     ; 保護子程序寄存器中用到的寄存器
						; 由於主程序的限定
						; 這里由CPU自動為我們分配棧空間
						
			
			mov di,0	;顯示緩存區中的偏移量
			mov bl,dh	
			dec bl		; bl-1才是真正的行,因為行號從0開始計數
			mov al,160  
			mul bl		; 每行160字節 用 行數*每行偏移量 得到目標行的偏移量
			mov bx,ax   ; mul bl之后,乘積存儲在ax中,這里要轉存入bx中
			mov al,2	; 列的偏移量為2,兩個字節代表一列!!!
			mul dl		; 與行偏移量同理
			add bl,al	;將列偏移量與行偏移量相加,得到指定位置的偏移量。
			
			mov ax,0b800h
			mov es,ax	;指定顯示緩存區的內存位置
			
			mov al,cl	; 由於后面jcxz語句的判斷要用到cx,所以我們要將
						; cl(顏色)先存下來。
	 s:     mov ch,0
			mov cl,ds:[si] ;首先將當前指向字符串的某個字符存入cx中
			jcxz ok			; 如果cx為0,則轉移到ok標號執行相應代碼
			mov es:[bx+di],cl	;將字符傳入低地址
			mov es:[bx+di+1],al	; 將顏色傳入高地址
			add di,2	; 列偏移量為2
			inc si		; 字符串的偏移量為1
			loop s		; 不為0,繼續復制
	
	ok:     pop dx		
			pop cx
			pop si		; 還原寄存器變量
			ret			; 結束子程序調用
	
code ends
end start


免責聲明!

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



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