|
Das deutsche QBasic- und FreeBASIC-Forum Für euch erreichbar unter qb-forum.de, fb-forum.de und freebasic-forum.de!
|
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen |
Autor |
Nachricht |
St_W
Anmeldungsdatum: 22.07.2007 Beiträge: 949 Wohnort: Austria
|
Verfasst am: 17.08.2007, 19:09 Titel: QB Arrays in ASM bearbeiten |
|
|
Hallo!
Ich will den Bilschirmspeicher in einem in QB definiertem Array mit einer Assembler-Routine (als Lib in QB geladen) speichern, bzw. das Array wieder in den Bildschirmspeicher zurückschreiben (Textmodus 80 x 25). Ich bin absoluter Assembler Anfänger (was an meinem Versuch unterhalb wahrscheinlich erkennbar ist )
So sieht die Routine in QB aus, ist jedoch zu langsam (und nebenbei verbraucht Sie den doppelt so viel Speicher, als nötig wäre; integer --> 2Byte, 1Byte wird gespeichert))
Code: |
'Array in dem Bildschirm gespeichert wird:
DIM SHARED Bild(0 TO 3999) AS INTEGER
DEF SEG = &HB800 'Grafikspeicher
FOR q = 0 TO 3999 'Bytes einzeln aus Bildschirm-Speicher lesen...
Bild(q) = PEEK(q) '...und in Array schreiben
NEXT
|
Mein Versuch das Ganze in Assembler zu realisieren (Überschreibt jedoch bei einer Ausführung irgendetwas im Speicher und DOS stürzt ab )
Code: |
.MODEL medium,basic
.386
.STACK 100h
.CODE
;***********************************************************************
; SUB SaveScreen (BYVAL ArraySeg AS INTEGER, BYVAL ArrayOffs AS INTEGER)
;***********************************************************************
PUBLIC SaveScreen
SaveScreen PROC
; 08 Array Offset
; 06 Array Segment
; 04 Basic segment
; 02 Basic offset
; 00 BP
PUSH BP
MOV BP,SP
;Arraysegment nach DS, ArrayOffset nach AX
MOV AX,[BP+6]
MOV DS, AX
MOV AX,[BP+8]
MOV SI, AX
;Textsegement nach ES
MOV BX, 0B800H
MOV ES, BX
MOV BX, 0000H
MOV DI, BX
NextByteSave:
MOV CX, ES:[DI]
MOV DS:[SI], CX
INC DI
INC SI
CMP DI, 0F9FH
JBE NextByteSave
POP BP
RET
SaveScreen ENDP
END
|
Der Aufruf der obigen Assembler Sub (in Lib) von QB:
Code: |
DECLARE SUB SaveScreen (BYVAL ArraySeg AS INTEGER, BYVAL ArrayOffs AS INTEGER)
DIM SHARED Bild(0 TO 3999) AS INTEGER
SaveScreen VARSEG(Bild(0)), VARPTR(Bild(0))
|
Warum funktioniert das so nicht?
Weche Verbesserungsvorschläge habt Ihr für das Programm?
(Hab' das Grundgerüst der SUB übrigens von der DirectQB-Lib, Code von mir)
Danke im Voraus, St_W |
|
Nach oben |
|
|
Georgp24
Anmeldungsdatum: 30.06.2006 Beiträge: 81 Wohnort: Ahlen
|
Verfasst am: 18.08.2007, 21:57 Titel: |
|
|
Es gibt z.B. diese Assembler-Library, die Routinen zum Speichern und Wiederherstellen des Bildschirminhalts enthält, auch als ASM-source: ASMWIZ31
Kann hier heruntergeladen werden: http://www.tgh3.com/
Georg |
|
Nach oben |
|
|
Georgp24
Anmeldungsdatum: 30.06.2006 Beiträge: 81 Wohnort: Ahlen
|
Verfasst am: 18.08.2007, 22:12 Titel: |
|
|
Zu Deinem Code noch folgende Bemerkung:
1. man kann den Bildschirminhalt auch in einer String Variable speichern
2. statt der NextByteSave Schleife kann man auch einfach schreiben:
cld ;vorwärts
mov cx,4000 ;verschiebe 4000 byte
rep movsb ; verschiebe byte, wiederhole cx-mal
Georg |
|
Nach oben |
|
|
csde_rats
Anmeldungsdatum: 07.01.2007 Beiträge: 2292 Wohnort: Zwischen Sessel und Tastatur
|
Verfasst am: 18.08.2007, 22:17 Titel: |
|
|
Georgp24 hat Folgendes geschrieben: | man kann den Bildschirminhalt auch in einer String Variable speicherng | Es sei angemerkt, dass QB-Strings maximal 32 KB groß sind - der bildschirm ist höchstwahrscheinlich grösser... _________________ If hilfreicher_Beitrag then klick(location.here)
Klick |
|
Nach oben |
|
|
Jojo alter Rang
Anmeldungsdatum: 12.02.2005 Beiträge: 9736 Wohnort: Neben der Festplatte
|
Verfasst am: 18.08.2007, 22:27 Titel: |
|
|
Der Textscreen ist genau 4000byte groß... Und im ersten Post steht ja was von 80x25... _________________ » Die Mathematik wurde geschaffen, um Probleme zu lösen, die es nicht gäbe, wenn die Mathematik nicht erschaffen worden wäre.
|
|
Nach oben |
|
|
ytwinky
Anmeldungsdatum: 28.05.2005 Beiträge: 2624 Wohnort: Machteburch
|
Verfasst am: 19.08.2007, 22:55 Titel: |
|
|
IIRC wird auf dem Bildschirm(auch im Text-Modus) ein zweites Byte benutzt, damit zum Zeichen auch Farben dargestellt werden können. 80x25=2000. Wenn also das 1.Byte das Zeichen ist(&hB800), wäre das 2. Byte(also &hB801) das Farbbyte. Damit erhöht sich natürlich die zu speichernde Menge erheblich, bleibt mit 4000 Byte aber immer noch deutlich unter 32KB.
Inwieweit da auch noch andere Angaben enthalten sind, weiß ich nicht mehr.
Schön, daß es WikiPedia gibt
[Edit]
Gut, daß ich mir mit 'oder ich..' noch ein Hintertürchen offengelassen hatte
Ich habe diesen Beitrag, entsprechend dem Einwand von Georgp24, geändert.. _________________
v1ctor hat Folgendes geschrieben: | Yeah, i like INPUT$(n) as much as PRINT USING.. | ..also ungefähr so, wie ich GOTO..
Zuletzt bearbeitet von ytwinky am 20.08.2007, 16:38, insgesamt einmal bearbeitet |
|
Nach oben |
|
|
Georgp24
Anmeldungsdatum: 30.06.2006 Beiträge: 81 Wohnort: Ahlen
|
Verfasst am: 20.08.2007, 08:09 Titel: |
|
|
Also 80x25 sind 2000 Byte und durch das zweite Byte ergeben sich 4000.
Georg |
|
Nach oben |
|
|
St_W
Anmeldungsdatum: 22.07.2007 Beiträge: 949 Wohnort: Austria
|
Verfasst am: 20.08.2007, 11:09 Titel: |
|
|
Danke für eure schnellen Antworten...
Der Ansatz, alles in einem String zu speichern, gefällt mir gut.
Wie realisiere ich das jetzt in Assembler?
in QB muss ich wahrscheinlich dann statt
DIM Bild(0 to 3999) AS INTEGER
DIM Bild AS STRING * 4000
verwenden. Ist das so richtig? Damit wäre der doppelte Speicherverbrauch schon beseitigt.
Wie die ASM-Routine dazu aussehen soll, davon habe ich keine Ahnung. Vielleicht kann mir das jemand genauer erklären.
Übrigens, zum Bildschirmspeicher im 80x25 Textmodus (SCREEN 0):
80 Spalten * 25 Zeilen mit jeweils einem ASCII-Zeichen(1 Byte) ergeben 2000 Bytes, dazu wird noch die Textfarbe (4-Bits) , die Hintergrundfarbe (3-Bits) und ein Blinkend-Bit (1-Bit) für jedes Zeichen gespeichert, also wieder (4+3+1=8 Bits, 1Byte) * 80 * 25 ergeben 2000 Bytes. Und diese werden nacheinander gespeichert, also ein Zeichen, dann ein Farbattribut, ein Zeichen, ... insgesamt 4000 Bytes! |
|
Nach oben |
|
|
Georgp24
Anmeldungsdatum: 30.06.2006 Beiträge: 81 Wohnort: Ahlen
|
Verfasst am: 20.08.2007, 22:43 Titel: |
|
|
Code: |
'Ich habe das Bildschirminhalt-Speichern und -Wiederherstellen mal mit
'dem QuickBasic Inline-Assembler gelöst ;)
'die Function Blockcpy$ stammt aber nicht von mir, sondern von
'Rick Elbers
'Man kann damit auch Teile des Bildschirms kopieren bzw. jeden Speicher-
'bereich unter 1 MB.
'
'Georg
'
'
DECLARE FUNCTION BLOCKCPY$ () 'aligned blockcopy
CLS
COLOR 15, 4
PRINT "First Screen"
COLOR 7, 0
DEFINT A-Z
CPY$ = BLOCKCPY$
SRCSEG = &HB800: SRCOFF = 0
DIM SMS AS STRING * 4000 'SMS = Save my screen
SMSSEG = VARSEG(SMS$): SMSOFF = VARPTR(SMS)
CALL ABSOLUTE(BYVAL (SRCSEG), BYVAL (SRCOFF), BYVAL (SMSSEG), BYVAL (SMSOFF), 4000, SADD(CPY$))
DEF SEG
PRINT "Press a key to clear screen": SLEEP
CLS
PRINT "Press a key to restore screen": SLEEP
CALL ABSOLUTE(BYVAL (SMSSEG), BYVAL (SMSOFF), BYVAL (SRCSEG), BYVAL (SRCOFF), 4000, SADD(CPY$))
DEF SEG
END
DEFSTR A-Z
'ASSEMBLY IN QBASIC 9: .386 CODING.(rick@tip.nl)
FUNCTION BLOCKCPY
'-----------------------------------------------------------
'This is an aligned blockcopy which makes use of
'Paul Hsiehs align method and .386 coding
'STACKPASSING: BYVAL(SRCSEG),BYVAL(SRCOFF)
' BYVAL(DESTSEG),BYVAL(DESTOFF),NROFBYTES
'-----------------------------------------------------------
''SET UP STACKFRAME
ASM = ASM + CHR$(&H55) 'PUSH BP
ASM = ASM + CHR$(&H89) + CHR$(&HE5) 'MOV BP,SP
ASM = ASM + CHR$(&H1E) 'PUSH DS
ASM = ASM + CHR$(&H6) 'PUSH ES
'GET LEN POINTER FROM THE STACK
ASM = ASM + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H6) 'MOV BX,[BP+06]>LEN
'LOADS SOURCE TO DS[SI], DEST TO ES[DI], LEN TO CX
ASM = ASM + CHR$(&HC4) + CHR$(&H7E) + CHR$(8) 'LES DI,[BP+8]
ASM = ASM + CHR$(&H8B) + CHR$(&HF) 'MOV CX,[BX]
ASM = ASM + CHR$(&HC5) + CHR$(&H76) + CHR$(&HC) 'LDS SI,[BP+C]
'ALIGN THE START OF THE COPYROUTINE TO ES[DI]MOD 4 =0
ASM = ASM + CHR$(&H89) + CHR$(&HC8) 'MOV AX,CX
ASM = ASM + CHR$(&H29) + CHR$(&HF9) 'SUB CX,DI
ASM = ASM + CHR$(&H29) + CHR$(&HC1) 'SUB CX,AX
ASM = ASM + CHR$(&H81) + CHR$(&HE1) + MKI$(&H3) 'AND CX,3
ASM = ASM + CHR$(&H29) + CHR$(&HC8) 'SUB AX,CX
ASM = ASM + CHR$(&H7E) + CHR$(13) 'JLE +13 ONLY_ENDBYTES
'COPY THE FIRST BYTES LEFT OVER WITH MOVSB
ASM = ASM + CHR$(&HF3) + CHR$(&HA4) 'REP MOVSB
'ALIGN THE NUMBER OF BYTES FOR MAIN COPYLOOP TO LEN MOD 4=0
ASM = ASM + CHR$(&H89) + CHR$(&HC1) 'MOV CX,AX
ASM = ASM + CHR$(&H25) + CHR$(&H3) + CHR$(&H0) 'AND AX,3
ASM = ASM + CHR$(&HC1) + CHR$(&HE9) + CHR$(2) 'SHR CX,2 <386
'MAIN COPY LOOP WITH THE BLAZE OF MOVSD
ASM = ASM + CHR$(&HF3) + CHR$(&H66) + CHR$(&HA5) 'REP MOVSD< 386
'END_BYTES: COPY THE LEFT OVER BYTES WITH MOVSB
ASM = ASM + CHR$(&H1) + CHR$(&HC1) 'ADD CX,AX
ASM = ASM + CHR$(&HF3) + CHR$(&HA4) 'REP MOVSB
'WE ARE DONE :RETURN TO QBASIC
ASM = ASM + CHR$(&H7) 'POP ES
ASM = ASM + CHR$(&H1F) 'POP DS
ASM = ASM + CHR$(&H5D) 'POP BP
ASM = ASM + CHR$(&HCA) + MKI$(10) 'RETF A
BLOCKCPY = ASM
END FUNCTION
|
|
|
Nach oben |
|
|
|
|
Du kannst keine Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum nicht antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen.
|
|