?? sin.asm
字號:
;******************************************************************************************
;題目:正弦波信號發生器
;要求:要求模擬正弦波信號發生器,將正弦波信號顯示在顯示器上,信號的周期,峰;值可以鍵盤輸入。
;應用:理解數字信號的發生原理。
;提示:運用分支,循環,子程序等編程形式,運用鍵盤顯示器,文件的中斷調用。
;-----------------------------------------------------------------------
;注意:所畫圖形必須在全屏狀態下才能顯示。
;******************************************************************************************
mode_11 = 11h ;640*480 2 colors
x_axisy = 240
x_axisx = 20
x_axislen = 600
y_axisx = 320
y_axisy = 10
y_axislen = 460
white = 1
;ax:line bx:colomn
writedot macro ;寫像素
mov cx,ax
mov dx,bx
mov ah,0ch
mov al,01
mov bh,0
int 10h
endm
data segment
direction db ?
angle dw ?
savemode db ?
currX dw ?
currY dw ?
t db 6,?,7 dup(?) ;周期
num_t dw ?
a db 5,?,6 dup(?) ;幅度
num_a dw ?
mess_t db 'T:$'
mess_a db 'A:$'
mess1 db 13,10,"Error:Over flow!",13,10,'$'
table db 100,100,100,100,100,100,099,099,099,099
db 098,098,098,097,097,097,096,096,095,095
db 094,093,093,092,091,091,090,089,088,087
db 087,086,085,084,083,082,081,080,079,078
db 077,075,074,073,072,071,069,068,067,066
db 064,063,062,060,059,057,056,054,053,052
db 050,048,047,045,044,042,041,039,037,036
db 034,033,031,029,028,026,024,022,021,019
db 017,016,014,012,010,009,007,005,003,002,000
data ends
code segment
assume cs:code,ds:data
main proc far
mov ax,data
mov ds,ax
call input ;輸入周期和峰值
call xy ;畫笛卡爾坐標系
mov direction,0 ;畫正半軸
call DrawSin
mov direction,1 ;畫負半軸
call DrawSin
;Wait for a keystroke
mov ah,10h ;wait for key
int 16h
;Restroe the starting video mode
mov ah,0
mov al,savemode
int 10h
;Return to Dos
mov ax,4c00h
int 21h
main endp
;-------------------------------------------------------------------------
;function: 在指定范圍畫出正弦波(從零開始畫)
;input:direction=0 正向
; =1 負向
;-------------------------------------------------------------------------
DrawSin proc near
mov angle,0
next: mov ax,angle
sub ax,90 ;90-ax
neg ax
call search
mov ax,bx ;bx*num_a/100
mov cx,num_a
imul cx ;(dx,ax)
mov cx,100
idiv cx
mov bx,ax
cmp bx,-240
jl modify
cmp bx,240
jg modify
sub bx,240 ;240-bx
neg bx
mov ax,angle ;ax+320
mov cx,num_t ;ax*num_t/100
imul cx
mov cx,100
idiv cx
cmp ax,-320
jl DrawSin_exit
cmp ax,320
jge DrawSin_exit
add ax,320
writedot
modify: cmp direction,0
jne reverse
inc angle
jmp next
reverse:dec angle
jmp next
DrawSin_exit:
ret
DrawSin endp
;-------------------------------------------------------------------------
;search子程:
;input:ax存放度數
;output:bx:函數值*100
;require:以table為首的余弦函數表(僅有2位小數)
;-------------------------------------------------------------------------
search proc near
push ax
push cx
push dx
mov cl,0 ;初始化整數部分(默認為零)
mov ch,-1
cmp ax,0
jg greater
neg ax
greater:
cmp ax,360 ;0<=ax<=360則轉移
jle between_0_and_360
cwd ;將ax轉化到[0,360]之間
mov bx,360
idiv bx ;(dx,ax)/bx
mov ax,dx ;ax中為轉化好的度數
between_0_and_360:
sub ax,180
cmp ax,0
jg search_plus
neg ax ;負數時求補
search_plus:
cmp ax,90
jle find ;[0,90)之間,直接去查找
sub ax,180 ;[90,180]之間時,函數值為正
neg ax
mov ch,1
find: mov bx,ax ;確定小數部分
mov dl,table[bx]
mov dh,0
mov bx,dx
cmp ch,-1
jne search_exit
neg bx
search_exit:
pop dx
pop cx
pop ax
ret
search endp
;-------------------------------------------------------------------------
;畫笛卡爾坐標系
;-------------------------------------------------------------------------
xy proc near
;Save the current video mode
mov ah,0fh ;get video mode
int 10h
mov savemode,al
;Switch to a graphics mode
mov ah,0 ;set video mode
mov al,mode_11
int 10h
;Draw the X-axis
mov cx,x_axisx ;X-coord of start of line
mov dx,x_axisy ;Y-coord of start of line
mov ax,x_axislen ;length of line
mov bl,white ;line color
call DrawHorizLine
;Draw the Y-axis
mov cx,y_axisx ;X-coord of start of line
mov dx,y_axisy ;Y-coord of start of line
mov ax,y_axislen ;length of line
mov bl,white ;line color
call DrawVerticalLine
ret
xy endp
;--------------------------------------------------------------
DrawhorizLine proc
;
;Draw a horizontal line starting at position X,Y with
;Receives: CX=X-coordinate, DX=Y-coordinate
; AX=length,and BL=color
;REturns:nothing
;---------------------------------------------------------------
push cx
mov currX,cx ;save X-coordinate
mov cx,ax ;loop counter
dhl1: push cx ;save loop counter
mov al,bl ;color
mov ah,0ch ;draw pixel
mov bh,0 ;video page
mov cx,currX ;retrieve X-coordinate
int 10h
inc currx ;move 1 pixel to the right
pop cx ;restroe loop counter
loop dhl1
pop cx
ret
DrawHorizLine endp
;--------------------------------------------------------------
DrawVerticalLine proc
;
;Draw a vertical line starting at position X,Y with
;a given length and color
;Receives: CX=X-coordinate,DX=Y-coordinate,
; AX=length,BL=color
;Returns:nothing
;---------------------------------------------------------------
push cx
mov currY,dx ;save Y-coordinate
mov currX,cx ;save X-coordinate
mov cx,ax ;loop counter
dvl1: push cx ;save loop counter
mov al,bl ;color
mov ah,0ch ;function:draw pixel
mov bh,0 ;set video page
mov cx,currX ;set X-coordinate
mov dx,currY ;set Y-coordinate
int 10h ;draw the pixel
inc currY ;move down 1 pixel
pop cx ;restore loop counter
loop dvl1
pop cx
ret
DrawVerticalLine endp
;---------------------------------------------------------------
;將ax中的數轉換為10進制數輸出。
;---------------------------------------------------------------
binidec proc near
push cx
push dx
push ax
push bx
pushf
;MAIN PART OF THE PROGRAM GOES HERE:
mov ch,0 ;CH為0則AX為正數,CH為1則Ax為負數
cmp ax,0
jge normal
neg ax
mov ch,1
normal: mov cl,0 ;計數器置零
mov bx,10
binidec_next:
mov dx,0
div bx
push dx
inc cl
cmp ax,0
jne binidec_next
cmp ch,1
jne print
mov ah,2
mov dl,'-'
int 21h
print: pop ax
mov dl,al
add dl,30h
mov ah,2
int 21h
dec cl
jne print
popf
pop bx
pop ax
pop dx
pop cx
ret
binidec endp
;--------------------------------------------------------------
;function:輸入周期值和峰值
;input:none
;output:將周期值和峰值分別放入num_t和num_a中
;--------------------------------------------------------------
input proc near
mov ah,9
mov dx,offset mess_t
int 21h
mov ah,0ah ;輸入t
mov dx,offset t
int 21h
mov ah,2 ;輸出回車換行
mov dl,0dh
int 21h
mov dl,0ah
int 21h
mov bl,t+1 ;在表達式末尾加';'
mov bh,0
mov t[bx+2],';'
mov si,offset t+2
call decibin
mov cx,100 ;ax*100/360
mul cx
mov cx,360
div cx
mov num_t,ax
mov ah,9
mov dx,offset mess_a
int 21h
mov ah,0ah ;輸入a
mov dx,offset a
int 21h
mov ah,2 ;輸出回車換行
mov dl,0dh
int 21h
mov dl,0ah
int 21h
mov bl,a+1 ;在表達式末尾加';'
mov bh,0
mov a[bx+2],';'
mov si,offset a+2
call decibin
mov cx,100 ;ax=整數部分*100
mul cx
jo input_error
mov cx,ax
cmp byte ptr [si+1],'.'
jne input_mov
add si,2
call decibin ;轉化小數部分
cmp ax,10
ja input_add
mov bx,10 ;若小數部分只有一位則乘以10
mul bx
input_add:
add ax,cx ;小數部分+整數部分
input_mov:
mov num_a,ax
ret
input_error:
jmp decibin_error1
input endp
;-----------------------------------------------------------
;function:將十進制數轉換為二進制數
;input:Si指向表達式
;output:轉換后的數放在AX中
;instruction:遇到非數字字符就認為該串數字結束
; 如數字過大導致溢出,則輸出提示信息后程序結束
; 出錯信息名為mess1,請在數據段中定義
;-----------------------------------------------------------
decibin proc near
push bx
push cx
push dx
mov bx,0
newchar:mov al,byte ptr [si]
sub al,30h
jl exit
cmp al,9d
jg exit
cbw
;digit is now in AX
;Multiply number in BX by 10 decimal
xchg ax,bx
mov cx,10d
imul cx
jno c1
jmp decibin_error1
c1: xchg ax,bx
;Add digit in AX to number in BX
add bx,ax
jno c2
jmp decibin_error1
c2: inc si
jmp newchar
exit: mov ax,bx ;將得數存入AX
dec si ;保證SI指向的是數字的最后一個
pop dx
pop cx
pop bx
ret
decibin_error1: ;出錯處理
mov ah,9
mov dx,offset mess1
int 21h
mov ax,4c00h
int 21h
decibin endp
code ends
end main
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -