MASM nach NASM übersetzen ...
-
'mov di, [JumpTable + (cx*2)]' geht aus 2 Gründen nicht:
1. es gibt keine Skalierung
2. CX kann nicht zur addressierung verwendet werden: nur BX,BP,DI,SI
(sieh Bild für mögliche Kombinationen)Du musst die Berechnung 'von Hand' machen:
z.B.:
mov di,cx shl di,1 mov di,[di+JumpTable]
-
Ack. Das liegt auch nicht am NASM.
Was ansonsten die Schmutzverletzung angeht, solltest du vielleicht mal genau untersuchen, was nach dem Linken beim Aufruf der externen Funktionen eigentlich an Code generiert wird. Ich hatte da zumindest mit verschiedenen Linkern zT. recht eigenartige Resultate, wie Aufrufe in extra generierte Jump-Tables.
BTW:
Das Offset einer Variable holst du dir in NASM mitVar db 00 ;... mov di, Var
-
masm schrieb:
z.B.:
mov di,cx shl di,1 mov di,[di+JumpTable]
Mir ist die Adressierung über Segment:Offset durchaus bekannt. Dein Code kann aber so nicht funktionieren, würde ich sagen.
Angenommen:
Segment = 0x1000
Offset = 0x0040Dann wäre die physikalische Adresse:
0x1000 << 1 + 0x0040 = 0x10000 + 0x0040 = 0x10040Du würdest hier aber die "1" von 0x1000 aus dem Register "rausschieben" (shl di, 1)
@Nobuo T
Du sprichst wahrscheinlich das wegen dem "lea" an oder? Hab ich nur gemacht, weil ich den Grund für Access Violation gesucht habe. Der springt bei den Aufrufen von _gets und _printf an vollkmommen falsche Stellen (stellenweiße im Bereich von _main)
-
FrEEzE2046 schrieb:
Mir ist die Adressierung über Segment:Offset durchaus bekannt. Dein Code kann aber so nicht funktionieren, würde ich sagen.
[......]Oha. Da geht aber einiges ordentlich daneben. Vielleicht willst du dein Verstaendnis von logischen Operationen und der "Adressierung über Segment:Offset" nochmal ueberdenken?
FrEEzE2046 schrieb:
Der springt bei den Aufrufen von _gets und _printf an vollkmommen falsche Stellen (stellenweiße im Bereich von _main)
Jo, das mit dem offset habe ich wegen deinem lea erwaehnt. Benutzt man ansonsten so eher nicht.
Die Umsetzung des Codes sieht vom Prinzip sonst aber IMHO korrekt aus. Ich wuerde also darauf tippen, dass dein Problem irgendwo bei deiner Wahl des Ausgabeformats von NASM, der korrekten Einbettung deines Codes darin (Korrekte Segmentanordnung, Orgs, usw.) oder beim Linken liegt.
-
@Nobuo T
Okay, mein Beispiel wegen dem Bitshifting war quatsch, aber dennoch sehe ich die Problematik.
Kannst du mir das vielleicht näher erläutern, was bei mir "gründlich daneben geht"?
Wenn du ein 16 Bit Register einem bitshift nach links um 1 vollziehst, dann fällt der Wert von Bit 0 komplett weg nnd die Wertigkeit der anderen Bits verändert sich um x * 2^(n-1)Was ist daran falsch?
-
Ok, dann also Stueck fuer Stueck:
Im Prinzip hast du recht, dass es beim shiften (wie beim Multiplizieren, Dividieren, Addieren, usw.) zu einem Ueberlauf kommen kann.
Das ist zB. bei einem Linksshift dann der Fall, wenn das MSB (most significant bit = Bit mit hoechster Wertigkeit = idR. bit n-1 -> bei n=16 Bit also Bit 15) 1 ist und dann quasi hinten rausfaellt.
Sollte hier aber keine grosse Rolle spielen, da du zum einen das selbe Problem auch haettest, wenn du so etwas schreiben koenntest wie "mov ax, [di*2]" und
man idR. diesen Fall eh abfangen sollte, indem man vor der Berechnung der Adresse in ein Array prueft, ob der Index die Arraygrenzen (oder eben Adressierungsgrenzen) ueberschreitet.Dann nochmal zur Adressierung im RM in deinem Beispiel:
Angenommen:
Segment = 0x1000
Offset = 0x0040Dann wäre die physikalische Adresse:
0x1000 << 1 + 0x0040 = 0x10000 + 0x0040 = 0x10040Das shifting selbst ist falsch, wie du schon festgestellt hast.
Dann kommt hinzu, dass du das offset skalieren/shiften solltest, nicht den Segmentanteil (den laesst man falls moeglich immer konstant).
Ausserdem wird eine physikalische Adresse aus Segment:Offset im RM wie folgt gebildet:
pAddr = Segment * 16 + OffsetDh. dein Beispiel muesste korrekt so lauten:
pAddr = (0x0040 << 1) + (0x1000 << 4) = 0x10080
-
Sorry,
dass:
0x1000 << 1 + 0x0040 = 0x10000 + 0x0040 = 0x10040
soll natürlich:
0x1000 << 4 + 0x0040 = 0x10000 + 0x0040 = 0x10040
heißen. Wie du sieht, hatte ich aber trotzdem korrekt gerechnet; war nur ein Tippfehler.
Wir reden etwas aneinander vorbei. Was ich hier kritisiere ist, dass du das Offset um 1 Bit nach links verschiebst, weil ich mir die Frage nach dem "warum" stelle.EDIT:
Ich gehe davon aus, dass ihr das "shl di, 1" auf meine Multiplikation "* 2" bezieht. Ist jedoch Quatsch. Ich habe das gemacht, da ich ein Pointer-Array habe, wobei jeder Pointer im 16-Bit Mode 2 Byte groß ist. In "cx" lag bei mir der Index dieses Arrays, daher die Multiplikation.Warum ihr dass jetzt als Faustregel in die normale Berechnung der physikalischen Adresse im Real Mode reingehauen habt, verstehe ich nicht.
phys. (lineare) Adresse = Segment * 16 + Offset = Segment << 4 + Offset
-
Hier mal wie sich eine Adresse zusammensetzt (20Bit)
[Segmentselektor: CS,DS,SS,...] |15 |11 |0 [Offset: Register und/oder imm16] + |15 |0 -------------------------------------------------- [ 20 Bit Adresse ] |20 |0
Wenn man also die echte Adresse ausrechnen will, muss man den Inhalt des Segmentregisters um 4 nach links shiften und dann das Offset dazu addieren:
p = ([CS,DS,SS...] << 4) + OffsetDas Offset kann sowohl durch ein Register/Registerkombination und/oder einem 16Bit immediate (Zahlenwert)gegeben sein.
Hieraus ergibt sich im Übrigen auch, dass man Ein und die Selbe Adresse durch verschieden paare von Segmentregister und Offset Bilden kann.
-
@masm
Nicht böse gemeint, aber habe ich dem in irgendeiner Art und Weise widersprochen?
-
da hab ich deinen letzten Beitrag falsch verstanden
-
FrEEzE2046 schrieb:
phys. (lineare) Adresse = Segment * 16 + Offset = Segment << 4 + Offset
Macht für mich halt nur keinen Sinn, warum in den Beispielen von euch immer das Offset shl 1 gemacht wurde.
Aber da habt ihr euch wohl von meiner Umrechnung vom Index auf die 16-Bit Adresse aus meinem Beispeil irre machen lassen.
-
Ok, ich sehe ein es war ein Fehler, dein Beispiel aufzugreifen, da es offenbar nur noch mehr Verwirrung gestiftet hat.
Die Formel zur Berechnung der physikalischen Adresse im RM hast du da jetzt korrekt gepostet.
Zu der Sache mit dem shift bleibt sonst nur nochmal festzuhalten, dass es in 16Bit-Adressen keine Registerskalierung (*2, *4, etc.) oder -summanden gibt und du deshalb in so einem Fall entsprechende Berechnungen extra ausfuehren musst:
mov ax, [di * 2] ; Skalierung funktioniert mit 16Bit-Adressen nicht! ;stattdessen aequivalent: shl di, 1 mov ax, [di]
Das hat dir "masm" bereits ganz zu Anfang geschrieben, worauf dein eigenartiges Beispiel folgte...
-
Nobuo T schrieb:
worauf dein eigenartiges Beispiel folgte...
Okay, ich habe ein falsches Beispiel gepostet (bzgl shl 1, statt 4) und du hast die Berechnung im Real Mode falsch beschrieben. Es ist schließlich nicht vorgesehen den Offset immer * 2 (shl 1) zu rechnen. Dass hatte im übrigen nichts mit meinem Beispiel von oben zu tun, wo ich den Index auf die Adresse (16-Bit) anpassen musste.
Irgendwo haben wir doch eh das selbe gemeint, aber hatten Schwierigkeiten es auch so auszudrücken. Thema erledigt.
-
FrEEzE2046 schrieb:
du hast die Berechnung im Real Mode falsch beschrieben.
Wo denn?
-
Nobuo T schrieb:
Wo denn?
Hier:
Nobuo T schrieb:
Dh. dein Beispiel muesste korrekt so lauten:
pAddr = (0x0040 << 1) + (0x1000 << 4) = 0x10080Mein Beispiel war:
FrEEzE2046 schrieb:
Angenommen:
Segment = 0x1000
Offset = 0x0040
-
FrEEzE2046 schrieb:
Nobuo T schrieb:
Wo denn?
Hier:
Nobuo T schrieb:
Dh. dein Beispiel muesste korrekt so lauten:
pAddr = (0x0040 << 1) + (0x1000 << 4) = 0x10080Mein Beispiel war:
FrEEzE2046 schrieb:
Angenommen:
Segment = 0x1000
Offset = 0x0040Da hast du wohl was falsch verstanden.
Das ist, wie im zitierten Beitrag steht, meine Interpretation deines Beispiels (warum postest du eigentlich ueberhaupt nur diesen kleinen nichtssagenden Ausschnitt desselben?)?
Moeglich, dass ich deine Frage mit dem Beispiel falsch interpraetiert habe, allerdings habe ich nirgendwo geschrieben, dass der Teil, den du hier zitierst, die allgemeine Formel fuer die physikalische Adressberechnung im RM sei - die steht naemlich direkt darueber.
-
@ Nobuo T
Du hast einfach die beiden Beispiele zusammen "gewurschtelt". Daher auch die Missverständnise.
Die Formel für die Berechnung der phys. Adresse hast du darüber richtig gepostet, dass stimmt natürlich.