Assemblercodes für das neue X4

    Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

    • Hier nochmal was zum Thema Arrays und Bereiche mit LongInts

      FindMax findet das Maximum. Parameter 1 ist das erste Element des Arrays oder die Bereichsadresse und Parameter 2 die Anzahl der Elemente (oder Anzahl Longs im Bereich). Rückgabe ist der größte enthaltene Wert.

      Quellcode

      1. ASM "FindMax", 2
      2. PUSH EBX
      3. PUSH ECX
      4. PUSH ESI
      5. MOV ESI, PAR1 // Zieladresse
      6. MOV ECX, PAR2 // Größe
      7. MOV EBX, $FFFFFFFF // Minimalwert als Maximum vorgeben
      8. CLD
      9. @@maSchleife:
      10. LODSD // Wert holen
      11. CMP EAX, EBX // mit Maximum vergleichen
      12. JL @@maNOM // wenn kleiner, Sprung
      13. MOV EBX, EAX // neues Maximum notieren
      14. @@maNOM:
      15. LOOP @@maSchleife // wiederholen, bis ECX = 0
      16. MOV EAX, EBX // notiertes Maximum in Ausgaberegister
      17. // gepuschte Register in umgekehrter Reihenfolge wieder holen
      18. POP ESI
      19. POP ECX
      20. POP EBX
      21. ENDASM
      Alles anzeigen

      FindMaxI ist nahezu identisch. Als dritter Parameter kommt noch die Adresse einer Profanvariablen hinzu. Diese nimmt den Index des gefundenen Maximums auf. Bei Bereichen ist der Wert mit 4 zu multiplizieren, um den Offset im Bereich zu erhalten. Anstelle der Adresse einer Profanvariablen kann auch 0 stehen, dann wird der Index nicht ermittelt.

      Quellcode

      1. ASM "FindMaxI", 3
      2. PUSH EBX
      3. PUSH ECX
      4. PUSH EDX
      5. PUSH ESI
      6. PUSH EDI
      7. MOV ESI, PAR1 // Zieladresse
      8. MOV ECX, PAR2 // Größe, immer Anzahl Werte
      9. MOV EDI, PAR3 // Adresse Profan-Variable für gefundenen Index
      10. MOV EDX, ECX // Größe merken
      11. MOV EBX, $FFFFFFFF // Minimalwert als Maximum vorgeben
      12. CLD
      13. @@maSchleifeI:
      14. LODSD // Wert holen
      15. CMP EAX, EBX // mit Maximum vergleichen
      16. JL @@maNOMI // wenn kleiner, Sprung
      17. MOV EBX, EAX // neues Maximum notieren
      18. OR EDI, EDI // Test ob Variablenadresse angegenen
      19. JZ @@maNOMI // wenn 0, Sprung
      20. PUSH EDX // Arraygröße auf Stack retten
      21. SUB EDX, ECX // Aktueller Index = Größe - NichtBearbeitet
      22. MOV [EDI], EDX // Aktueller Index in Profan-Variable schreiben
      23. POP EDX // Arraygröße zurückholen
      24. @@maNOMI:
      25. LOOP @@maSchleifeI // wiederholen, bis ECX = 0
      26. MOV EAX, EBX // notiertes Maximum in Ausgaberegister
      27. // gepuschte Register in umgekehrter Reihenfolge wieder holen
      28. POP EDI
      29. POP ESI
      30. POP EDX
      31. POP ECX
      32. POP EBX
      33. ENDASM
      Alles anzeigen

      Das Gleiche für den kleinsten Wert

      Quellcode

      1. ASM "FindMin", 2
      2. PUSH EBX
      3. PUSH ECX
      4. PUSH ESI
      5. MOV ESI, PAR1 // Zieladresse
      6. MOV ECX, PAR2 // Größe
      7. MOV EBX, $7FFFFFFF // Maximalwert als Minimum vorgeben
      8. CLD
      9. @@miSchleife:
      10. LODSD // Wert holen
      11. CMP EAX, EBX // mit Minimum vergleichen
      12. JG @@miNOM // wenn größer, Sprung
      13. MOV EBX, EAX // Neues Minimum notieren
      14. @@miNOM:
      15. LOOP @@miSchleife // wiederholen bis ECX = 0
      16. MOV EAX, EBX // notiertes Maximum in Ausgaberegister
      17. // gepuschte Register in umgekehrter Reihenfolge wieder holen
      18. POP ESI
      19. POP ECX
      20. POP EBX
      21. ENDASM
      Alles anzeigen

      Und mit Ermittlung des Index

      Quellcode

      1. ASM "FindMinI", 3
      2. PUSH EBX
      3. PUSH ECX
      4. PUSH EDX
      5. PUSH ESI
      6. PUSH EDI
      7. MOV ESI, PAR1 // Zieladresse
      8. MOV ECX, PAR2 // Größe, immer Anzahl Werte
      9. MOV EDI, PAR3 // Adresse Profan-Variable für gefundenen Index
      10. MOV EDX, ECX // Größe merken
      11. MOV EBX, $7FFFFFFF // Maximalwert als Minimum vorgeben
      12. CLD
      13. @@miSchleifeI:
      14. LODSD // Wert holen
      15. CMP EAX, EBX // mit Minimum vergleichen
      16. JG @@miNOMI // wenn größer, Sprung
      17. MOV EBX, EAX // Neues Minimum notieren
      18. OR EDI, EDI // Test ob Variablenadresse angegenen
      19. JZ @@miNOMI // wenn 0, Sprung
      20. PUSH EDX // Arraygröße auf Stack retten
      21. SUB EDX, ECX // Aktueller Index = Größe - NichtBearbeitet
      22. MOV [EDI], EDX // Aktueller Index in Profan-Variable schreiben
      23. POP EDX // Arraygröße zurückholen
      24. @@miNOMI:
      25. LOOP @@miSchleifeI // wiederholen, bis ECX = 0
      26. MOV EAX, EBX // notiertes Maximum in Ausgaberegister
      27. // gepuschte Register in umgekehrter Reihenfolge wieder holen
      28. POP EDI
      29. POP ESI
      30. POP EDX
      31. POP ECX
      32. POP EBX
      33. ENDASM
      Alles anzeigen

      Und hier ein kleines Demo

      Quellcode

      1. Window 800, 840
      2. Declare Int A[50], Wert, Index
      3. Declare Memory Bereich
      4. Dim Bereich, 300
      5. Randomize
      6. WhileLoop 0, 49
      7. Wert = Rnd(9000) - 4500
      8. A[&Loop] = Wert
      9. Long Bereich, &Loop * 4 = Wert
      10. EndWhile
      11. CLS
      12. ASM "FindMaxI", 3
      13. PUSH EBX
      14. PUSH ECX
      15. PUSH EDX
      16. PUSH ESI
      17. PUSH EDI
      18. MOV ESI, PAR1 // Zieladresse
      19. MOV ECX, PAR2 // Größe, immer Anzahl Werte
      20. MOV EDI, PAR3 // Adresse Profan-Variable für gefundenen Index
      21. MOV EDX, ECX // Größe merken
      22. MOV EBX, $FFFFFFFF // Minimalwert als Maximum vorgeben
      23. CLD
      24. @@maSchleifeI:
      25. LODSD // Wert holen
      26. CMP EAX, EBX // mit Maximum vergleichen
      27. JL @@maNOMI // wenn kleiner, Sprung
      28. MOV EBX, EAX // neues Maximum notieren
      29. OR EDI, EDI // Test ob Variablenadresse angegenen
      30. JZ @@maNOMI // wenn 0, Sprung
      31. PUSH EDX // Arraygröße auf Stack retten
      32. SUB EDX, ECX // Aktueller Index = Größe - NichtBearbeitet
      33. MOV [EDI], EDX // Aktueller Index in Profan-Variable schreiben
      34. POP EDX // Arraygröße zurückholen
      35. @@maNOMI:
      36. LOOP @@maSchleifeI // wiederholen, bis ECX = 0
      37. MOV EAX, EBX // notiertes Maximum in Ausgaberegister
      38. // gepuschte Register in umgekehrter Reihenfolge wieder holen
      39. POP EDI
      40. POP ESI
      41. POP EDX
      42. POP ECX
      43. POP EBX
      44. ENDASM
      45. ASM "FindMinI", 3
      46. PUSH EBX
      47. PUSH ECX
      48. PUSH EDX
      49. PUSH ESI
      50. PUSH EDI
      51. MOV ESI, PAR1 // Zieladresse
      52. MOV ECX, PAR2 // Größe, immer Anzahl Werte
      53. MOV EDI, PAR3 // Adresse Profan-Variable für gefundenen Index
      54. MOV EDX, ECX // Größe merken
      55. MOV EBX, $7FFFFFFF // Maximalwert als Minimum vorgeben
      56. CLD
      57. @@miSchleifeI:
      58. LODSD // Wert holen
      59. CMP EAX, EBX // mit Minimum vergleichen
      60. JG @@miNOMI // wenn größer, Sprung
      61. MOV EBX, EAX // Neues Minimum notieren
      62. OR EDI, EDI // Test ob Variablenadresse angegenen
      63. JZ @@miNOMI // wenn 0, Sprung
      64. PUSH EDX // Arraygröße auf Stack retten
      65. SUB EDX, ECX // Aktueller Index = Größe - NichtBearbeitet
      66. MOV [EDI], EDX // Aktueller Index in Profan-Variable schreiben
      67. POP EDX // Arraygröße zurückholen
      68. @@miNOMI:
      69. LOOP @@miSchleifeI // wiederholen, bis ECX = 0
      70. MOV EAX, EBX // notiertes Maximum in Ausgaberegister
      71. // gepuschte Register in umgekehrter Reihenfolge wieder holen
      72. POP EDI
      73. POP ESI
      74. POP EDX
      75. POP ECX
      76. POP EBX
      77. ENDASM
      78. Index = -1
      79. Print "Maximum im Array: " + Str$(FindMaxI(Addr(A[0]), 50, Addr(Index))) + " auf Index: " + Str$(Index)
      80. Index = -1
      81. Print "Maximum im Bereich: " + Str$(FindMaxI(Bereich, 50, Addr(Index))) + " an Adresse: " + Str$(Index * 4)
      82. Index = -1
      83. Print "Minimum im Array: " + Str$(FindMinI(Addr(A[0]), 50, Addr(Index))) + " auf Index: " + Str$(Index)
      84. Index = -1
      85. Print "Minimum im Bereich: " + Str$(FindMinI(Bereich, 50, Addr(Index))) + " an Adresse: " + Str$(Index * 4)
      86. WhileLoop 0,49
      87. Print &Loop, "Array : "; A[&LOOP], "Bereich : "; Long(Bereich, &LOOP * 4)
      88. EndWhile
      89. Print
      90. WaitKey
      91. Dispose Bereich
      92. End
      Alles anzeigen


      Gruß Volkmar

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Volkmar ()

    • Hier noch was mit Strings.

      Die Länge eines übergebenen Profanstrings Addr(x$) wird ausgelesen. Das macht eigentlich nicht viel Sinn, gegenüber Len(x$) bringt das keine Verbesserung, aber möglicherweise in irgendwelchen größeren Funktionen könnte es eingebaut werden.

      Quellcode

      1. ASM "PRFLen", 1
      2. PUSH ESI
      3. MOV ESI, Par1
      4. XOR EAX, EAX // Voreinstellung für Leerstring
      5. OR ESI, ESI // Prüfen auf Leerstring ("")
      6. // Profanstring hat immer die Adresse 0, wenn er leer ist!
      7. // damit also nie etwas tun!
      8. JZ @@Nul // Wenn ja, raus mit Ergebnis 0
      9. SUB ESI, 4 // Auf Längenwert positionieren (steht auf Stringadresse -4)
      10. LODSD // Längenwert laden in EAX
      11. @@Nul:
      12. POP ESI
      13. EndASM
      Alles anzeigen


      Die Länge eines nullterminierten Strings, dessen Anfangsadresse übergeben wird, wird ermittelt.

      Quellcode

      1. ASM "StrZLen", 1
      2. PUSH EDX
      3. PUSH ESI
      4. MOV ESI, Par1
      5. MOV EDX, ESI // Anfangsadresse merken
      6. @@S2:
      7. LODSB // Byte laden
      8. OR AL, AL // auf Null testen
      9. JNZ @@S2 // wenn <> Null, wiederholen mit nächstes Zeichen
      10. DEC ESI // Korrektur, weil ESI jetzt hinter Null zeigt
      11. MOV EAX, ESI
      12. SUB EAX, EDX // Endposition - Anfangsadresse ist Länge
      13. POP ESI
      14. POP EDX
      15. EndASM
      Alles anzeigen


      Ein String wird gedreht und steht anschließend rückwärts auf seiner ursprünglichen Postion. Es kann entweder die Adresse eines Profanstrings oder eine Bereichsadresse übergeben werden. Die Rückgabe ist die Anzahl der durchgeführten Schritte oder -1, wenn ein leerer Preofanstring übergeben wurde.

      Quellcode

      1. ASM "DrehString", 1
      2. PUSH ECX
      3. PUSH EDX
      4. PUSH ESI
      5. MOV EDX, Par1
      6. MOV EAX, -1
      7. OR EDX, EDX // Prüfen auf Profan-Leerstring ("")
      8. // oder Bereichsadresse 0
      9. JZ @@Nul // wenn ja: Ende mit EAX = -1
      10. MOV ESI, EDX
      11. XOR ECX, ECX
      12. @@S1:
      13. LODSB // abschließendes Nullbyte suchen
      14. OR AL, AL
      15. JNZ @@S1
      16. // ESI zeigt jetzt hinter das abschließende Nullbyte
      17. DEC ESI // auf Nullbyte
      18. MOV EAX, ESI
      19. SUB EAX, EDX // ist die Länge
      20. JZ @@Nul
      21. SHR EAX, 1 // Division /2 ist Schrittzahl
      22. JZ @@Nul // wenn Schrittzahl = 0, dann raus
      23. MOV ECX, EAX // Schrittzahl nach ECX
      24. PUSH ECX // Schrittzahl auf Stack merken
      25. DEC ESI // Endposition korrigieren vor Nullbyte
      26. @@Dreh:
      27. MOV AL, [ESI] // letztes Zeichen nach AL
      28. MOV AH, [EDX] // erstes Zeichen nach AH
      29. MOV [ESI], AH // AH auf erste Position schreiben
      30. MOV [EDX], AL // AL auf letzte Position schreiben
      31. DEC ESI // letzte Position -1
      32. INC EDX // erste Position +1
      33. LOOP @@Dreh // wiederholen bis ECX = 0 (berechnete Schrittzahl)
      34. POP EAX // gemerkte Schrittzahl nach EAX holen
      35. @@Nul:
      36. POP ESI
      37. POP EDX
      38. POP ECX
      39. EndASM
      Alles anzeigen


      Gruß Vokmar
    • Hallo Volkmar,
      Deine Codes sind wie immer sehr beispielhaft.
      Besonders die Kommentare hinter den Anweisungen
      finde ich sehr gut. Da lernt man was. :top:

      Was oben noch fehlt, ist der Mittelwert eines
      num. Profan-Arrays. Wenn es dir nichts ausmacht,
      könntest du es oben noch bei FindMaxI und FindMinI
      dazu machen.

      Das kommt dann mit in meine Sammlung ;-)
    • Hier erst mal was Einfaches. In einem Durchlauf werden Minimum und Maximum ermittelt und dann (Minimum / 2) + (Maximum / 2) zurück gegeben. Einfaches Aufaddieren aller Werte im Array und Division durch die Anzahl der Einträge macht mir da Bauchschmerzen, bei großen Zahlen oder einem großen Array können wir da irgendwann den möglichen Zahlenbereich überschreiten. Aber ich versuche das mal nachher.

      Quellcode

      1. ASM "FindMid", 2
      2. PUSH EBX
      3. PUSH ECX
      4. PUSH EDX
      5. PUSH ESI
      6. MOV ESI, Par1 // Zieladresse
      7. MOV ECX, Par2 // Größe
      8. MOV EBX, $7FFFFFFF // Maximalwert als Minimum vorgeben
      9. MOV EDX, $FFFFFFFF // Minimalwert als Maximum vorgeben
      10. CLD
      11. @@mdSchleife:
      12. LODSD
      13. CMP EAX, EBX
      14. JNL @@mdNoMin
      15. MOV EBX, EAX // neues Minimum notieren
      16. @@mdNoMin:
      17. CMP EAX, EDX
      18. JL @@mdNoMax
      19. MOV EDX, EAX // neues Maximum notieren
      20. @@mdNoMax:
      21. LOOP @@mdSchleife // Wiederholen bis ECX = 0
      22. // ECX ist hier immer 0
      23. // Nachfolgende Rechnung dividiert jede Zahl erst durch 2
      24. // wobei das Vorzeichen erhalten bleibt (SAR) und der Rest
      25. // im Carry-Flag landet
      26. CLC // CarryFlag löschen
      27. SAR EBX, 1 // Division /2, Rest im Carryflag
      28. JNC @@mdNoC1 // nichts im Carry
      29. INC ECX // ECX + 1, Wenn Carry
      30. @@mdNoC1:
      31. CLC // CarryFlag löschen
      32. SAR EDX, 1 // Division /2, Rest im Carryflag
      33. JNC @@mdNoC2 // nichts im Carry
      34. OR ECX, 1 // ECX = ECX or 1, kennzeichnet damit
      35. // das ein Divisionsrest vorliegt
      36. @@mdNoC2:
      37. MOV EAX, EBX // halbes Minimum nach EAX
      38. ADD EAX, ECX // Divisionsrest addieren
      39. ADD EAX, EDX // halbes Maximum addieren
      40. POP ESI
      41. POP EDX
      42. POP ECX
      43. POP EBX
      44. EndASM
      Alles anzeigen

      Übrigens, die vorherigen Codes habe ich nochmal geändert, die arbeiten nun alle konsequent mit LODSD und mit LOOP statt des unnötigen LOOPNZ.

      Gruß Volkmar
    • Und jetzt der Rest

      Hier werden nun alle Einträge aufaddiert und dann durch die Anzahl der Einträge dividiert.

      Quellcode

      1. ASM "FindMid2", 2
      2. PUSH EBX
      3. PUSH ECX
      4. PUSH EDX
      5. PUSH ESI
      6. MOV ESI, Par1 // Zieladresse
      7. MOV ECX, Par2 // Größe
      8. XOR EBX, EBX // EBX löschen, Anfangswert für Summierung
      9. CLD
      10. PUSH ECX // Anzahl Einträge notieren
      11. @@smSchleife:
      12. LODSD // Wert lesen
      13. Add EBX, EAX // Gelesenen Wert zu EBX addieren
      14. LOOP @@smSchleife // Wiederholen bis ECX = 0
      15. MOV EAX, EBX // Summe nach EAX
      16. XOR EDX, EDX // EDX löschen für Division EDX:EAX / ECX
      17. CMP EAX, 0 // ist negativ Zahl in EAX
      18. JBE @@smNoN // Nein
      19. DEC EDX // sonst negatives Vorzeichen nach EDX
      20. @@smNoN:
      21. POP ECX // notierte Anzahl Einträge zurückholen
      22. IDIV ECX // Summe durch Anzahl Einträge
      23. // Érgebnis steht in EAX
      24. POP ESI
      25. POP EDX
      26. POP ECX
      27. POP EBX
      28. EndASM
      Alles anzeigen

      Hier wird einfach die Summe über alle Einträge gebildet

      Quellcode

      1. ASM "FindSum", 2
      2. PUSH EBX
      3. PUSH ECX
      4. PUSH EDX
      5. PUSH ESI
      6. MOV ESI, Par1 // Zieladresse
      7. MOV ECX, Par2 // Größe
      8. XOR EBX, EBX // EBX löschen, Anfangswert für Summierung
      9. CLD
      10. @@mdSchleife:
      11. LODSD // Wert laden
      12. Add EBX, EAX // gelesenen Wert zu EBX addieren
      13. LOOP @@mdSchleife // Wiederholen bis ECX = 0
      14. MOV EAX, EBX // Summe nach EAX
      15. POP ESI
      16. POP EDX
      17. POP ECX
      18. POP EBX
      19. EndASM
      Alles anzeigen

      Beides steht immer unter dem Vorbehalt, daß man damit auch mit großen Zahlen oder großen Arrays schnell die Grenzen sprengen kann.


      Gruß Volkmar

      Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von Volkmar () aus folgendem Grund: Erster Code funktionierte nicht richtig, ist korrigiert

    • Super, vielen Dank.

      Sicher, man kann schon an die Grenzen kommen, aber
      -2 Mrd. bis + 2 Mrd. (ungefähr) ist schon was.
      Bei normalen Bedingungen genügt es ja.

      Um es wasserfest zu machen, könnte man noch
      die Obergrenze von 2.147.483.647 abfangen und
      -1 zurückgeben. Dann stürzt so leicht nichts ab.
    • Mit dem Abfangen ist das so eine Sache:
      2.147.483.600 wäre in jedem Falle noch erlaubt. Aber man kann nicht mehr alles addieren. Und Entsprechendes gilt auch für negative Zahlen. Wäre dann vor jeder Operation festzustellen, wieviel noch geht und dann prüfen, ob der nächste Wert innerhalb dieses Limits liegt :polizei:

      Gruß Volkmar
    • Ich glaube, so könnte es recht einfach mit dem Fehlerabfangen gehen (man muß eben erstmal die Möglichkeiten des Prozessors durchforsten ;-) )

      Eine einfache Rückgabe von -1 als Fehler geht nicht. Würde Array die beiden Werte -3 und 1 enthalten, wäre der Mittelwert -1 :-) Also als dritten Parameter wieder die Adresse einer Profan-Variablen übergeben. Die wird beim Eintritt in die Funktion erst mal mit 0 initialisiert. Tritt ein Überlauf auf, wird aus der Schleife nach @@smErr gesprungen und dort die Variable auf -1 gesetzt, dann die ganze Funktion verlassen.

      Quellcode

      1. ASM "FindMid3", 3
      2. PUSH EBX
      3. PUSH ECX
      4. PUSH EDX
      5. PUSH ESI
      6. PUSH EDI
      7. MOV ESI, Par1 // Zieladresse
      8. MOV ECX, Par2 // Größe
      9. MOV EDI, Par3 // Profan-Varibale als Fehlerflag
      10. XOR EBX, EBX // EBX löschen, Anfangswert für Summierung
      11. MOV [EDI], EBX // Fehlerflag löschen
      12. CLD
      13. DEC ECX
      14. PUSH ECX // Anzahl Einträge notieren
      15. JMP @@smSchleife
      16. @@smErr: // Bei Überlauf
      17. POP EAX
      18. MOV ECX, -1 // Fehlerwert
      19. MOV [EDI], ECX // Fehlerflag-Variable setzen
      20. JMP @@smEnd // Und zum Ende
      21. @@smSchleife:
      22. //xor ebx, ebx
      23. LODSD // Wert lesen
      24. // für später (noch einbauen):
      25. // Abstand EBX zum MaxMin-Wert $7FFFFFFF-$FFFFFFFF muß kleiner
      26. // sein als EAX abhängig von den Vorzeichen
      27. ADD EBX, EAX // Gelesenen Wert zu EBX addieren
      28. JO @@smErr // Bei Überlauf raus
      29. LOOP @@smSchleife // Wiederholen bis ECX = 0
      30. MOV EAX, EBX // Summe nach EAX
      31. XOR EDX, EDX // EDX löschen für Division EDX:EAX / ECX
      32. CMP EAX, 0 // ist negativ Zahl in EAX
      33. JG @@smNoN // Nein
      34. DEC EDX // sonst negatives Vorzeichen nach EDX
      35. @@smNoN:
      36. POP ECX // notierte Anzahl Einträge zurückholen
      37. IDIV ECX // Summe durch Anzahl Einträge
      38. // Érgebnis steht in EAX
      39. @@smEnd:
      40. POP EDI
      41. POP ESI
      42. POP EDX
      43. POP ECX
      44. POP EBX
      45. EndASM
      Alles anzeigen

      Das ganze würde dann so eingesetzt werden:

      Quellcode

      1. Declare Int Wert, Fehler
      2. Wert = FindMid3(Addr(A[0]), SizeOf(A[]), Addr(Fehler))
      3. If Fehler
      4. Print "Zahlenüberlauf beim Ermitteln des Mittelwertes"
      5. Else
      6. Print "Mittelwert ist " + Str$(Wert)
      7. EndIf



      Gruß Volkmar

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Volkmar ()

    • Da stimmt aber was nicht. Bei meinem Array

      Quellcode

      1. Declare Int a[5]
      2. Declare Int Wert, Fehler
      3. a[0] = 1
      4. a[1] = 2
      5. a[2] = 3
      6. a[3] = 4
      7. a[4] = 5
      8. ' Habe mal die ASM Routine platzsparend hier als Forumsbeitrag ausgelassen
      9. Wert = FindMid3(Addr(a[0]), SizeOf(a[]), Addr(Fehler))
      10. If Fehler
      11. Print "Zahlenüberlauf beim Ermitteln des Mittelwertes"
      12. Else
      13. Print "Mittelwert ist " + Str$(Wert)
      14. EndIf
      15. WaitKey
      16. End
      Alles anzeigen
      Kommt sowas raus : -715827880

      Da müßte doch 3 rauskommen.
    • Jetzt sehe ich auch, warum mir Fehler verborgen blieben. Bei meinen Testcodes hatte ich statt SizeOf(A[]) auch mal SizeOf(A[0]) stehen und auch die Zahl in der Declaration, also um eins daneben. Da liefern dann die Vergleichscodes teilweise falsche Ergebnisse.

      Die CPU allein kann nur mit Ganzzahlen umgehen. Es gibt nur Fehlerflags, die ein Überschreiten des zulässigen Zahlenbereichs anzeigen. Und für die Division ist das eine Ganzzahldivion mit dem Ganzzahlrest im EDX-Register. 7 / 4 wäre also 1 und in EDX steht dann eine 3. DIV und IDIV unterscheiden sich nur in der Behandlung des Vorzeichens. Echte Dezimalzahlen funktionieren ohne FPU nur über spezielle Mathebibliotheken, die üblicherweise in Hochsprachen eingebaut sind.

      Gruß Volkmar
    • Hochsprachen wie XProfan! :thumbsup:
      Wenn man selbst die Kommaverschiebung mitberechnet, klappt das schon:
      1.1 (11. mit 1x rechts) * 2.2 (22. mit 1x rechts) ==> (242. mit 2x links) = 2.42 :P
      Sehr weit kommt man mit 32 bit aber nicht, die FPU rechnet mit +/-53 bit und +/-10 bit Exponent, intern sogar mit 80, beim sin und cos mit bis zu 91 bit)
    • Ach ja: Mittels ProcAddr kann man auch XProfan-Prozeduren aus Assembler heraus aufrufen:

      Quellcode

      1. Proc PrintWert
      2. Parameters long A
      3. Print "A = " + Str$(A)
      4. Return 99
      5. EndProc
      6. Var Pointer pPrintWert = ProcAddr(PrintWert, 1)
      7. Print pPrintWert
      8. ASM "UseProcAddr", 1
      9. PUSH 128
      10. CALL Par1
      11. PUSH 23000
      12. CALL Par1
      13. ENDASM
      Alles anzeigen

      Gruß
      Roland
      Intel Duo E8400 3,0 GHz / 4 GB RAM / 1000 GB HDD / ATI Radeon HD4770 512 MB / Windows 7(32) - XProfan X3
      AMD Athlon II X2 2,9 GHz / 3 GB RAM / 500 GB HDD / ATI Radeon 3000 (onboard) / Windows 10(64) - XProfan X3


      http://www.xprofan.de
    • und mit Aufruf klappt das dann super:

      Quellcode

      1. cls:print "XProfan 14-Version = ";$profver:print
      2. ASM "UseProcAddr",1:PUSH 128:CALL Par1:PUSH 23000:CALL Par1:ENDASM
      3. PROC PrintWert :Parameters long A:Print "A = " + Str$(A):Return 88:EndProc
      4. Var Pointer pPrintWert = ProcAddr(PrintWert, 1)':Print pPrintWert
      5. UseProcAddr(pPrintWert):Waitinput 10000
      Das Merkblatt_XASM wurde entsprechend upgedated.
      Gruss
    • Ooops ... da habe ich doch glatt ein paar Zeilen verschlampt. Sorry!

      Übrigens mit "Print UseProcAddr(pPrintWert)" wird auch die 88 (oder in meinem Code die 99) ausgegeben.

      Gruß
      Roland
      Intel Duo E8400 3,0 GHz / 4 GB RAM / 1000 GB HDD / ATI Radeon HD4770 512 MB / Windows 7(32) - XProfan X3
      AMD Athlon II X2 2,9 GHz / 3 GB RAM / 500 GB HDD / ATI Radeon 3000 (onboard) / Windows 10(64) - XProfan X3


      http://www.xprofan.de