jumps wenn wan und wo :(?

25/12/2009 - 18:18 von Jens Kallup | Report spam
Hallo,

in meinen Compiler verwende ich gerade nur ein
jump Statement - jne: jump not equal ...
(Yacc/Pascal Code)

ifRelation
: '=' { $<lbl>$.if_reltype := 0; }
| '#' { $<lbl>$.if_reltype := 1; }
| '<' { $<lbl>$.if_reltype := 2; }
| '>' { $<lbl>$.if_reltype := 3; }
| '<' '=' { $<lbl>$.if_reltype := 4; }
| '>' '=' { $<lbl>$.if_reltype := 5; }
| '<' '>' { $<lbl>$.if_reltype := 6; }
| '=' '<' { $<lbl>$.if_reltype := 4; }
| '=' '>' { $<lbl>$.if_reltype := 5; }
;

...
data_code.Add(#9 + 'fxch st1');
data_code.Add(#9 + 'fucompp');
data_code.Add(#9 + 'fstsw ax');
data_code.Add(#9 + 'sahf');

case $<lbl>2.if_reltype of
0: data_code.Add(#9 + 'je near Le' +
IntToStr($<lbl>$.else_label)); break;
1: data_code.Add(#9 + 'jne near Le' +
IntToStr($<lbl>$.else_label)); break;
2: data_code.Add(#9 + 'jle near Le' +
IntToStr($<lbl>$.else_label)); break;
end;
...

wann muss ich welches J anwenden.
wie weiss ich (oder vielmehr der Compiler) wenn
eine zahl/konstrukt vorzeichen/vorzeichenlos ist?

Gruß
Jens
 

Lesen sie die antworten

#1 Jan Seiffert
25/12/2009 - 22:07 | Warnen spam
Jens Kallup schrieb:
Hallo,

in meinen Compiler verwende ich gerade nur ein
jump Statement - jne: jump not equal ...
(Yacc/Pascal Code)

ifRelation
: '=' { $<lbl>$.if_reltype := 0; }


JE
| '#' { $<lbl>$.if_reltype := 1; }


JNE ??
| '<' { $<lbl>$.if_reltype := 2; }


JB / JL
| '>' { $<lbl>$.if_reltype := 3; }


JA / JG
| '<' '=' { $<lbl>$.if_reltype := 4; }
| '>' '=' { $<lbl>$.if_reltype := 5; }


JAE / JGE
| '<' '>' { $<lbl>$.if_reltype := 6; }


JNE
| '=' '<' { $<lbl>$.if_reltype := 4; }


JBE / JLE
| '=' '>' { $<lbl>$.if_reltype := 5; }


????, is doch das gleiche wie 5?
;



Das gibt es dann noch mal in der verneinten form.
Es hilft zu wissen fuer was die Buchstaben stehen:
E - equal
B - below
L - less
A - above
G - greater
N - not

JNBE ist dann "jump if not below or equal"

above & greater bzw. below & less sind von der menschlichen Bedeutung sehr
aehnlich, sie sind aber unterschiedlich fuer unsigned/signed.

...

wann muss ich welches J anwenden.


Dann wenns passt.
Was nichts mit dem Jxx zu tun hat, sondern mit der Instruction die den Vergleich
herstellt. Denn sie gibt die flags vor, nach denen die jxx arbeiten.
Wenn du die Vergleichsinstruktion "grade aus" produzierst, sind auch die
Spruenge recht einfach.
Erst wenn du "komische" Vergleiche hast, dann wird das auch mit den Spruengen
etwas schwieriger.

wie weiss ich (oder vielmehr der Compiler) wenn
eine zahl/konstrukt vorzeichen/vorzeichenlos ist?




Das ergibt die Sprache die du compilierst und ihre Regeln welche Typen es gibt,
und in welchem Kontext ein vergleich ausgefuehrt wird.

Bei alle dem darfst du nicht vergessen, das du auch andere xx an einem jxx
nehmen kannst, wenn du nur den Vergleich passend machst.
Du willst also eigentlich eine Optimierer Stufe, die den einfachsten/passenden
Vergleich/Sprung raussucht (zur not nachdem erstmal ein "funktionierender"
erzeugt wurde). Denn manchmal willst du Vergleiche "umdrehen" damit es besser
passt und solche Spielchen.

Besorg dir mal das Intel SDM und schau dort unter Jxx, dort sind alle aufgefuert
und welche Flags sie checken. Die mit Vorzeichen haben meist so was wie "SF=OF".

Aber andererseits bevor man sich das Hirn verdreht da irgendwie die Flags zu
tracken, sollte man einfach dem Ausdruck folgen, sonst kommt meist nur sch***e
bei rum.
(Das musste ich mal auf einem µController machen, der hatte eben nur "teste 1
bit und springe, oder nicht", da musste man dann eben wirklich sagen "btjs 3,
flags", damit checked man dann das Carry flag nur was der test in diesem
zusammenhang bedeutet, ich hatte eigentlich jeden Test im ersten Anlauf dann
meist immer falsch, macht spass wenn man das dann nur mit nem Oszi an LEDs
debuggen kann...)

Wenn du mal den Code laut vorliest:

wenn a kleiner 16
tu was

dann ist das:
cmp a, 16
jb / jl tu_was

oder:
cmp a, 16
jnb / jnl nach_tu_was
tu was
nach_tu_was:

Die Konstante kann jetzt nur an einer Stelle in der Instruktion sein, aber hier
passt es grad. Wenn der User z.B. schreibt:

Wenn 16 groesser a

willst du erzeugen
cmp 16, a
ja /jg

Das geht aber nicht. Du kannst jetzt die 16 in ein register holen und den
vergleich so ausfuehren wie du willst, aber dann hast du wieder Register
pressure (und dein Register allocator war ja auch nicht vorhanden...).

Oder du drehst den Vergleich eben um.

Und man kann sich auch das Hirn damit verrenken das CMP intern ein SUB macht,
nur das Ergebniss wegwirft, und eben dann immer im Kopf damit rumwurgeln das
entweder "a - 16" oder "16 - a" da steht, aber obs hilft...
Nebenbei, die grosse Kunst ist dann aus sowieso anfallenden Operationen die
erzeugten flags zu nutzen. Du machst am Ende eines loops immer "sub reg, 4"
dann kannst du danach auch gleich das passende Jxx einfuegen ohne ein CMP.
Achja, und TEST gibts auchnoch, was aber auch nur ein AND ist dass das Ergebniss
wegwirft. Davon ist meist nur das "zero/nonzero" interresant.

Gruß
Jens


Gruss
Jan

Have you ever noticed that the Klingons are all speaking unix?
"Grep ls awk chmod." "Mknod ksh tar imap."
"Wall fsck yacc!" (that last is obviously a curse of some sort)

Ähnliche fragen