I'm looking for example how to calculate sine using coprocessor. I've found function:
CalcSin
fld long [angle] ; st(0) = angle
fsin ; st(0) = sin(angle) (angle is in radians)
fstp long [SinX] ; SinX = sin(angle)
I want to draw sine and I need to Y in ax
and X in bx
.
X will be no problem, because I will make loop for, but with Y I have a problem. X will be from example 0 to 350 (like a pixels).
How to calculate it and have Y for pixel if for example sin (30 deg) is 1/2.
How to round result to have good coordinate?
Edit: I'm sorry, but I when I run your code it shows me no sinus, but 2 lines. I don't know what I'm doing wrong now
segment .data
segment .code
..start:
mov ax, 13h
int 10h ; switch to 320x200 mode
mov ax, 0a000h ; The offset to video memory
mov es, ax ; We load it to ES through AX,
; because immediate operation
; is not allowed on ES
;;;;;;;;;;;;;;;;;;;;;;
DrawWave:
mov ebx, y ; EBX = &y
mov ecx, 0
; let st(1) = 2*PI/640
fldpi ; st(0) = PI
fidiv dword [step] ; st(0)/160 = 0.009817...
fldz ; st(0) = 0.0, st(1) = 0.00045...
.loop:
fld st0 ; duplicate the x on the top
fsin ; st(0) = sin x
fimul dword [imgHeight] ; st(0) = y*240
fiadd dword [imgHeight] ; eliminate negative coordinate by translating the wave vertically
fistp dword [y] ; store y to ´y´
fadd st0, st1 ; add the step value to x, doing the step
;draw pixel at [*EAX:ECX]
push ax
push bx
push cx
call DrawPixel
pop cx
pop bx
pop ax
inc ecx
cmp ecx, 320 ; perform 640 steps to draw a single sine wave
jl .loop
fstp st0 ;clean up
fstp st0 ;clean up
ret
;;;;;;;;;;;;;;;;;;;;;;;;;
xor ah, ah
int 16h ; keyboard (wait for key)
mov ax, 3
int 10h ; go to text mode
mov ax, 4c00h
int 21h ; return to DOS, exit code 0
;;;;;;;;;;;;;;;;;;;;;
; EBX = in &CoordY
; ECX = CoordX
;DrawPixel:
; draw a pixel at [*EBX:ECX]
; ret
DrawPixel:
push dx ; mul changes dx too
mov ax, cx ; ax is X coord copy from cx
mov cx, 320
mul cx ; multiply Y (ax) by 320 (one row)
add ax, bx ; and add X (bx) (result= dx:ax)
mov di, ax
pop dx
mov dl, 4
mov [es:di], dl ; store color/pixel
ret
;CONSTANTS:
step: dw 160 ; 2/320 = 160
imgWidth: dw 320 ; 320px
imgHeight: dw 200/2 ; 200px on half, because Y also gets negative
;VARIABLES:
x: dw 0 ; a tmp place to save X
y: dw 0 ; a tmp place to save Y
If I understand your correctly, you want to draw a sine wave without any translations and scaling. Therefore you can take the angle
as your X
coordinate, and the value you get from function f(x) = sin x
is your Y
coordinate.
; EAX = in &CooordX
; EBX = out &CoordY
SinX:
fld qword [eax] ; st(0) = angle
fsin ; st(0) = sin(angle)
fstp qword [ebx] ; *ebx = sin(angle)
ret
Now let's say you want to draw a single wave. That means that x == 2*PI rad
(a full wave) must be true exactly when drawing the last pixel. With a screen 640 pixels wide, your single step for x
in drawing loop is 2*PI/640 = 0.009817
. The rest is simple.
;CONSTANTS:
step: dw 320 ; 2/640 = 320, omitted PI
imgWidth: dw 640 ; 640px
imgHeight: dw 480/2 ; 480px on half, because Y also gets negative
;VARIABLES:
y: dw 0 ; a tmp place to save Y
DrawWave:
mov ebx, y ; EBX = &y
mov ecx, 0
; let st(1) = 2*PI/640
fldpi ; st(0) = PI
fidiv dword [step] ; st(0)/320 = 0.009817...
fldz ; st(0) = 0.0, st(1) = 0.009817...
.loop:
fld st(0) ; duplicate the x on the top
fsin ; st(0) = sin x
fimul dword [imgHeight] ; st(0) = y*240
fiadd dword [imgHeight] ; eliminate negative coordinate by translating the wave vertically
fistp dword [y] ; store y to ´y´
fadd st(0), st(1) ; add the step value to x, doing the step
;draw pixel at [*EAX:ECX]
call DrawPixel
inc ecx
cmp ecx, 640 ; perform 640 steps to draw a single sine wave
jl .loop
fstp st(0) ;clean up
fstp st(0) ;clean up
ret
; EBX = in &CoordY
; ECX = CoordX
DrawPixel:
; draw a pixel at [*EBX:ECX]
ret