Springen naar inhoud

Opdracht digitale technieken schrijven assembler functies samen met c++ code


  • Log in om te kunnen reageren

#1

Stef31

    Stef31


  • >250 berichten
  • 609 berichten
  • Ervaren gebruiker

Geplaatst op 26 december 2007 - 10:26

Hallo iedereen

We hebben een opdracht gehad om functies te schrijven in assembler, bepaalde functies werken al maar deze functies werken echt niet heb echt verkeerde resultaten en heb al erg weinig kennis van die assembler want was ook veel zelfstudie met die FPU 8087 processorset.

Op deze functies namelijk ArcSin(), ArcCos(), TanX(), SH(x), CH(x) en de functies voor Exp2(x) geven zelfs verkeerde resultaten, en heb al een 4 tal uur zitten zoeken op die fout maar kan ze helaas niet vinden, we moeten wel dit project ingeven en we mogen van internet en forums gebruikmaken. Heeft hier iemand assembler kennis en mij kan helpen wat hier fout gaat in die stukjes code?

Hier zijn de codes die helemaal niet werken:

extern double Exp2(double x)
{
	double temp = 0.0;
	short MaskedCW;
	short SaveCW;
	_asm
	{
		FLD x						; waarde van x ophalen
		FSTCW MaskedCW				; 
		OR BYTE PTR MaskedCW + 1, 1100b;
		FLDCW MaskedCW
		FLD ST(0)
		FLD ST(0)						
		FRNDINT						; bereken gehele deel
		FXCH						; verwissel de int waarden
		FSUB ST(0), ST(1)			; bereken frac deel
		F2XM1						; bereken 2 ^ frac(x) - 1
		FLD1
		FADD						; bereken 2 ^ frac(x)
		FXCH						; Ophalen van het gehele deel
		FLD1						; bereken 1 * 2 ^ int(x)
		FSCALE
		FSTP ST(1)					; haal de waarde van de stack ST(1) op
		FMUL						; bereken 2 ^ int(x) * 2 ^ frac(x)
		FLDCW SaveCW				; herstel de afrondingsmode
		FST temp
		FNINIT
	}
	return(temp);
}

// Werkt niet rond de waarde af
extern double TanX(double x)
{
	double temp = 0.0;
	double result = Deg2Rad(x);
	_asm
	{
		FLD result	; sla de terugkeerwaarde op op de TOS
		FPTAN		; bereken de Tan(x)
		FST temp	; sla de terugkeerwaarde op op de TOS
		FNINIT
	}
	return(temp);

}

extern double ArcSin(double x)
{
	double temp = 0.0;
	// double result = Deg2Rad(x);
	_asm
	{
		FINIT
		FLD x
		FST ST(1)
		FMUL	
		FST ST(1)
		FLD1
		FSUBR
		FSQRT
		FDIVR x
		FST ST(1)
		FLD1					; bereken de ArcTan
		FPATAN
		FST temp				; opslaan in de temp
	}
	return(temp);
}

extern double ArcCos(double x)
{
	double temp = 0.0;
	double result = Deg2Rad(x);
	_asm
	{
		FLD result
		FMUL					; berekend x * x
		FLD ST(0)				; x * x op de TOS
		FLD1					; bereken 1 - x^2
		FSUBR

		FDIVR					; bereken (1 - x^2) / (x^2)
		FSQRT					; bereken sqrt(1 - x^2) / (x^2)
		FLD1					; bereken de ArcTan
		FPATAN
		FST temp				; opslaan in de temp
		FNINIT
	}
	return(temp);
}

Is niet de bedoeling mijn huiswerk te maken want heb dit wel zelf allemaal geschreven en gehaald uit de wiskunde maar het gaat mis als ik dat uitvoer met de computer waarom daar stel ik wel de vraag om

Dit forum kan gratis blijven vanwege banners als deze. Door te registeren zal de onderstaande banner overigens verdwijnen.

#2

Rogier

    Rogier


  • >5k berichten
  • 5679 berichten
  • VIP

Geplaatst op 26 december 2007 - 12:10

Let goed op wat die FPU instructies doen, sommige zijn niet helemaal intuļtief. Zo berekent FPTAN bijvoorbeeld niet alleen tan(st(0)) maar pusht vervolgens ook nog eens 1 op de stack (het achterliggende idee daarvan is dat een tan een verhoudingen tussen twee coordinaten 1:t representeert).

Dus hij rondt de waarde niet af, volgens mij krijg je altijd 1.0 terug uit jouw TanX functie. Zo moet ie wel werken: (let op de extra FSTP st(0) na de FPTAN)
extern double TanX(double x)
{
  double temp = 0.0;
  double result = Deg2Rad(x);
  _asm
  {
	FLD result ; sla de terugkeerwaarde op op de TOS
	FPTAN	  ; bereken de Tan(x) en pusht 1
	FSTP st(0) ; pop 1 van de stack (staat daar door fptan)
	FST temp   ; sla de terugkeerwaarde op op de TOS
	FNINIT
  }
  return(temp);
}

In jouw Exp2 functie vergeet je de oorspronkelijke status in SaveCW op te slaan, terwijl je hem daar op het eind wel weer uit restored. Zet voor of na FSTCW MaskedCW ook even FSTCW SaveCW, voor de rest moet die functie wel werken.

Die ArcSin functie van je is volgens mij in orde. Maar vergeet je niet dat je daar radialen in moet stoppen, omdat de Deg2Rad gecomment staat? (ik zou sowieso altijd overal met radialen werken, voorkomt verwarring en wiskundig gezien slaat 360 graden in een cirkel nergens op).

Je ArcCos functie lijkt te zijn gebaseerd op LaTeX maar die gelijkheid klopt niet. Moet zijn: LaTeX . Tevens vergeet je in het begin om st(0) te kopiėren (op het moment dat je FMUL doet om x*x te berekenen staat er nog niets in st(1), vergelijk met ArcSin) dus waarschijnlijk geeft die functie nu een exception.
In theory, there's no difference between theory and practice. In practice, there is.

#3

Stef31

    Stef31


  • >250 berichten
  • 609 berichten
  • Ervaren gebruiker

Geplaatst op 26 december 2007 - 12:24

Ik heb eerst in ArcSin toch die functie gebruikt om graden om te zetten in radialen maar krijg toch een foutief resultaat hoor en wat moet ik aanpassen in de code voor mijn ArcCos() ?

#4

Rogier

    Rogier


  • >5k berichten
  • 5679 berichten
  • VIP

Geplaatst op 26 december 2007 - 12:42

Ik heb eerst in ArcSin toch die functie gebruikt om graden om te zetten in radialen maar krijg toch een foutief resultaat hoor

Je gebruikt twee keer x in die functie. Als je toch graden i.p.v. radialen wilt gebriuken moet je die functie ont-commenten en op beide plekken x vervangen door result.

en wat moet ik aanpassen in de code voor mijn ArcCos() ?

Nou, LaTeX
Dus je kunt het makkelijkste gewoon de code van ArcSin kopiėren en daar die LaTeX bij proppen.
In theory, there's no difference between theory and practice. In practice, there is.

#5

Stef31

    Stef31


  • >250 berichten
  • 609 berichten
  • Ervaren gebruiker

Geplaatst op 26 december 2007 - 12:44

Ik heb mijn code aangepast :

extern double ArcSin(double x)
{
	double temp = 0.0;
	double result = Deg2Rad(x);
	_asm
	{
		FLD result
		FMUL					; berekend x * x
		FLD ST(0)				; x * x op de TOS
		FLD1					; bereken 1 - x^2
		FSUBR

		FDIV					; bereken x^2 / (1 - x^2)
		FSQRT					; bereken sqrt(x^2) / (1 - x^2)
		FLD1					; bereken de ArcTan
		FPATAN
		FST temp				; opslaan in de temp
		FNINIT
	}
	return(temp);
}

Geen idee waar ik dat moet bij proppen

#6

Rogier

    Rogier


  • >5k berichten
  • 5679 berichten
  • VIP

Geplaatst op 26 december 2007 - 12:52

Ik heb mijn code aangepast :

Bijna goed nu, je maakt alleen nog die fmul fout in het begin. Oftewel een FST ST(1) voor de FMUL, ofwel er FMUL st(0),st(0) van maken.
In theory, there's no difference between theory and practice. In practice, there is.

#7

Stef31

    Stef31


  • >250 berichten
  • 609 berichten
  • Ervaren gebruiker

Geplaatst op 26 december 2007 - 12:55

Waarom moet dat er zo staan "FST ST(1)" wat is de functie daarvan als je dat in commentaar schrijft?

#8

Rogier

    Rogier


  • >5k berichten
  • 5679 berichten
  • VIP

Geplaatst op 26 december 2007 - 13:01

Waarom moet dat er zo staan "FST ST(1)" wat is de functie daarvan als je dat in commentaar schrijft?

st(0) kopiėren naar st(1), dat deed je zelf toch ook al in je oorspronkelijke ArcSin functie? Of weet je zelf niet meer wat je daar hebt uitgespookt :D

Maar FMUL st(0),st(0) is misschien duidelijker.
In theory, there's no difference between theory and practice. In practice, there is.

#9

Stef31

    Stef31


  • >250 berichten
  • 609 berichten
  • Ervaren gebruiker

Geplaatst op 26 december 2007 - 13:24

Ja inderdaad weet wat het doet je je vermenigvuldigd de inhoud die op de stack op index 0 staat met zichzelf en plaatst het terug in de stack met index 0

Dan nog een vraagje:

Hoe los je dit op ik wil van de ene assembler routine een functie aanroepen naar een andere maar met een call gaat dit verkeerd hoe kan je oplossen?

Voorbeeld:
=======

extern double Exp2(double x)
{
	double temp = 0.0;
	short MaskedCW;
	short SaveCW;
	_asm
	{
		FLD x						; waarde van x ophalen
		FSTCW MaskedCW				; 
		FSTCW SaveCW

		OR BYTE PTR MaskedCW + 1, 1100b;
		FLDCW MaskedCW
		FLD ST(0)
		FLD ST(0)						
		FRNDINT						; bereken gehele deel
		FXCH						; verwissel de int waarden
		FSUB ST(0), ST(1)			; bereken frac deel
		F2XM1						; bereken 2 ^ frac(x) - 1
		FLD1
		FADD						; bereken 2 ^ frac(x)
		FXCH						; Ophalen van het gehele deel
		FLD1						; bereken 1 * 2 ^ int(x)
		FSCALE
		FSTP ST(1)					; haal de waarde van de stack ST(1) op
		FMUL						; bereken 2 ^ int(x) * 2 ^ frac(x)
		FLDCW SaveCW				; herstel de afrondingsmode
		FST temp
		FNINIT
	}
	return(temp);


extern double Exp10(double x)
{
	double temp;
	short MaskedCW;
	short SaveCW;

	_asm
	{
		FLD x						; waarde van x ophalen
		FLDL2T						; zet de Log(10) op de stack
		FMUL						; berekend x * Log(10)
	; CALL Exp2					; berekend 2 ^ x * Log(10)
		
		// ========================================================
		// Aanroep van de functie Exp2
		// ========================================================
		FSTCW MaskedCW				;
		FSTCW SaveCW

		OR BYTE PTR MaskedCW + 1, 1100b;
		FLDCW MaskedCW
		FLD ST(0)
		FLD ST(0)						
		FRNDINT						; bereken gehele deel
		FXCH						; verwissel de int waarden
		FSUB ST(0), ST(1)			; bereken frac deel
		F2XM1						; bereken 2 ^ frac(x) - 1
		FLD1
		FADD						; bereken 2 ^ frac(x)
		FXCH						; Ophalen van het gehele deel
		FLD1						; bereken 1 * 2 ^ int(x)
		FSCALE
		FSTP ST(1)					; haal de waarde van de stack ST(1) op
		FMUL						; bereken 2 ^ int(x) * 2 ^ frac(x)
		FLDCW SaveCW				; herstel de afrondingsmode
		FST temp
		FNINIT
	}
	return(temp);
}

Hallo Rogier of andere programmeurs

Mijn ArcCos() heeft nog steeds verkeerde resultaten en vind die fout nergens heb het nu zo aangepast:

extern double ArcCos(double x)
{
	double temp = 0.0;
	double result = Deg2Rad(x);
	_asm
	{
		FLD result
		FMUL					; berekend x * x
		FLD ST(0)				; x * x op de TOS
		FLD1					; bereken 1 - x^2
		FSUBR

		FDIVR					; bereken (1 - x^2) / (x^2)
		FSQRT					; bereken sqrt(1 - x^2) / (x^2)
		FLD1					; bereken de ArcTan
		FPATAN
		FST temp				; opslaan in de temp
		FNINIT
	}
	return(temp);
}

#10

Rogier

    Rogier


  • >5k berichten
  • 5679 berichten
  • VIP

Geplaatst op 26 december 2007 - 14:14

Hoe los je dit op ik wil van de ene assembler routine een functie aanroepen naar een andere maar met een call gaat dit verkeerd hoe kan je oplossen?

Hangt van je compiler af, en met name de calling conventies die die compiler gebruikt. Die bepalen o.a. hoe en in welke volgorde de argumenten worden meegegeven, zou bijvoorbeeld kunnen dat je compiler om te optimizen float of double argumenten meteen in de FPU meegeeft. Om functies vanuit asm aan te roepen moet je denk ik iets van __declspec(naked) gebruiken, zie ook.

Mijn ArcCos() heeft nog steeds verkeerde resultaten en vind die fout nergens heb het nu zo aangepast:

Je doet nu nog hetzelfde als bij ArcSin hierboven (inclusief weer die FMUL fout), alleen met FDIVR in plaats van FDIV. Da's niet correct, je moet het FPATAN resultaat van LaTeX aftrekken om het gewenste resultaat (arccos) te krijgen.

Wat betreft de wiskunde die ermee gemoeid is: LaTeX is niet hetzelfde als LaTeX (let op negatieve x) en LaTeX is ook niet hetzelfde als LaTeX (let wederom op negatieve x). Voor positieve x zouden die twee wel kloppen, maar ik neem aan dat het voor iedere x moet werken.

Veranderd door Rogier, 26 december 2007 - 14:28

In theory, there's no difference between theory and practice. In practice, there is.

#11

Rogier

    Rogier


  • >5k berichten
  • 5679 berichten
  • VIP

Geplaatst op 26 december 2007 - 14:32

Sorry, foutje in latex en mag nu m'n bericht niet meer wijzigen... onderste zin moest zijn:

Wat betreft de wiskunde die ermee gemoeid is: LaTeX is niet hetzelfde als LaTeX (let op negatieve x), en LaTeX is ook niet hetzelfde als LaTeX (let wederom op negatieve x). Voor positieve x zouden die twee wel kloppen, maar ik neem aan dat het voor iedere x moet werken.
In theory, there's no difference between theory and practice. In practice, there is.

#12

Stef31

    Stef31


  • >250 berichten
  • 609 berichten
  • Ervaren gebruiker

Geplaatst op 01 januari 2008 - 17:35

Hallo iedereen

Kan mij eens iemand vertellen wat er juist gebeurt of hoe kan je dat best voorstellen visueel want we moeten onze code ook gaan uitleggen?

FLD result				; ST := result
		FPTAN					; ST := Tan(x)
		FSTP ST(0)				; pop 1 van de stack
		FST temp				; sla de terugkeerwaarde op op de TOS

#13

Stef31

    Stef31


  • >250 berichten
  • 609 berichten
  • Ervaren gebruiker

Geplaatst op 01 januari 2008 - 18:23

Hallo iedereen

Bij de functie ArcSin voer ik 60 in en deze geeft een raar resultaat en op de rekenmachine is het wel juist hoe kan ik dat oplossen?

extern double ArcSin(double x)
{
	double temp = 0.0;
	double result = Deg2Rad(x);
	_asm
	{
		FLD result
		FST ST(1)
		FMUL					; berekend x * x
		FLD ST(0)				; x * x op de TOS
		FLD1					; bereken 1 - x^2
		FSUBR

		FDIV					; bereken x^2 / (1 - x^2)
		FSQRT					; bereken sqrt(x^2) / (1 - x^2)
		FLD1					; bereken de ArcTan
		FPATAN
		FST temp				; opslaan in de temp
		FNINIT
	}
	return(temp);
}


Voor de rest werkt mijn code maar bij 60° gaat het goed mis geen idee wat het is
Kan iemand mij dat eens zeggen en oplossen wat er mis gaat

Ik heb zelfde probleem met TanH(x) deze geeft ook een verkeerd resultaat af

hier is mijn code

extern double TanH(double x)
{
	double MCX = 0.0;
	double MSX = 0.0;
	double temp = 0.0;
	// double result = Deg2Rad(x);

	
	MCX = CosH(x);
	MSX = SinH(x);
	_asm
	{
		FLD MCX					; load MCX := CosH(x) => ST(0)
		FLD MSX					; load MSX := SinH(x) => ST(1)
		FDIVR					; ST(0) := SinH(x) / CosH(x)
		FST temp				; mem[temp] := SinH(x) / CosH(x)
		FNINIT					; init FPU registers
	}
	return(temp);
}

#14

Safe

    Safe


  • >5k berichten
  • 9906 berichten
  • Pluimdrager

Geplaatst op 01 januari 2008 - 18:51

Je werkt toch in radialen!

#15

Stef31

    Stef31


  • >250 berichten
  • 609 berichten
  • Ervaren gebruiker

Geplaatst op 01 januari 2008 - 19:57

Neen de gebruiker kan graden invoeren en wordt intern omgezet naar radialen





0 gebruiker(s) lezen dit onderwerp

0 leden, 0 bezoekers, 0 anonieme gebruikers

Ook adverteren op onze website? Lees hier meer!

Gesponsorde vacatures

Vacatures