Hallo, was ist eigentlich der Sinn von sra und sla? Klar, was es macht steht im Buch, aber der Sinn? Und was heisst hier "Arithmetisch"? bei sll und srl verstehe ich den Sinn (pro shift wird mal 2 resp. durch 2 geteilt) Bloss: wieso sagt man dem "logisches" shift? das ist doch arithmetisch???
Der Unterschied ergibt sich fuer den Rechtsshift von negativen Zahlen. -8 arithmetisch geschiftet gibt -4, logisch geshifted geht das Vorzeichen verloren und man bekommt eine positive Zahl, je nach Breite des Registers. Z.b. fuer 8 bit: -8 = 0xf8, geshifted 0x7C = 124.
Hallo Kay, das hab ich erst auch gedacht, aber ich hab das mal mit -77 ausprobiert: 10110011 sra 2 = 11101100 und das ist 20 und nicht 19!? Es müsste doch abgerundet werden und nicht aufgerundet? Und wofür ist denn sla??? das gibt bei signed ja überhaupt keinen Sinn.
Thomas Iseli schrieb: > das hab ich erst auch gedacht, aber ich hab das mal mit -77 ausprobiert: > 10110011 sra 2 = 11101100 und das ist 20 und nicht 19!? > Es müsste doch abgerundet werden und nicht aufgerundet? Das Problem taucht immer wieder auf. Auch die Herren Softies haben damit zu kämpfen, dass ein arithmetischer Shift einer negativen Zahl eben keine richtige Division durch 2 ist. Beitrag "Re: Dividieren durch Schiften" Beitrag "Optimiert der Compiler Division durch 2^n wirklich?" > Und wofür ist denn sla??? das gibt bei signed ja überhaupt keinen Sinn. Das ist genau das selbe wie sll, egal ob unsigned oder signed. Der Befehl ist einfach aus Orthogonalitätsgründen vorhanden. Z.B. auch bei uCs: Beitrag "Was ist der unterschied zwischen ASL und LSL"
Bei CPUs gibt es zwischen ASL und LSL durchaus Unterschiede. z.b. 68000 Nach LSL ist das Overflowbit im Statusregister immer 0, nach ASL wird es gesetzt wenn sich das MSB, d.h. das Vorzeichen ändert.
Na ja, wenn ich diese zum Teil lange diskutierten Beiträge lese, ist für mich klar, dass ich diesen Befehl wohl nur zum optimieren benutzen werde, ansonsten ist sra nur unnütz und vor allem verwirrend, wenn er eh nicht immer zum richtigen Resultat führt! Solchen Code zu unterhalten, vor allem wenn es später u.U. jemand anderes tun müsste, ist immer sehr Fehlerbehaftet. Für mich ist das alles andere als "Arithmetisch". Und dass man einen sinnlosen Befehl wie asl nur Vollständikeitshalber kreiert, ist für mich sowiso unverständlich. Hauptsache man ist verwirrt? Deshalb werde ich mich wohl an die Operatoren / und * halten, auch wenn sie vielleicht ein bisschen mehr ressourcen benötigen....
Thomas I. schrieb: > Deshalb werde ich mich wohl an die Operatoren / und * halten, auch wenn > sie vielleicht ein bisschen mehr ressourcen benötigen.... Ja, da ist der Fall. Der / braucht einiges, der shift ist ja "nur" eine Umverdrahtung mit Vorzeichenerweiterung... Hier mal eine VHDL-Beschreibung zum Test:
1 | library IEEE; |
2 | use IEEE.STD_LOGIC_1164.ALL; |
3 | use IEEE.NUMERIC_STD.ALL; |
4 | |
5 | entity DivVsShift is |
6 | port ( slv : in std_logic_vector (7 downto 0); |
7 | |
8 | uns_shift : out std_logic_vector (7 downto 0); |
9 | uns_div : out std_logic_vector (7 downto 0); |
10 | sig_shift : out std_logic_vector (7 downto 0); |
11 | sig_div : out std_logic_vector (7 downto 0) |
12 | );
|
13 | end DivVsShift; |
14 | |
15 | architecture Behavioral of DivVsShift is |
16 | begin
|
17 | |
18 | uns_div <= std_logic_vector( unsigned(slv) / 8); |
19 | uns_shift <= std_logic_vector( shift_right( unsigned(slv), 3)); |
20 | |
21 | sig_div <= std_logic_vector( signed(slv) / 8); |
22 | sig_shift <= std_logic_vector( shift_right( signed(slv), 3)); |
23 | |
24 | end Behavioral; |
Und die Testbench:
1 | LIBRARY ieee; |
2 | USE ieee.std_logic_1164.ALL; |
3 | USE ieee.numeric_std.ALL; |
4 | use std.textio.all; |
5 | |
6 | ENTITY tb_DivVsShift_vhd IS |
7 | END tb_DivVsShift_vhd; |
8 | |
9 | ARCHITECTURE behavior OF tb_DivVsShift_vhd IS |
10 | COMPONENT DivVsShift |
11 | PORT( |
12 | slv : IN std_logic_vector(7 downto 0); |
13 | uns_shift : OUT std_logic_vector(7 downto 0); |
14 | uns_div : OUT std_logic_vector(7 downto 0); |
15 | sig_shift : OUT std_logic_vector(7 downto 0); |
16 | sig_div : OUT std_logic_vector(7 downto 0) |
17 | );
|
18 | END COMPONENT; |
19 | |
20 | SIGNAL slv : std_logic_vector(7 downto 0) := (others=>'0'); |
21 | |
22 | SIGNAL uns_shift : std_logic_vector(7 downto 0); |
23 | SIGNAL uns_div : std_logic_vector(7 downto 0); |
24 | SIGNAL sig_shift : std_logic_vector(7 downto 0); |
25 | SIGNAL sig_div : std_logic_vector(7 downto 0); |
26 | |
27 | BEGIN
|
28 | uut: DivVsShift PORT MAP( |
29 | slv => slv, |
30 | uns_shift => uns_shift, |
31 | uns_div => uns_div, |
32 | sig_shift => sig_shift, |
33 | sig_div => sig_div |
34 | );
|
35 | |
36 | tb : process |
37 | variable l : line; |
38 | begin
|
39 | |
40 | for i in -128 to 127 loop |
41 | |
42 | slv <= std_logic_vector( to_signed(i, 8)); |
43 | wait for 6 ns; -- approx. the real time, for synthesis report |
44 | |
45 | write(l, "i: " & integer'image( i) & ht); |
46 | write(l, "uns_shift: " & integer'image( to_integer( unsigned(uns_shift))) & ht); |
47 | write(l, "uns_div: " & integer'image( to_integer( unsigned(uns_div))) & ht); |
48 | write(l, "sig_shift: " & integer'image( to_integer( signed(sig_shift))) & ht); |
49 | write(l, "sig_div: " & integer'image( to_integer( signed(sig_div))) & ht); |
50 | writeline(output, l); |
51 | |
52 | end loop; |
53 | |
54 | wait; -- will wait forever |
55 | end process; |
56 | END; |
Und der Output:
1 | |
2 | i: -128 uns_shift: 16 uns_div: 16 sig_shift: -16 sig_div: -16 |
3 | i: -127 uns_shift: 16 uns_div: 16 sig_shift: -16 sig_div: -15 |
4 | i: -126 uns_shift: 16 uns_div: 16 sig_shift: -16 sig_div: -15 |
5 | : |
6 | : |
7 | i: -121 uns_shift: 16 uns_div: 16 sig_shift: -16 sig_div: -15 |
8 | i: -120 uns_shift: 17 uns_div: 17 sig_shift: -15 sig_div: -15 |
9 | i: -119 uns_shift: 17 uns_div: 17 sig_shift: -15 sig_div: -14 |
10 | : |
11 | : |
12 | i: -113 uns_shift: 17 uns_div: 17 sig_shift: -15 sig_div: -14 |
13 | i: -112 uns_shift: 18 uns_div: 18 sig_shift: -14 sig_div: -14 |
14 | i: -111 uns_shift: 18 uns_div: 18 sig_shift: -14 sig_div: -13 |
15 | i: -110 uns_shift: 18 uns_div: 18 sig_shift: -14 sig_div: -13 |
16 | i: -109 uns_shift: 18 uns_div: 18 sig_shift: -14 sig_div: -13 |
17 | i: -108 uns_shift: 18 uns_div: 18 sig_shift: -14 sig_div: -13 |
18 | i: -107 uns_shift: 18 uns_div: 18 sig_shift: -14 sig_div: -13 |
19 | : |
20 | : |
21 | i: -28 uns_shift: 28 uns_div: 28 sig_shift: -4 sig_div: -3 |
22 | i: -27 uns_shift: 28 uns_div: 28 sig_shift: -4 sig_div: -3 |
23 | i: -26 uns_shift: 28 uns_div: 28 sig_shift: -4 sig_div: -3 |
24 | i: -25 uns_shift: 28 uns_div: 28 sig_shift: -4 sig_div: -3 |
25 | i: -24 uns_shift: 29 uns_div: 29 sig_shift: -3 sig_div: -3 |
26 | i: -23 uns_shift: 29 uns_div: 29 sig_shift: -3 sig_div: -2 |
27 | i: -22 uns_shift: 29 uns_div: 29 sig_shift: -3 sig_div: -2 |
28 | i: -21 uns_shift: 29 uns_div: 29 sig_shift: -3 sig_div: -2 |
29 | i: -20 uns_shift: 29 uns_div: 29 sig_shift: -3 sig_div: -2 |
30 | i: -19 uns_shift: 29 uns_div: 29 sig_shift: -3 sig_div: -2 |
31 | i: -18 uns_shift: 29 uns_div: 29 sig_shift: -3 sig_div: -2 |
32 | i: -17 uns_shift: 29 uns_div: 29 sig_shift: -3 sig_div: -2 |
33 | i: -16 uns_shift: 30 uns_div: 30 sig_shift: -2 sig_div: -2 |
34 | i: -15 uns_shift: 30 uns_div: 30 sig_shift: -2 sig_div: -1 |
35 | i: -14 uns_shift: 30 uns_div: 30 sig_shift: -2 sig_div: -1 |
36 | i: -13 uns_shift: 30 uns_div: 30 sig_shift: -2 sig_div: -1 |
37 | i: -12 uns_shift: 30 uns_div: 30 sig_shift: -2 sig_div: -1 |
38 | i: -11 uns_shift: 30 uns_div: 30 sig_shift: -2 sig_div: -1 |
39 | i: -10 uns_shift: 30 uns_div: 30 sig_shift: -2 sig_div: -1 |
40 | i: -9 uns_shift: 30 uns_div: 30 sig_shift: -2 sig_div: -1 |
41 | i: -8 uns_shift: 31 uns_div: 31 sig_shift: -1 sig_div: -1 |
42 | i: -7 uns_shift: 31 uns_div: 31 sig_shift: -1 sig_div: 0 |
43 | i: -6 uns_shift: 31 uns_div: 31 sig_shift: -1 sig_div: 0 |
44 | i: -5 uns_shift: 31 uns_div: 31 sig_shift: -1 sig_div: 0 |
45 | i: -4 uns_shift: 31 uns_div: 31 sig_shift: -1 sig_div: 0 |
46 | i: -3 uns_shift: 31 uns_div: 31 sig_shift: -1 sig_div: 0 |
47 | i: -2 uns_shift: 31 uns_div: 31 sig_shift: -1 sig_div: 0 |
48 | i: -1 uns_shift: 31 uns_div: 31 sig_shift: -1 sig_div: 0 |
49 | i: 0 uns_shift: 0 uns_div: 0 sig_shift: 0 sig_div: 0 |
50 | i: 1 uns_shift: 0 uns_div: 0 sig_shift: 0 sig_div: 0 |
51 | i: 2 uns_shift: 0 uns_div: 0 sig_shift: 0 sig_div: 0 |
52 | i: 3 uns_shift: 0 uns_div: 0 sig_shift: 0 sig_div: 0 |
53 | i: 4 uns_shift: 0 uns_div: 0 sig_shift: 0 sig_div: 0 |
54 | i: 5 uns_shift: 0 uns_div: 0 sig_shift: 0 sig_div: 0 |
55 | i: 6 uns_shift: 0 uns_div: 0 sig_shift: 0 sig_div: 0 |
56 | i: 7 uns_shift: 0 uns_div: 0 sig_shift: 0 sig_div: 0 |
57 | i: 8 uns_shift: 1 uns_div: 1 sig_shift: 1 sig_div: 1 |
58 | i: 9 uns_shift: 1 uns_div: 1 sig_shift: 1 sig_div: 1 |
59 | : |
60 | : |
61 | i: 123 uns_shift: 15 uns_div: 15 sig_shift: 15 sig_div: 15 |
62 | i: 124 uns_shift: 15 uns_div: 15 sig_shift: 15 sig_div: 15 |
63 | i: 125 uns_shift: 15 uns_div: 15 sig_shift: 15 sig_div: 15 |
64 | i: 126 uns_shift: 15 uns_div: 15 sig_shift: 15 sig_div: 15 |
65 | i: 127 uns_shift: 15 uns_div: 15 sig_shift: 15 sig_div: 15 |
Wer lieber Bilder anguckt: siehe Anhang... Und in der Implementierung sehen uns_shift und uns_div genau gleich aus. sig_shift sieht ähnlich aus wie diese beiden, nur wird das Bit 4 (=Vorzeichen) auf die führenden 3 Bits ausgedehnt. Aber sig_div sieht komplett anders aus: da ist einiges mehr an Kombinatorik nötig (2 Addierer...). Demnach sieht hier der Ressourcenverbrauch so aus: der sig_div braucht 4 Slices, der sig_shift 0.
> ansonsten ist sra nur unnütz und vor allem verwirrend, wenn er eh nicht > immer zum richtigen Resultat führt! Klar, deshalb wird SRA auch in moderne CPUs immer noch eingebaut... ;) DIV liefert übrigens auch das falsche Ergebnis. Das korrekte Ergebnis wäre ja auch keine Ganzzahl. Dazu mal das Beispiel (-79 / 4) = -19,75 10110001 sra 2 = 11101100 = -20 10110001 div 2 = 11101101 = -19 Wie man leicht sieht liegt "sra 2" näher am korrekten Ergebnis als "div 2", der Rundungsfehler ist also kleiner. Zählt man die Fälle, wie oft welches Verfahren "näher" rundet, geht das im Großen und Ganzen unentschieden aus. Wenn einem das "Runden nach minus Unendlich" egal ist oder sogar gelegen kommt, nimmt man halt SRA. Braucht man "Runden zur 0", nimmt man DIV. ----- Was mich allerdings wirklich interessieren würde: Wenn SRL "logisch" und SRA "arithmetisch" ist, warum brauche ich dann zum Teilen einer vorzeichenlosen Ganzzahl SRL? Hat doch viel mit Zahlen und wenig mit binärer Logik zu tun. Die Frage bezieht sich auf die Benennung der Befehle, nicht auf die Funktionsweise ;)
logische Schiebeoperationen schieben immer den Initialisierungswert des Basistyps nach, arithmetische füllen Vorzeichen richtig auf
Thomas I. schrieb: > dass man einen sinnlosen Befehl wie asl nur Vollständikeitshalber > kreiert, ist für mich sowiso unverständlich. Hauptsache man ist > verwirrt? Ist dir schon mal der Gedanke gekommen, daß man Shift-Befehle zum Shiften eines Registers benutzen könnte? MfG Klaus
@ Klaus: > Ist dir schon mal der Gedanke gekommen, daß man Shift-Befehle zum > Shiften eines Registers benutzen könnte? Ja klar, nur erstens wirst du da wohl eher sll und srl nehmen und zweitens was hat asl dann mit "arithmetik" zu tun?(sra = aritmetical shift left) Das war denn auch meine Frage. @ Morin: div liefert meiner Meinung nach das richtige Ergebnis (rundet immer nach 0 ab). Aber das ist wohl Ansichtssache, was Abrunden heisst: nach 0 oder nach minus? Na ja, auf jeden fall bin ich geholfen ;-) Vielen Dank für eure Beiträge.
> div liefert meiner Meinung nach das richtige Ergebnis (rundet immer nach > 0 ab). Aber das ist wohl Ansichtssache, was Abrunden heisst: nach 0 oder > nach minus? Zum einen das, aber vor allem ist die Frage warum abrunden das "richtige" Ergebnis liefert und nicht z.B. "echt runden", was ja im Schnitt einen kleineren Rundunsfehler verursacht. DIV ist nunmal definiert als Division mit Abrunden, aber das ist halt nur so weil es so definiert wurde. Es gibt erst mal keinen Grund, warum SRA das genauso machen soll.
Morin schrieb: > aber das ist halt nur so weil es so definiert wurde. > Es gibt erst mal keinen Grund, warum SRA das genauso machen soll. Das schon, aber urigerweise ist jeder überrascht, wenn er hinter dieses "Geheimnis" kommt. Weil es ja im positiven Bereich so gut funktioniert hat... ;-)
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.