⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sin.asm

📁 正弦波信号发生器 1、摘要:使用查表法在屏幕上显示正弦波信号。 2、参考资料: IBM-PC汇编语言程序设计(第二版) Intel汇编语言程序设计(第四版) (汇编语言)
💻 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 + -