; Der Anfang, weil wir es ein mal rekursiv machen und ein mal ohne, benutzen wir einen Stack ; weil wir die Ausgab auf PORTD machen, setzen wir DDRD auf 0xff ; ich muss gucken ob ich mich mit der Reihenfolge beim Stack nicht vertan habe. ; Ja, ich habe mich vertan ich muss das umdrehen, das ist allerdings unlogisch, deswegen gucke ich noch mal nach. ; nein, ich habe mich nicht vertan, sondern bei meinem Merkblatt ; ich muss die Include file fuer das LCD einbinden, weil ich das jetzt nicht neu schreibe ; ausserdem muss ich, den RAM, weil wir haben ja einen Statischen Code, im Statischen Speicher - EEPROM - da ist unser Programm und unsere statischen Daten - allerdings koennen wir da unsere Folge nicht rein schreiben, weil die muss ja in den dynamischen Speicher RAM - anders als Bei x86, wo der RAM vorherrscht und - ich moechte einfach die Quadratzahlen ausgeben, im RAM bei Daten, nennt das Heap - (1.) statische Daten, Programm (2.) Stack (3.) Heap Dynamische Daten, speichern (4.) Bereich fuer die EA ; Also, den haep mache ich mit dem Label .data leite ich das ein und davor normal das label fuer das Variablen Namen, ich verwende jetzt allerdings fuer die groesse, der Speicherbereiche nicht DB usw. sondern BYTE, bei AVR Spezifisch ; ich muss natuerlich die numbers in zeichen umwandeln, aber das duerfte kein Problem sein, habe ich neulich auf x86 gemacht und immer durch 10 teilen, bis nichts mehr da ist und der Rest + '0' ist jeweils das Auszugebende zeichena .include "m8def.inc" .def temp1 = r16 .def temp2 = r17 .def temp3 = r18 ldi r16, HIGH (RAMEND) out SPH, r16 ldi r16, LOW (RAMEND) out SPL, r16 ldi r16, 0xff out DDRD, r16 ldi r16, 5 mul r16, r16 mov r17, r0 ; so erst mal die quadratzahlen speicher speichern ldi ZH, HIGH (squarenumbers) ldi ZL, LOW (squarenumbers) ldi r16, 1 ; jetzt muss ich den mul fuer AVR nachschauen ; https://cdn-reichelt.de/documents/datenblatt/A300/ATMEGA8xxx.pdf ; MUL Rd, Rr Multiply Unsigned R1:R0 ← Rd x Rr loop1: mul r16, r16 st Z+, r0 inc r16 cp r16, r17 brne loop1 ;jetzt probiere ich mal aus, ob sich der Code schon mal uebersetzen laesst. ;Da kommt unknown Direktive Data. Ich schaue im Buch nach. ;ich habe unsinn gebaut, das heisst .dseg natuerlich, das war dummheit. .dseg squarenumbers: .byte 10 .include "lcd-routines.asm"jetzt probiere ich mal aus, ob sich der Code schon mal uebersetzen laesst. Da kommt unknown Direktive Data. Ich schaue im Buch nach. ich habe unsinn gebaut, das heisst .dseg natuerlich, das war dummheit.
; Der Anfang, weil wir es ein mal rekursiv machen und ein mal ohne, benutzen wir einen Stack ; weil wir die Ausgab auf PORTD machen, setzen wir DDRD auf 0xff ; ich muss gucken ob ich mich mit der Reihenfolge beim Stack nicht vertan habe. ; Ja, ich habe mich vertan ich muss das umdrehen, das ist allerdings unlogisch, deswegen gucke ich noch mal nach. ; nein, ich habe mich nicht vertan, sondern bei meinem Merkblatt ; ich muss die Include file fuer das LCD einbinden, weil ich das jetzt nicht neu schreibe ; ausserdem muss ich, den RAM, weil wir haben ja einen Statischen Code, im Statischen Speicher - EEPROM - da ist unser Programm und unsere statischen Daten - allerdings koennen wir da unsere Folge nicht rein schreiben, weil die muss ja in den dynamischen Speicher RAM - anders als Bei x86, wo der RAM vorherrscht und - ich moechte einfach die Quadratzahlen ausgeben, im RAM bei Daten, nennt das Heap - (1.) statische Daten, Programm (2.) Stack (3.) Heap Dynamische Daten, speichern (4.) Bereich fuer die EA ; Also, den haep mache ich mit dem Label .data leite ich das ein und davor normal das label fuer das Variablen Namen, ich verwende jetzt allerdings fuer die groesse, der Speicherbereiche nicht DB usw. sondern BYTE, bei AVR Spezifisch ; ich muss natuerlich die numbers in zeichen umwandeln, aber das duerfte kein Problem sein, habe ich neulich auf x86 gemacht und immer durch 10 teilen, bis nichts mehr da ist und der Rest + '0' ist jeweils das Auszugebende zeichena .include "m8def.inc" .def temp1 = r16 .def temp2 = r17 .def temp3 = r18 ldi r16, HIGH (RAMEND) out SPH, r16 ldi r16, LOW (RAMEND) out SPL, r16 ldi r16, 0xff out DDRD, r16 ldi r16, 5 mul r16, r16 mov r17, r0 ; so erst mal die quadratzahlen speicher speichern ldi ZH, HIGH (squarenumbers) ldi ZL, LOW (squarenumbers) ldi r16, 1 ; jetzt muss ich den mul fuer AVR nachschauen ; https://cdn-reichelt.de/documents/datenblatt/A300/ATMEGA8xxx.pdf ; MUL Rd, Rr Multiply Unsigned R1:R0 ← Rd x Rr loop1: mul r16, r16 st Z+, r0 inc r16 cp r16, r17 brne loop1 ;jetzt probiere ich mal aus, ob sich der Code schon mal uebersetzen laesst. ;Da kommt unknown Direktive Data. Ich schaue im Buch nach. ;ich habe unsinn gebaut, das heisst .dseg natuerlich, das war dummheit. .dseg squarenumbers: .byte 10 .include "lcd-routines.asm"und ein kleiner fehler war drin, ich habe ld statt ldi verwendet. So im naechsten schritt, wandle ich die zahlen in die richtigen ziffern und zeichen um, dann kann ich schon ausgeben.
jetzt hat der AVR natuerlich keinen DIV Befehl, dann muss ich jetzt entweder dividieren binaer oder mir was anderes ausdenken
binaer multiplizieren geht so
1101 * 1010 1101 * 1000 + 1010 * 10Das geht auch mit Shiften jeweils, hinter die Division bin ich bisher auch beim Abakus noch nicht dahinter gekommen, aber wir koennen ja mal ueberlegen.
Wenn ich das umkehre und 1010 das glaube ich zufaelligerweise 10dec
dann muss ich die Subtraktion umkehren, das heisst, das Ergebnis ist die summe von allen.
x * 10 + x * 1000 = y
Ich mus diese gleichung loesen.
jetzt muss ich das aber umstellen
(y - x*1000)/x = 10
oder so. muss ich kurz nachdenken.
man koennte jetzt ein horner schema verwenden und x ausklammer, oder 10 ausklammen
x * (10 + 1000) x* 10 * (1+100)muss kurz ueberlegen
wir koennten ein intervallhalbirungsverfahren anwenden. Um die Gleichung
x * 10 + x * 1000 = yzu loesen kann ich lauter x einsetzen und das im Intervallhalbierungsverfahren
oder jetzt faellt mir auf -
wir haben es schlussendlich mit einem polynom zu tun. wir
1010 haben ist der Faktor 0 * x2 und 0*x0 aber sonst steht x fuer 10dann haben wir, eigentlich haben wir eine Mischung aus einer linearen Gleichung und einer Polynogleichung, weil wir haben die Potenzen bei 10
10^0 10^1 ... aber es ist eine lineare Mal gucken, wenn wir die Potenzen anwenden, kriegen wir es vielleicht hin doch doch, wir koennen ohne problem durch 10, 100, 1000 teilen, das sind jeweils shifts nach links, 2 bit, 3 bit, 4 bit Dann schreiben wir das einfach mal so hin c x * 10 + x * 1000 = y x << 2 + x << 1000 = yDann koennen wir die gleichung jetzt vielleicht so umdrehen,
y >> 1000vielleicht ist ja das die loesung
y >> 10 - y >> 1000 = xausprobieren in c
ich glaube ich habe eine gewisse Loesung, man muss nich folgendes machen
x1 - x2 - x3 ...wenn sie das jetzt vorstellen
x3 = x5-x4egal, jetzt muessen differenzen von hinten bilden und dann jeweils vom groesseren die differenz abziehen und vom naechstgroesseren wieder die Differenz.
#include <stdio.h> int main (void) { int a = 212; int b = 314; int y = a*b; int x; int x0, x1; int i; printf ("%i\n", y); for (i = 0, x0 = 0; i < 14; i++) { if (((a >> i) & 0x01)) { x0 = (y >> i); break; } } for (; i < 14; i++) { if (((a >> i) & 0x01)) { x1 = (y >> i); x0 = x0 - x1; printf ("x1: %i, i: %i, x0: %i ", x1, i, x0); } } printf ("%i\n", x0); return 0; }
Nein, das ist nur eine moeglichkeit
aber, wenn man hat
5 - 3 - 1 ist das 1 und (5 - (3-1) ist drei.Was unlogish waere weil, dann wuerde die zahl groesser.
aber wir koennten auch von der groesseren zahl die naechste abziehe
x1-x2und von x2 x1 und zu dem von vorher, das abziehen
oder so, ich weiss es nicht
aber in der Umkehrung der Formel
x << 1000 + x << 10 = yliegt die Loesung.
Wir muessen jetzt versuchen dafuer einen mathematischen Koerper fuer die ganzen zahlen zu finden, um es so um zu drehen.
Also
x << 1000 + x << 10 = y (x << 100 + x) << 10 = y (x << 100 + x) = y >> 10jetzt kann ich x ausklammern
x * (1 << 100 + 1) = y >> 10 x = (y >> 10) / (1 << 100 + 1)ja, hier weiss ich niht witer, wegen eben dem Shift
aber, was ich viellecht das selbe wie gerade ebe
x = (y * 10)/(101)Da weiss ich eben nicht weiter.
einen moment wir haben zeit.
Nein, man kann die gleichung
x*1000 + x*10 = yfuer x nicht einfach loesen. Weil, anders herum, wenn x fest ist, ist das kein Problem, aber x taucht mehrfach auf
was man tun koennte, waere
Das Ergebnis - x*1000 = y ausrechnen x * 10 = ynach x aufloesen, also, fuer ein festes y und daraus einen geschickten Mittleren wert errechnen.
fuer 1000 kann ich das nach links shiften, das y. Kann ich 4 nach links shiten
natuerlich heisst das x << 4 fuer x * 1000 und nicht x << 1000, aber das ist jetzt egal.
ich glaube ich habe einen loesungsansatz
1010 * x = y 1000 * x + 10 * x = y 10 * (100*x + 1*x) = y (100*x+1*x) = y/10So, jetzt ist
101 * x = y/10ok, das ist trivial
aber jetzt muss ich ausrechnen
y/10/101und so weiter.
So wuerde ich das verfeinern, jetzt habe ich nur das Problem, mit der 1 bei der 101
das ist das problem
also, ich muesste quasi immer weiter teilen und dabei muesste die 1 am Ende, etwas bewirken.
ich muss quasi einen bestimmten fall einfuehren durch
10 100 1000 10000 100000kann ich ohne problem teilen ich kann durch 10000 teilen indem ich durch
100 100 teile, zwei malich brauche jetzt den spezialfall
101 1001 10001 100001 ...wenn ich den loesen kann, dann kann ich das Ergebnis ausrechnen, zwischenspeichern, und jedes Mal den Fall erneut anwenden.
ich habe einen algorithmus, der mit wenigen schritten, mit wenig subtraktionen und ich sage, das ist erlaubt, weil es gibt Hardware algorithmen, die werden in ASM Diagrammen und - RTL genommen. Sie koennen fuer die Multiplikation, eine schleife von additionen machen. Aber wie man 10001 ausrechnet Also
y = x * 10001So, dann gilt
y = 10000 * x + xSo, ist ist die Struktur so zu sagen von
x*10000 xquasi die gleiche, also
x0000 xund das entspricht dem y, x0000
so, damit wissen wir, weil am ende nur eine 1 steht, keine andere Zahl, keine riesige zahl, sondern nur eine 1, der unterschied wird nicht bedeutend sein
so, dann haben wir
x0000 und yund wir wissen, dass das von der struktur identisch ist, das ist das gleiche
wir werden also hier anfangen. Wir wissen jetzt, dass das
und anders formuliert
wir nehmen y und wir sagen, das ist x000 und jetzt nehmen wir x, das ist x000 » 000 nach da
und jetzt probieren wir aus
wenn wir das x aendern, das heisst, 1 nach unten zaehle, dann aendern wir das x000 und zwar beim x, logischerweise
dabei subtrahieren wir. und wenn das Ergebnis y ist dann stimmt es
Jetzt muessen wir bedenken fuer den Algorithmus
y/10000ist
y/10/10/10/10genauso mussen wir jetzt auch denken, mit einem bisschen ausprobieren. Dazwischen, weil wir stossen unterwegs wir teilen ja nicht nur
10000immer wieder auf
101 1001 10001Gut, wir wissen
10001 ist von 1000x nich so unterschiedlich, deswegen werden wir nicht viel zahlen
Jetzt haben wir aber bruchwerte
2/3Das machen wir natuerlich nicht, da bleibt ein Rest. Und da muessen wir jetzt nachdenken.
Es besteht vielleicht folgendes Moeglichkeit, wenn wir mit
100001multiplizieren x
dann ist y = 100000 * x + xWenn y vorne und hinten die gleiche Struktur hat
x1,x2 x1 = x2 und x1*100000 + x2Dann wenn das fuer y gilt, egal wie gross x ist, waere das problem schnell geloest
Jetzt zahlen wie
10101110die struktur hinten, bei * 1000 entspricht nicht dem vorne
1010 1110und wir koennten jetzt vielleicht mit der Differenz zwischen
1010 und 1110etwas anfangen.
mir kommt es so vor, als haette ich eine idee
also, wenn ich
1000100011000000durch 100 teile, dann kommt heraus
10001000110000wenn ich das aber durch
100000000000 teile werden 1 verschluckt. Bei einer Operation nicht tragisch, das ist ein Rest. Gut, durch die Schiftung bleibt erhalten
darueber haben wir bisher nicht gesprochen.
was in dem Fall y betrifft
Gut, wenn wir
1011 0011 = y haben und durh 1011 teilen fuer x, als Ergebnis dann ware 10001 * 1011 1011 1011so, da sagten wir, dass es her eine Differenz gibt, aber das ist ein Rest, und zwar ein positiver oder negativer
Der unterschied, zwischen dem eigentlichen Ergbenis
1011 0011 und 1011 1011ich kann nicht genau wie genau sich das jetzt mit dem Rest verhaelt, da wir aber den Rest am Ende mitnehmen muessen, koennen wir uns ueberlegen, wenn den Rest verstanden haben, der da neu ensteht, ob wir den einfach mit einbauen.
ich meine, bei einer Ganzzahl division bleibt so oder so ein Rest
dann sage ich einfach jetzt das Ergebnis, ich muss mal ausprobieren, Rest irgendetwas. Was da raus kommt, jetzt mal ueberpruefen. es sieht so aus, als haette es funktioniert.
Also
11011.01101/100001 11011.11011 -11011.01101Ich habe zur probe, den rechner genommen
11011 * 100001 = 11011.11011Wie zu erwarten, hat es sich bestaetigt
Jetzt
11011.11011 - 11011.01101 = 1110 Also sind 11011.01101/100001 = 11011 Rest 1110Und das Ergebnis im Dec ist
877 und 27*33-14 = 877
Gut, unterschied, positive und negative Reste
Den Rest muessen halt mitnehmen und dann koennen wir weiter machen. ich glaube wir sind der Sache sehr nahe und ich mache Beendet fuer heute. Es bietet sich dann die Reste zu addieren, das heisst, mitzu nehmen, und dabei wird die Potenz an 10, mit der reste vergrossert, immer groesser. oder umgekehrt. Am ende bleibt ein groesserer rest, ich vermute, den kann ich wieder so telen und addiere. Warum addieren? Weil Rest ist immer dazu addiert, irgendwann ist der Rest kleiner, als der Divisor. Wenn er das ist, dann ist das der Rest, der sich nicht mehr laesst.