String Array



  • Klasse! Guck ich mir morgen mal an. Wenn ich mir das jetzt noch anschauen würde, würde ich ziemlich viele blöde Fragen stellen 😃



  • Normalerweise verwendet man einfach die passenden Datentypen, oder man richtet die Daten mit Alignment an passenden Adressen aus, beispielsweise mit align 16.
    Oder legt die Strings für + 10h oder so einzeln an, bzw. belegt sie vor.

    Mit Befehlen wie z.B.

    Doppelwort_Stringtangas DD 66 DUP (0)
    

    kann man sich Stringarrays in Doppelwortgröße anlegen. Vorsicht Verwechslungsgefahr: DW meint NICHT Doppelwort.

    Dann gibt es noch diverse anderen Assemblerhilfen(direktiven) wie STRUC oder UNION die bei solchen Sachen helfen, oder eben wie masm oben schon beschreibt.



  • GutenAbend schrieb:

    Sry

    Windows 7 x64
    masm32
    Anfänger 🙂

    Tja, dann versuch erstmal, die Aufgabe in C zu lösen, oder C++, oder wie auch immer in einer Dir vertrauten Programmiersprache.
    Dann schreibe ein wenig Testcode, mit dem die Funktion getestet wird, gängige "Use cases", illegale Parameter und was Dir noch so einfällt.
    Dann versuche, die Funktion in Assembler zu implementieren und parallel mit dem Testcode zu testen...
    Sollte es bereits an der Implementierung in C scheitern - dann gehe und zocke lieber Battle Field oder WoW o.ä.



  • @nachtfeuer:
    Ja, sowas kam mir auch in etwa in den Sinn. Da ich aber gerade erst mit ASM anfange, wollte ich direkt die "standard" bzw. beste Methode benutzen.

    @abc.w:
    Wie gesagt, ich suche die beste Methode für ASM.
    Der letzte Satz ist übrigens sehr hilfreich 👍

    @masm:
    Habs mir jetzt mal genauer angeschaut. Das dynamische Array hat mir sehr geholfen

    @Alle:
    Danke !



  • GutenAbend schrieb:

    @abc.w:
    Wie gesagt, ich suche die beste Methode für ASM.
    Der letzte Satz ist übrigens sehr hilfreich 👍

    Ich habe Dir die beste Methode gezeigt. Es gibt keine bessere. Zum Schluss hast Du zwei Implementierungen, einmal in einer Hochsprache und einmal in Assembler. Die beiden kannst Du vergleichen - je nach dem, was Du genau vorhast - "Optimize for size" oder "Optimize for speed".
    Siehe es auch noch so: Mit dieser Methode sparst Du Zeit und gehst an das Problem objektiv heran und du kannst nachweisen, dass Du etwas verbessert (oder auch verschlechtert) hast.



  • @abc.w:
    In C++ hab ich das schon einmal gehabt, an sich der gleiche Ansatz wie der von masm. Hab nur gedacht, dass man das in ASM noch etwas "eleganter" lösen könnte...

    @masm:
    Hab deine Lösung jetzt "übernommen" und modifiziert.
    Möchte ich jetzt ungern posten, da der Code einfach durch zahlreiche Experimente ziemlich wild aussieht.
    Bin nur etwas von den masm32 Macros abgewichen, dh. ich hab z.B. anstatt "alloc(...)" -> VirtualAlloc bzw HeapAlloc verwendet.
    Wenn ich nun die Elemente aus dem dynamischen Array ausgeben will, werden die mir falsch herum ausgegeben, d.h. LIFO.
    Kann man natürlich leicht umgehen, aber woran liegt das ?

    Noch etwas:
    Rein von der Performance wäre es doch sinnvoller, einen großen Block zu reservieren (und ggf. später noch vergrößern), anstatt für jedes Element neuen Speicher zu reservieren, oder sehe ich das falsch?



  • GutenAbend schrieb:

    Bin nur etwas von den masm32 Macros abgewichen, dh. ich hab z.B. anstatt "alloc(...)" -> VirtualAlloc bzw HeapAlloc verwendet.

    Ist richtig so, HeapAlloc sollte man verwenden – alloc() liest sich in Beispiel halt besser 😉

    GutenAbend schrieb:

    Wenn ich nun die Elemente aus dem dynamischen Array ausgeben will, werden die mir falsch herum ausgegeben, d.h. LIFO.
    Kann man natürlich leicht umgehen, aber woran liegt das ?

    Das liegt daran, wie du die Strings ein- und/oder ausgibst.

    GutenAbend schrieb:

    Noch etwas:
    Rein von der Performance wäre es doch sinnvoller, einen großen Block zu reservieren (und ggf. später noch vergrößern), anstatt für jedes Element neuen Speicher zu reservieren, oder sehe ich das falsch?

    ja, das ist Sinnvoll und deswegen macht es der Heap-Manager für dich.



  • Hm...alles klar soweit, bis auf die Kleinigkeit mit der verkehrten Ausgabe.
    Ich baue das Array doch folgendermaßen zusammen:

    -Str1
    -Str1+Str2
    -Str1+Str2+Str3
    ...

    Ausgabe:
    -[Array]
    -[Array+1] <- bzw. + 4
    -[Array+2]
    ...

    Aber warum ist jetzt die Ausgabe LIFO?

    Gruß



  • zeig doch einfach den code.



  • Aber nicht für das ganze Durcheinander erschlagen 😉

    .DATA
    	str1		DB		"str1",0
    	str2		DB		"str222",0
    	str3		DB		"str3333333",0
    .DATA?
    	pStrDyn		DD		3 DUP(?)
    .CODE
    WinMainCRTStartup PROC
    	LOCAL pStr:DWORD
    
    	lea		ESI, pStrDyn
    	xor		EBX, EBX
    
    .while EBX < 3
    
    	cmp		EBX, 1
    	je		Load2
    	jb		Load3
    Load1:
    	mov		pStr, 0
    	mov		pStr, OFFSET str1
    	jmp		Done
    Load2:
    	mov		pStr, 0
    	mov		pStr, OFFSET str2
    	jmp		Done
    Load3:
    	mov		pStr, 0
    	mov		pStr, OFFSET str3
    Done:
    
    	invoke	        eStrLen, pStr
    	mov		EDX, EAX
    	inc		EDX
    
    	;push	        PAGE_EXECUTE_READWRITE
    	;mov		EAX, MEM_COMMIT
    	;or		EAX, MEM_RESERVE
    	;push	        EAX
    	;push	        EDX
    	;push	        0
    	;call	        VirtualAlloc
    
    	call	        GetProcessHeap
    	push	        EDX
    	push	        HEAP_ZERO_MEMORY
    	push	        EAX
    	call	        HeapAlloc
    	mov		EDI, EAX
    
    	invoke	        szCopy, pStr, EDI
    
    	mov		DWORD ptr [ESI+EBX*4], EDI
    	inc		EBX
    
    .endw
    	;----------------------------------------------
    	lea		ESI, pStrDyn
    	mov		EBX, 3
    
    GO:
    	dec		EBX
    	push	        0
    	mov		EAX, DWORD ptr [ESI+EBX*4]
    	push	        EAX
    	push	        EAX
    	push	        0
    	call	        MessageBoxA
    
    	cmp		EBX, 0
    	jne		GO
    
    	push	        0
    	call	        ExitProcess
    	ret
    WinMainCRTStartup ENDP
    ...
    

    Das ist es. Wie gesagt, öfters "hin und her geschoben", von daher... 😃



  • Vergleich mal deine Schleifen - der unterschied sollte dir auffallen.
    Ganz wichtig: Die Register EAX,ECX und EDX werden durch WinAPI-Funktionen geändert - nur ESI,EDI und EBX bleiben unberührt (Win/Intel ABI). Wenn der Inhalt dieser Register gebraucht wird, musst du sie vor einem API-Aufruf z.B. auf dem Stack oder in einer lokalen Variablen sichern (EDX->Zeile 33-45)



  • Oh verdammt!
    Nein sorry, das ist meine "optimierte" Methode. So wird alles korrekt ausgegeben...
    Wenn ich diese Schleife "korrigiere", tritt eben dieser falsche Effekt auf...



  • GutenAbend schrieb:

    Oh verdammt!
    Nein sorry, das ist meine "optimierte" Methode. So wird alles korrekt ausgegeben...
    Wenn ich diese Schleife "korrigiere", tritt eben dieser falsche Effekt auf...

    So lange Du keinen Testcode hast, kannst "optimieren" bis zum Umfallen. Danach kann man den Quellcode ausdrucken und als Klopapier benutzen - ehrlich.



  • Man beachte die " 😉
    Optimiert war das falsche Wort, "korrigiert" wäre richtig.

    @masm:
    Das ist die korrekte Schleife die du meinst. Aber hier tritt eben der Effekt auf, das zu erst das letzte Element ausgegeben wird:

    ... ; alles wie oben
    	;----------------------------------------------
    	lea		ESI, pStrDyn
    	xor		EBX, EBX
    
    .while EBX < 3
    	push	0
    	mov		EAX, DWORD ptr [ESI+EBX*4]
    	push	EAX
    	push	EAX
    	push	0
    	call	MessageBoxA
    	inc		EBX
    .endw
    
    	push	0
    	call	ExitProcess
    	ret
    WinMainCRTStartup ENDP
    ...
    


  • cmp        EBX, 1 
        je        Load2 
        jb        Load3
    

    ⚠



  • Wo ist der Smilie, der den Kopf gegen die Wand schlägt?
    Danke...


Anmelden zum Antworten