Was tut dieser Assembly Code? (Anfängerfrage)


  • Gesperrt

    Also was ich machen möchte das steht in den Kommentaren in Zeile 9, 10 und 11.

    Sowas blödes... Dann hab ich die ganze Zeit die falschen Register verwendet!

    Aber nochmal ganz kurz umrissen, was ich machen möchte:
    Es werden zwei int Werte übergeben, sagen wir jetzt einfach mal i und j.
    Dann möchte ich einmal dividieren und zweimal multiplizieren (und einmal cos aufrufen):
    (cos((3.14 / 180.0) * i) * j)
    Das Ergebnis möchte ich dann wieder in einen int Wert konvertieren und nach %eax schieben.



  • @EinNutzer0 (3.14 / 180.0) ist ein Konstanter Wert, den du schon vorher ausrechnen kannst (spart die Division).


  • Gesperrt

    @DirkB : richtig, das wäre $0x3c8efa35. 🙂



  • @EinNutzer0 sagte in Was tut dieser Assembly Code? (Anfängerfrage):

    Dann möchte ich einmal dividieren und zweimal multiplizieren (und einmal cos aufrufen):
    (cos((3.14 / 180.0) * i) * j)

    Du willst aber eine floating-Point-Division durchführen! div mit rax ist aber Integer-Division. Floating point Division ist fdiv (wie im Pentium-Bug) (das wäre @hustbaer s "guter alter" Weg). Mit SSE kannst du z.B. mit cvtsi2sd xmm0, eax den Wert aus eax von int nach double konvertieren. Dann weiter mit divsd oder so.

    Schau dir doch einfach mal den gewünschten Code an im Compiler Explorer an. Nur für dich als Beispiel: https://godbolt.org/z/7cxXFW



  • @EinNutzer0 ich weiß immer noch nicht was du mit x86-64 asm willst wenn du lernen sollst einen bestimmten (welchen?) µController zu programmieren. Geht nicht in mein Hirn.


  • Gesperrt

    @wob : super, ich weiß nur noch nicht, wie man selber zu solch einer Lösung gelangen kann.


  • Gesperrt

    @wob sagte in Was tut dieser Assembly Code? (Anfängerfrage):

    dann hast du doch bestimmt irgendwas bekommen haben, womit du lernen sollst?!

    Wir haben ein Skript. Das gute Stück umfasst 500 Folien und mehr... Aber das Problem: es ist zwar Assembler Code vorhanden, jedoch wird dieser in keinster Weise erklärt.



  • @EinNutzer0 sagte in Was tut dieser Assembly Code? (Anfängerfrage):

    Wir haben ein Skript. Das gute Stück umfasst 500 Folien und mehr... Aber das Problem: es ist zwar Assembler Code vorhanden, jedoch wird dieser in keinster Weise erklärt.

    Nochmal:

    @Swordfish sagte in Was tut dieser Assembly Code? (Anfängerfrage):

    [...] (welchen?) µController [...]

    MMX auf x86-64 hilft dir dabei sicher nicht.


  • Gesperrt

    Ich hab noch lauter Fragezeichen... funktioniert muls.. , divs.. usw. nur dann, wenn ich eax vorher in xmm schiebe? Ist das immer so, dass es mit den general purpose register nicht funktioniert? Und was genau bewirkt push %rax und push %rbx, wieso braucht man danach ein mov für lokale Variablen? Und soll man noch pop aufrufen oder bewirkt das das leave.

    Sorry man merkt ich bin Anfänger auf diesem Gebiet, aber haben wir alle nicht mal low begonnen?

    @Swordfish sagte in Was tut dieser Assembly Code? (Anfängerfrage):

    (welchen?) µController

    Das versuche ich gerade herauszufinden... In der Prüfung kann auch ein ganz anderer mc drankommen, es wird ein Teil der Doku mitgegeben. Dennoch möchte ich mich "vorbereiten".


  • Gesperrt

    Habe jetzt Assemblercode der funktioniert aber das falsche Ergebnis für x ausgibt:

    	.text
    	.globl	getx
    	.type	getx, @function
    getx:
    .LFB0:
    	push		%rcx
    # main.c:7: 	float w2 = w * (M_PI / 180.0);
    # main.c:8: 	x = (int) (r * cos(w2));
    # main.c:9: 	return x;
    	movl			$0x4048f5c3, %ecx
    	movl			$0x43340000, %edx
    	cvtsi2sd	%ecx, %xmm0
    	cvtsi2sd	%edx, %xmm1
    	divsd		%xmm0, %xmm1
    	cvtsi2sd	%eax, %xmm0
    	mulsd		%xmm0, %xmm1
    	movsd			%xmm1, %xmm0
    	call		cos@PLT
    	movsd			%xmm0, %xmm1
    	cvtsi2sd	%ebx, %xmm0
    	mulsd		%xmm0, %xmm1
    	cvttsd2si	%xmm1, %eax
    	pop			%rcx
    	ret
    

    Caller:

    # main.c:24: 		x = getx(25, i);
    	movl	-4(%rbp), %ebx	# i, tmp87
    	movl		$25, %eax	#,
    	call	getx	#
    	movl	%eax, -16(%rbp)	# tmp88, x
    # main.c:25: 		y = gety(25, i);
    	movl	-4(%rbp), %eax	# i, tmp89
    	movl	%eax, %esi	# tmp89,
    	movl	$25, %edi	#,
    	call	gety	#
    	movl	%eax, -20(%rbp)	# tmp90, y
    

    Wieso ist das Ergebnis noch falsch?



  • @EinNutzer0 sagte in Was tut dieser Assembly Code? (Anfängerfrage):

    In der Prüfung kann auch ein ganz anderer mc drankommen, es wird ein Teil der Doku mitgegeben.

    Dann wird das sicher etwas ziemlich simples sein. Ich finde aber so eine Ansage eher ... ähm ... pervers.
    Auf jeden Fall wird es mit ziemlicher Sicherheit nicht AT&T-Syntax sein.



  • Stimme Swordfish zu. Du willst jetzt speziell Floating-Point-Berechnung auf X8664 lernen, um Mikrocontroller-Assembler zu schreiben?!

    Jedenfalls: was tust du denn eigentlich in deiner Funktion?
    Du teilst 0x43340000 durch 0x4048f5c3 (oder andersrum, ich kommt bei at&t immer durcheinander) - das ergibt 1.0453936 und hat in jedem Fall nichts mit pi/180 zu tun. Wie kommst du überhaupt auf die beiden Zahlen in Zeile 10/11?



  • @EinNutzer0
    0x4048f5c3 ist die IEEE single precision float representation für 3.14.
    So funktioniert das aber nicht. cvtsi2sd interpretiert den Wert im Register als Integer.
    Laut Internetz kannst du movd dafür verwenden.
    Also statt

    	movl			$0x4048f5c3, %ecx
    	movl			$0x43340000, %edx
    	cvtsi2sd	%ecx, %xmm0
    	cvtsi2sd	%edx, %xmm1
    

    dann

    	movl			$0x4048f5c3, %ecx
    	movl			$0x43340000, %edx
    	movd			%ecx, %xmm0
    	movd			%edx, %xmm1
    

    Die weiteren cvtsi2sd müssen aber bleiben, denn da willst du ja wirklich nen Integer nach Float konvertieren.


  • Gesperrt

    Ich glaub jetzt inzwischen, die float literals sind das Problem... (Und ich hatte eax und ebx in getx vertauscht...)

    Hier hab ich eine interessante Quelle gefunden: https://www3.nd.edu/~dthain/courses/cse40243/fall2015/intel-intro.html

    https://a.uguu.se/bm1a5UpI4kHZ.png

    https://a.uguu.se/KKLJK0bxdZFI.png

    https://a.uguu.se/gNWD5HtWKcry.png

    Möglichkeit 2: Man verwende ein int literal und teile dies durch einen Divisor


  • Mod

    Da du so konsequent diese Frage von Swordfish, DirkB und anderen ignorierst, versuche ich noch einmal mein Glück: Du bist dir vollkommen bewusst, dass die Feinheiten der x64-Floating-Point-Programmierung dir absolut gar nichts helfen, wenn du einen anderen Prozessortyp als eigentliche Zielplattform hast? Dass du gerade deine Zeit damit vertrödelst Spanisch zu büffeln, wenn du demnächst eine Französischklausur schreiben musst?

    Schlimmer noch: Allem nach zu beurteilen, was du bisher gesagt hast, geht es in der Prüfung doch wohl eher um fundamentales wie Kontrollfluss und grundlegende Algorithmen, wohingegen Floating Point Berechnungen erst recht nutzloses Spezialwissen sind. Du lernst spanische Sprichwörter, wenn es um französische Grammatik geht.



  • ...um dir das nochmal deutlich zu machen. Wähle in dem Compiler-Explorer-Link, den ich gepostet hatte (https://godbolt.org/z/7cxXFW) einfach mal rechts einen anderen Compiler, z.B. "Power64 AT 12.0" und vergleiche den generierten Assemblercode. Du wirst sehen: sieht ganz anders aus. Eben Französisch <-> Spanisch. Oder sogar böhmische Dörfer?


  • Gesperrt

    Ja ihr habt recht. x64 Assembler ist in diesem Fall nicht der geeignete Einstieg bzw. etwas völlig anderes als das zu Lernende.

    Dennoch, wenn ich mit etwas anfange, möchte ich es eigentlich auch hinbekommen.

    Also eigentlich versuche ich jetzt das hier zu berechnen: (cos(((314.0 / 100.0) / 180.0) * i) * j)



  • @EinNutzer0 Dann kannst du auch gleich 314. / 18000. berechnen.
    Oder du berechnest einfach atan(1)/45. Das wäre genauer.



  • @EinNutzer0 sagte in Was tut dieser Assembly Code? (Anfängerfrage):

    Ich glaub jetzt inzwischen, die float literals sind das Problem...

    Hast du meinen Beitrag gelesen?


  • Gesperrt

    @hustbaer : ja, hatte ich, danke dafür. Ich werd's nachher nochmal versuchen. Sorry, falls es langsam nervig wird.

    Etwas hab ich noch übersehen, denn x ist nach wie vor 0:

    getx:
    .LFB0:
    # main.c:7: 	float w2 = w * (M_PI / 180.0);
    # main.c:8: 	x = (int) (r * cos(w2));
    # main.c:9: 	return x;
    	push		%rcx
    	movl		$0x4048f5c3, %ecx
    	movl		$0x43340000, %edx
    	movd		%ecx, %xmm0
    	movd		%edx, %xmm1
    	divsd		%xmm0, %xmm1
    	cvtsi2sd	%ebx, %xmm1
    	mulsd		%xmm0, %xmm1
    	movsd		%xmm1, %xmm0
    	call		cos@PLT
    	movsd		%xmm0, %xmm1
    	cvtsi2sd	%eax, %xmm0
    	mulsd		%xmm0, %xmm1
    	cvttsd2si	%xmm1, %eax
    	pop		%rcx
    	ret
    

Anmelden zum Antworten