0

I wrote program in assembly that takes only two variables from C program, then returns the answer to C program at the end. I got problem with finding what is wrong in assembly file.

My goal is to write program using FPU (nasm), that will count arctg (x), where x is a variable in C, typed in by user. Second variable is accuracy, so the number of taylor series integers.

program C:

extern float arctg(float x, int dokladnosc); //deklaracja funkcji zewnętrznej
#include <stdio.h>

int main()
{
        float a;
        int b;
        printf("1.Napisz program, ktory oblicza arctg(x), gdzie x jest argumentem podanym przez\n uzytkownika,podobnie jak dokladnosc obliczenia.\n");
        printf("\nPodaj wartosc X z przedzialu (-1,1): ");
        scanf("%f",&a);
        if(a>=1 || a<=-1)
        {
        printf("zly argument!! ");
        getch();
        return 0;
        }
        printf("Dokladnosc: ");

        scanf("%i",&b);
        if(b<1)
        {
        printf("zly argument!! ");
        getch();
        return 0;
        }
        printf("Wartosc funkcji Arctg(%f) = %f\n", a, arctg(a, b));
        getch();
        return 0;
}

program assembler:

section .text   use32                  
global _arctg                  
_arctg:

%idefine x [ebp+8]
%idefine dokl [ebp+12]
push ebp                               
mov ebp, esp           


finit                                          
fld             dword x                
;?fst dword x          
fild    dword dokl             
; st1 x   st0  dokl  
  fld1
  fsubp st1,st0
  ; st1 x   st0  dokl-1 (tak jak we wzorze od zera->do n-1)
fldz ; nowa dokladnosc -> dokl !! dopoki bd rowne :X !
; st2 x   st1  dokl-1  st0 0 <-mnoznik do tego!

fld1 ;jezeli tu bd jedynka to wyraz bedzie dodatni!!
; st3 x   st2  dokl-1  st1 0 <-mnoznik do tego!  st0 1(znaku)


;na obliczenia:
fldz
; st4 x   st3  dokl-1  st2 0 <-mnoznik do tego!  st1 1(znaku)=1  st0 obliczenia=1

licz_kolejny_wyraz_szeregu:

;to wiemy, ze nastepny bedzie ujemny, jesli bedzie nastepny.
; st4 x   st3  dokl-1  st2 0 <-mnoznik do tego!  st1 1(znaku)=1  st0 obliczenia=1
;ustawiam znak st2->'0'


;1.sprawdzamy znak:

fld1
fcomp st2 ; jakiego znaku?
fstsw ax
sahf
je dodatni
;jmp ujemny
ujemny:
;dodaje 1 do bitu znaku '1' = dodatni ,
fld1
faddp st2,st0
;to samo co w dodatni, ale ze zmiana znaku

jmp dodatni_gdzie_bit_znaku_rowny_1



dodatni:
;odejmuje 1 od bitu znaku '1' = dodatni ,
fld1
fsubp st2,st0
dodatni_gdzie_bit_znaku_rowny_1:
;mozemy przejsc do liczenia pierwszego wyrazu(dodatniego)
;najpierw x^(2n+1)
;fld1 ;1szy nowy element
;petla do potegi ^2n+1, gdzie n->stała; np.3 razy
;fmul st0,st5 ; st0 x
;stworzymy biezace 2n+1 :o
; st4 x   st3  dokl-1  st2 0 <-mnoznik do tego!  st1 1(znaku)=0  st0 obliczenia=1
fld1 ;1szy nowy element
fld1
faddp ; mamy 2 , teraz razy biezace 'n'
fmul st0,st3  
; st5 x   st4  dokl-1  st3 0 <-mnoznik do tego!  st2 1(znaku)=0  st1 obliczenia=1   st0  2*0
fld1
faddp st1,st0 ; jest '1' przy pierwszej rundzie.
; st5 x   st4  dokl-1  st3 0 <-mnoznik do tego!  st2 1(znaku)=0  st1 obliczenia=1   st0  1->mnoznik_obecnej_petli
;licznik petli utworzony, wiec liczmy w petli !
fld1 ;2-gi nowy element
; st6 x   st5  dokl-1  st4 0 <-mnoznik do tego!  st3 1(znaku)=0  st2 obliczenia=1   st1  1->mnoznik_obecnej_petli   st0 1
potegowanie:
fmul st0,st6 ; st0 x
; st6 x   st5  dokl-1  st4 0 <-mnoznik do tego!  st3 1(znaku)=0  st2 obliczenia=1   st1  1->mnoznik_obecnej_petli   st0 x
;odjac 1 od licznika i sprawdzic czy jest rowny zero.
fld1
fsubp st2,st0
; st6 x   st5  dokl-1  st4 0 <-mnoznik do tego!  st3 1(znaku)=0  st2 obliczenia=1   st1  0->mnoznik_obecnej_petli   st0 x
;porownanie wartosc licznika z zerem:
fldz
fcomp st2
; st6 x   st5  dokl-1  st4 0 <-mnoznik do tego!  st3 1(znaku)=0  st2 obliczenia=1   st1  0->mnoznik_obecnej_petli   st0 x
sahf
je licznik_rowny_zero
jmp potegowanie


licznik_rowny_zero:
;teraz mianownik i dzielimy:
fxch st1 ;zamian 'potegi' z licznikiem petli

; st6 x   st5  dokl-1  st4 0 <-mnoznik do tego!  st3 1(znaku)=0  st2 obliczenia=1  st1 x      st0  0->mnoznik_obecnej_petli  
;od nowa ustawiam nowy mnoznik biezacej petli
fld1
faddp st1,st0
fld1
faddp st1,st0
fmul st0,st4
fld1
faddp st1,st0
; st6 x   st5  dokl-1  st4 0 <-mnoznik do tego!  st3 1(znaku)=0  st2 obliczenia=1  st1 x      st0 mianownik:  2n+1 ->1
fdivp st1,st0
 ; st5 x   st4  dokl-1  st3 0 <-mnoznik do tego!  st2 1(znaku)=0  st1 obliczenia=1  st0 x/(2n+1)    
;fmulp st1,st0
;zabawa ze znakiem: jezeli bit_znaku = 0 liczba dodatnia, jezeli bit_znaku = 1 , liczba ujemna, zmieniamy znak


fld1
fcomp st3
sahf
je ujemna_jednak
jmp dodatnia_jednak
ujemna_jednak:
fchs ;zmieniam znak i tyle.

dodatnia_jednak:

faddp st1,st0
; st4 x   st3  dokl-1  st2 0 <-mnoznik do tego!  st1 1(znaku)=0  st0 obliczenia= x/(2n+1)    

; st4 x   st3  dokl-1  st2 0 <-mnoznik do tego!  st1 1(znaku)=0  st0  +/-  obliczenia= x/(2n+1)  
;obliczyłem 1-szy wyraz szeregu czas na sprawdzenie czy mnoznik_do_tego = dokladnosci wyrazow jakie chcemy:
fld1   ;st0 = 1
fmul st0,st3  ;st0 = st3
fcomp st4 ; 0 = dokl -1  ??
fstsw ax
sahf
fld1  ; dodajmy do mnoznika 1
faddp st3,st0

jne licz_kolejny_wyraz_szeregu

;fst dword dokl
;mov eax, dokl
leave                                  
ret                    

section .data
mnoznik:    dd 1.0
cos    dd 1.0

When I type accuracy > 2 (dokladnosc) program stops, and when I type 1 program returns -x, not x

I compile using these lines in nasm: (i am using gcc)

cd C:\Users\jaa\Desktop\infa\architektura\projekt2\moje takie

nasm -f coff p4.asm -o plik.o

set path=%pah%;C:\mingw\bin

gcc  p2.c -c -o plik1.o

gcc plik.o plik1.o -o plik.exe

i try to send ST0 to C as result , that is my goal

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Kamil Witkowski
  • 1,978
  • 1
  • 19
  • 33
  • How about using 8087 FPU instruction set? This is the FPU designed for 8086 processors and it has an instruction FPATAN for counting arctan. – 3yakuya Jan 06 '14 at 23:28
  • no i can't use that , beacuse of the teacher. it must be Taylor series. – Kamil Witkowski Jan 06 '14 at 23:29
  • Your code looks pretty messy. For example: you push EBP and does not appear to pop it. No intendation makes it nearly-impossible to read. There appear to be many lines of commented code, not sure if that is deliberate. – 3yakuya Jan 06 '14 at 23:35
  • well the commented code are my notes, and many of them are about what is curently in st0 etc ( FPU stack) i only need to take ST0 at the end where is result. Sorry, but i'm from Poland, co comments are in polish. I could write you down what i try to make in english too if you have time to help me – Kamil Witkowski Jan 06 '14 at 23:39
  • I understand Polish, just keep the discussion understandable for potential answer-providers. – 3yakuya Jan 06 '14 at 23:40
  • Well, just read it (it is really hard, you should try to clean the code up, at least a bit). It appears you do not keep correct track of what is at the FPU. For example, in line 17: `fsubp st1,st0` - this will not give you `dokl-1` but `1-dokl` in st0. I recommend to sit for a while, and try to track what exactly goes on at the FPU. If you are not sure about some instruction (for example what is the order of the operands) check it carefully first. A good way is to "simulate" 1 or 2 loops on paper: write down what happens at the FPU stack after every operation. – 3yakuya Jan 07 '14 at 00:01
  • i;m not sure about that before i add fld1 so i have now st1 dokl, st0 1 , and now fsubp st1,st0 Subtract ST(0) from ST(i), store result in ST(i), and pop register stack. so st 1 - st 0 = dokl - 1 , and st 0 is out. right or not??? – Kamil Witkowski Jan 07 '14 at 00:11
  • It actually substracts ST(i) from ST(0) and store the value in ST(i), then pop the stack, as far as I know. This can be extremely confusing indeed. – 3yakuya Jan 07 '14 at 00:12
  • hm? my info is from this site: http://x86.renejeschke.de/html/file_module_x86_id_121.html – Kamil Witkowski Jan 07 '14 at 00:15
  • Well, it appears my ref-book is wrong then. I still recommend checking what exactly is happening at the FPU. It is not an easy job, but sometimes it is the only way. You may try using some debugger to check the value at registers as the code runs. – 3yakuya Jan 07 '14 at 00:20
  • do you know how to debug it ? i don't have any assembler debugger, and i use nasm to create .exe ;/ – Kamil Witkowski Jan 07 '14 at 00:22
  • Search online for some assembly debugger (for your operating system and assembly type). emu8086 was quite popular some time ago, but as far as I know it does not support FPU well... – 3yakuya Jan 07 '14 at 00:33
  • BTW @Byakuya, the `push EBP` is not an issue because `leave` will pop it. – Drew McGowen Jan 08 '14 at 10:18
  • i made it, only "fstsw ax" was missing ! – Kamil Witkowski Jan 08 '14 at 15:44
  • @DrewMcGowen failed to see it, that is right. – 3yakuya Jan 08 '14 at 18:22

0 Answers0