1

I don't know if anyone will be able to help me, but I will try to explain my problem as clearly, as possible. I am learning 8086 FPU with YASM. I want to draw y = cos(x^2+x+1) This is how this graph looks like. I am doing it in DosBox, and I am emulating 8086 processor.

My problem: How to normalize graph's(red) ratio, so it could be readable in DosBox.

So far, I managed to draw a coordinate plane. And I think I managed to draw this graph, but the ratio is too small to check if it is really good. This is how it looks so far GRAPH IMAGE](https://i.stack.imgur.com/0Hy6X.jpg).

I am using FPU, to calculate Y coordinates. I am using stack to calculate Y coordinate. X coordinate will go from 320 to 0 (with dec si), as you can see in my code.

In this code, I am trying to calculate Y (di) every with different X (si). And put the pixel in the spot, that it has to be in.

;------------------------------------------------------------------------
%include 'yasmmac.inc'  
org 100h               

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
section .text                   ; Code starts here

   startas:         
      call procSetGraphicsMode

;;;;;;;;;;;;;;;;;;;;;;;;; COORDINATE PLANE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
      mov di, 200
      mov si, 160
      .vertical:
         mov cl, 15 
         call procPutPixel 
         dec di
         jnz .vertical

      mov si, 320
      .horizontal:        
         mov di, 100
         mov cl, 15        ; 15 = white color
         call procPutPixel
         dec si
         jnz .horizontal

      ; y = di
      ; x = si
      mov si, 320
      mov di, 100

;;;;;;;;;;;;;;;;;;;;;;;; GRAPH ;;;;;;;;;;;;;;;;;;;;;;;;
      .loop:
         mov [value1], si
         mov [value2], si
         finit
         fild dword [value1]
         fild dword [value1]
         fild dword [value3]   ; move to stack 1
         fmul dword [value1]
         fadd st0, st1        ; add x in stack head
         fadd st0, st3        ; add 1 in stack head
         fcos                 ; cos(x^2 + x + 1)     
         frndint              ; round
         fistp word [y]       ; Load rounded answer to [y] variable
         add di, [y]          ; Add [y] to di
         mov cl, 4            ; 4 = Red color
         call procPutPixel
         dec si
         jnz .loop

;;;;;;;;;;;;;;;;;;;;;;;; WAIT FOR ESC ;;;;;;;;;;;;;;;;;;;;;;;;
      call procWaitForEsc 
      exit
      

%include 'yasmlib.asm'
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
section .data                   ; data

     value1: 
     dd  0.0
     
     value2:
     dd  0.0

     value3:
     dd 1.0

     xc: 
     dw 160
     yc:
     dw 100
          
     x: 
     dw  0
     y:
     dw 0
  
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
section .bss    

yasmlib.asm If it helps

KazlLaur
  • 63
  • 6

1 Answers1

2

The axes are the easy part

Since you are working on a graphics screen that has a resolution of 320 x 200, the X coordinates range from 0 to 319 and the Y coordinates range from 0 to 199. Your code erroneously outputs in X's of 320 and y's of 200 and you don't use the X's of 0 or the Y's of 0.

     xor  di, di     ; Y
.vertical:
     mov  si, 160    ; X
     mov  cl, 15     ; Color
     call procPutPixel
     inc  di
     cmp  di, 199    ; MaxY
     jbe  .vertical

     xor  si, si     ; X
.horizontal:        
     mov  di, 100    ; Y
     mov  cl, 15     ; Color
     call procPutPixel
     inc  si
     cmp  si, 319    ; MaxX
     jbe  .horizontal

  ; y = di
  ; x = si
  mov si, 320
  mov di, 100

The data definitions

value1: 
dd  0.0
value2:
dd  0.0
value3:
dd 1.0

Your FPU instructions are dealing with values stored in memory, but are doing so in incompatible ways! eg. value1 can't be both an integer dword and an single precision float at the same time. You primed this variable with the value from the 16-bit integer register SI, so deal with it as a 16-bit integer.

valueX:  dw 0

The calculation

finit (better use the non-waiting fninit) is best held outside of the loop.
frndint is redundant since fistp word [y] will automatically do the rounding for you.
fmul st0 can square the value from st0.
fld1 can load the value 1 to the FPU stack. No need for a memory based variable and also no need to reload it for every X.

    xor   si, si          ; X
    fninit
    fld1                  ; CONST 1
.loop:
    mov   [valueX], si    ; X
    fild  word [valueX]   ; st0 = X
    fmul  st0             ; st0 = X^2
    fiadd word [valueX]   ; st0 = X^2 + X
    fadd  st0, st1        ; st0 = X^2 + X + 1
    fcos                  ; st0 = cos(X^2 + X + 1)         [-1,+1]
    ...
    fistp word [y]        ; {-1,0,+1}
    mov   di, 100         ; Y
    add   di, [y]         ; -> Y={99,100,101}
    mov   cl, 4           ; Color
    call  procPutPixel
    inc   si
    cmp   si, 319
    jbe   .loop
    fstp                   ; Clean FPU stack, removing the CONST 1

Getting the output readable

The cosine value that the FPU delivers ranges from -1 to +1, but storing this value in the integer memory variable y will produce but 3 discrete values -1, 0, and +1.
What is needed is scaling the cosine by some factor like say 60.
Add this to the data:

scaleY:  dw 60

and at the ellipses you add fimul word [scaleY], producing:

    fcos                  ; st0 = cos(X^2 + X + 1)         [-1,+1]
    fimul word [scaleY]   ; st0 = cos(X^2 + X + 1) * 60
    fistp word [y]        ; [-60,+60]
    mov   di, 100         ; Y
    add   di, [y]         ; -> Y=[40,160]
Sep Roland
  • 33,889
  • 7
  • 43
  • 76
  • I think I understood what I was doing wrong. Is it possible to draw that graph where X is in the range [-π/2;π/2]? I think then the graph will be more readable than now. There is no much information about this on the internet. Thank you. – KazlLaur Dec 05 '22 at 14:38
  • 1
    @KazlLaur It's certainly possible but it's a different matter from what this question is about. I suggest you post a new question for it, including your ideas about how the screen should look like eg. fullscreen vs partial rectangle, height of the graph, ... And don't forget to try it yourself first and include that in the question because otherwise this might be seen as "give me the codez" and you don't want that to happen. Also in case you ask a new question, mark this one as accepted. – Sep Roland Dec 06 '22 at 22:55
  • thank you, I will post a new questions with everything You have said and I will add what I have tried myself – KazlLaur Dec 07 '22 at 10:56