Zeichen aus Zeichenkette auslesen



  • Hallo!

    Ich möchte aus einer Zeichenkette ein einzelnes Zeichen auslesen siehe Beispiel. Ich programmiere dies mit dem NASM und unter Linux. Mit

    mov ecx, msg + 4
    

    kann ich das o auslesen/anzeigen. Ich möchte die 4 aber durch eine Variable ersetzen zum Beispiel aus einem Register oder Speicherwert. Ich bekomme das aber nicht hin. Kann mir einer einen Tipp geben wie ich das realisieren kann?

    Danke schon mal!

    Hier ein Beispieltext:

    section .data
    
    	msg	db	"Hallo Welt!", 0xa
    	len	equ	$ - msg
    
    section .text
    
    	global _start
    
    	_start:
    
    		;Textausgabe
    		mov eax, 4
    		mov ebx, 1
    		mov ecx, msg
    		mov edx, len
    		int 0x80
    
    		;ein Zeichen aus Zeichenkette
    		mov eax, 4
    		mov ebx, 1
    		mov ecx, msg + 4 ;o wird ausgegeben
    		mov edx, 1
    		int 0x80
    
    		mov eax, 1
    		mov ebx, 0
    		int 0x80
    


  • Kopiere deine Variable (Offset innerhalb des Strings - zB. 4) nach ecx und addiere dann das Offset des Strings drauf (oder umgekehrt). Sollte klappen.

    Also in etwa:

    mov ecx, msg
    add ecx, ... (whatever, zB. 4)
    


  • Danke nochmals, es funktioniert.

    Nun wieder ein kleines Problem:

    Ich möchte zwei Ziffern, die hier drin stehen

    ZahlenBuffer resb 0xF
    

    addieren und in

    resb Ergebnis 0xF
    

    schreiben. Bekomme dies aber nicht hin. Muss ich die einzelnen Ziffern erst vom "Bytemodus" - also mit minus 0x30, ist die Null im ASCII-Code - in normal konvertieren und dann addieren oder hat jemand anderes eine Idee?

    Danke für eine Idee schonmal!



  • ich bin mir nicht sicher ob ich dich richtig verstanden habe.
    dein puffer ist 16 bytes groß. ich gehe also davon aus, dass
    du jetzt zwei einzelne 4-byte werte darin gespeichert hast
    die du addieren möchtest?!
    wie dem auch sei, in diesem falle musst du erst den ersten operanden
    in ein register kopieren, da 'add' keine speicher/speicher operanden
    erlaubt. also

    mov eax, ZahlenBuffer
    add eax, ZahlenBuffer+4
    mov Ergebnis, eax
    

    wie gesagt, dies hängt aber vollkommen davon ab, wie du die zahlenwerte
    tatsächlich im puffer gepeichert hast, und vor allem wie breit sie sind.



  • Noch besser: Es sind nur 15 Byte je Puffer. 😉

    Klingt fuer mich fast so, als haette er 2 Strings mit dezimalzahlen, die er addieren will... Allerdings will sich mir auch nicht erschliessen, wie das nun in diesem Puffer abgelegt ist. 😕

    Falls dem so sein sollte: Zahl -> String (der Thread ist sogar noch auf der 1. Seite)



  • Nobuo T schrieb:

    Noch besser: Es sind nur 15 Byte je Puffer. 😉

    doh! 😃

    passiert mir immer wieder 😛



  • Also, ich habs hinbekommen: man ließt die Adresse des Strings in ein Register ein z.B. ebx und gibt den Inhalt von [ebx] in ein anderes Register ax. Nun subtrahiert man von al und ah die 0x30 (ASCII-Code entfernen) und addiert al mit ah. Das Ergebnis addiert man wieder mit 0x30 und gibt dieses wieder aus.

    Ich kann den Code morgen mal komplett reinstellen, komm bloß grad ne daran.

    Nun wieder en kleines Problem mit dem NASM:

    Ich möchte den Stack benutzen, assemblieren und linken lässt sich das Programm, aber es kommt eine Fehlermeldung "Speicherzugriffsfehler" beim Ausführen des Programmes!

    Hier der Code:

    section .data
    
    section .text
    
    	global _start
    
    		_start:
    
    			;Teststack
    		Teststack
    			push	ebp
    			mov	ebp, esp
    
    				;...
    
    			mov	esp, ebp
    			pop	ebp
    		ret
    
    			;aufrufen
    			call Teststack
    
    			;Programm beenden
    			mov	eax, 1
    			mov	ebx, 0
    			int	0x80
    


  • Ist das wirklich der komplette Code? Schau dir das nochmal ganz genau an, ist wirklich ziemlich offensichtlich. 😉



  • Also, ich kann nix entdecken, außer vielleicht der eine Doppelpunkt, aber der ist glaub ich nicht der Fehler.

    Gib ma bitte nen Tipp ich sehs echt nich.

    Dankeschön!



  • ... Dann will ich dir mal etwas auf die Spruenge helfen...

    section .data
    
    section .text
    
    	global _start
    
    		_start:                    ; Hier startet das Programm
    
    			;Teststack
    		Teststack                  ; Beim Erstellen: Warnung: orphan label (-> da gehoert ein Doppelpunkt hinter)
    			push	ebp        ; Hier geht's weiter: Erster Befehl, der ausgefuehrt wird
    			mov	ebp, esp
    
    				;...
    
    			mov	esp, ebp
    			pop	ebp        ; praktisch hat sich bis hier nichts weiter getan...
    		ret                        ; Ab ins Nirvana: Die Zieladresse auf dem Stack ist hier undefiniert! -> "Speicherzugriffsfehler"
    
    ;alles Folgende wird nie ausgefuehrt...
    			;aufrufen
    			call Teststack
    
    			;Programm beenden
    			mov	eax, 1
    			mov	ebx, 0
    			int	0x80
    


  • Alles klar, jetzt hab ichs verstanden, ich mach jetzt einfach nen Sprung über das TestStack bzw. schreib den TestStack ganz unten hin.

    Dankööö!



  • Palim palim!

    Da bin ich wieder mit der nächsten Frage: Ich möchte mit Hilfe der cpuid-Instruktion den Herstellernamen auslesen und das alles in NASM.

    Hab mich schon ein wenig belesen:

    http://de.wikipedia.org/wiki/CPUID
    http://www.sandpile.org/ia32/cpuid.htm

    So, also ich muss ins EAX den Wert 0 übergeben und dann Interrupt ausführen? Aber welchen? Ist das auch der 0x80? Resultat ist ein 12 Zeichen langer Name des Herstellers und zwar in den Registern ebx, ecx, edx verteilt (3*4=12 Bytes). Aber irgendwie funktioniert das nich.

    Hat jemand ne Idee?



  • Keinen Interrupt. cpuid ist ein Prozessorbefehl - den schreibst du einfach so in dein Programm.



  • Aber irgendwie bekomm ichs trotzdem nicht hin...

    Hier mal der Quellcode:

    section .data
    
    	Vendor	db	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0	;13 Byte
    	Laenge	equ	$ - Vendor
    
    section .text
    
    	global _start
    
    		_start:
    
    			;Hersteller auslesen
    			xor	eax, eax
    
    			;Inhalte aus ebx, ecx, edx speichern
    			mov	[Vendor], ebx
    			;... die anderen Register
    
    			;Ausgabe
    			mov	eax, 4
    			mov	ebx, 1
    			mov	ecx, Vendor
    			mov	edx, Laenge
    			int	0x80
    
    			;Programm beenden
    			mov	eax, 1
    			mov	ebx, 0
    			int	0x80
    


  • ... Was erwartest du denn von diesem Code fuer eine Funktion? Meinst du, die CPU-ID wird ohne den cpuid-Befehl aus dem Nichts generiert, wann immer du eax auf 0 setzt? 😕



  • Nein, das habe ich nicht erwartet, aber wenn ich keinen Interrupt ausführen muss, was dann? Muss ich irgendein Schlüsselwort "cpuid" einsetzen und wo? Ich weiß nich wie ich an die Information komme...



  • NASM schrieb:

    Nein, das habe ich nicht erwartet, aber wenn ich keinen Interrupt ausführen muss, was dann? Muss ich irgendein Schlüsselwort "cpuid" einsetzen und wo? Ich weiß nich wie ich an die Information komme...

    .< ok, jetzt versuch ich es mal mit farbe zu erkären 😃
    cpuid ist eine instruktion wie

    mov
    

    oder

    add
    

    oder

    xor
    

    daraus folgt also

    cpuid
    

    im code genauso zu verwenden wie andere instruktionen. welche parameter in welchen registern erwartet werden kannst du in den prozessorspezifikationen nachlesen, ebenso in welchen registern aufrufresultate liegen.



  • Ok, jetzt hab ich verstanden. War ja ganz einfach :))

    Danke!!!


Anmelden zum Antworten