![]() |
[MASM] strlen Funktion
Hallo,
Hoffentlich kennt sich hier wer mit MASM aus ;-) Also ich habe gerade angefangen MASM zu lernen und scheiter daran, eine Funktion zu schreiben, die wie die strlen in C funktioniert. (Gibt die Anzahl der Bytes von der Startadresse bis zum ersten 0-Byte zurück) (Ich möchte keine fertige strlen Version, sondern wissen warum meine Version nicht geht) Also ich habe sogar zwei verschiedene Funktionen. Beide funktionieren manchmal und manchmal nicht (bei beiden tritt immer der Fehler beim selben Teilstring auf) ...und ich habe keine Ahnung warum :-( Der Rückgabewert, also die Länge, steht am Ende in cx drin Version 1:
Code:
Version 2:
STRLEN_DATA_TO_CX macro
xor cx, cx dec ax @@: inc ax inc cx cmp DATA[eax], 0 jnz @B dec cx endm
Code:
STRLEN_DATA_TO_CX macro
xor cx,cx .WHILE DATA[eax] != 0 inc cx inc eax .ENDW endm Wobei in eax die Startadresse drin steht (immer nach 0501) und DATA so definiert ist:
Code:
Ich nehme mal an ich habe hier einen Denkfehler :-(
DATA db 05,01,"aaa1a",00, 05,01,"a2a",00, 05,01,"3cd",00, 04,01
Falls ihr aus den Codeschnippsel jetzt nicht schlau werdet^^, hier das ganze Programm (aber ich nehm an der Fehler liegt in den Codeschnippsel)
Code:
Das Programm soll nichts anderes tun als drei Message Boxes auszugeben mit dem Inhalt:
; ### COMPILER EINSTELLUNGEN ###
.386 .model flat,stdcall option casemap:none ; ### BENÖTIGTE INCLUDES ### include C:\masm32\include\windows.inc include C:\masm32\include\user32.inc include C:\masm32\include\kernel32.inc include C:\masm32\include\gdi32.inc includelib C:\masm32\lib\user32.lib includelib C:\masm32\lib\kernel32.lib includelib C:\masm32\lib\gdi32.lib INC_DATA_POINTER macro _add xor eax,eax add DATA_POINTER, _add mov ax,DATA_POINTER endm ;STRLEN_DATA_TO_CX macro ; xor cx, cx ; dec ax ;@@: ; inc ax ; inc cx ; cmp DATA[eax], 0 ; jnz @B ; dec cx ;endm STRLEN_DATA_TO_CX macro xor cx,cx .WHILE DATA[eax] != 0 inc cx inc eax .ENDW endm .data DATA_POINTER dw 0 ; Speichert die aktuelle Position im DATA String Error db "Es ist leider ein interner Fehler aufgetreten :-(",10,10,0 AppNameDefault db "FD3",0 ; ### ZUM TESTEN ### DATA db 05,01,"aaa1a",00, 05,01,"a2a",00, 05,01,"3cd",00, 04,01 .code START: .WHILE TRUE ; Lösche EAX und Speicher den aktuellen Wert des DATA_Pointer xor eax, eax mov ax, DATA_POINTER ; ########## ; REGISTER 1 .IF DATA[eax] == 4 INC_DATA_POINTER 1 ;4/1 .IF DATA[eax] == 1 invoke ExitProcess,0 .ENDIF ; ########## ; REGISTER 5 .ELSEIF DATA[eax] == 5 INC_DATA_POINTER 1 ;5/1 .IF DATA[eax] == 1 INC_DATA_POINTER 1 invoke MessageBox, 0, ADDR DATA[eax], ADDR AppNameDefault, MB_OK STRLEN_DATA_TO_CX INC_DATA_POINTER cx .ENDIF ; ##### ; ERROR .ELSE invoke MessageBox, 0, ADDR Error, ADDR AppNameDefault, MB_OK invoke ExitProcess, 0 .ENDIF .ENDW invoke ExitProcess,0 END START aaa1a a2a 3cd und sich dann beenden. Die ersten zwei Messages Boxes werden ausgegeben, bei der dritten gibt auf einmal STRLEN einen falschen wert zurück !? (Nich über das Programm wundern, lern grad erst ASM und schreib irgendwas zum ausprobieren^^) vielen dank falls sich wer die Zeit nimmt mir weiter zu helfen, Lg, Ferby |
Re: [MASM] strlen Funktion
ist dir schon aufgefallen, daß du auf meißt nur AX setzt und mit EAX prüfst?
Code:
was glaubst du denn, was passiert, wenn beim weiterechnen die WORD-Grenze überschritten wird?
STRLEN_DATA_TO_CX macro
@@loop: inc eax <<<<< hier inc cx cmp DATA[eax], 0 jnz @@loop dec cx endm z.B. String fängt an Adresse $0040fff8 an und ist 32 Zeichen lang dann ergibt das eine schöne Endlosschleife, denn die #0 ist dann an Adresse $00410018, aber da nur AX geändert wird, kommst du nur an Adresse $00400018 vorbei.
Code:
STRLEN_DATA_TO_CX macro
xor cx, cx cmp eax, 0 // prüfen ob EAX = nil jz @@end // @@loop: inc eax inc cx cmp DATA[eax], 0 jnz @@loop dec cx @@end: endm |
Re: [MASM] strlen Funktion
Hallo,
Thx für deine Antwort. So was in der Art dachte ich mir schon, muss mir das glaub ich aufzeichnen damit ich das ganz check ;-) Was ich auch noch nicht ganz kapiert hab: wenn ich sag ma in eax den Wert 54353 Speicher und in ebx den Wert 354636 wie weiß jetzt der cmp Befehl ob ich die Werte 54353 und 354636 vergleichen will oder ob in eax und bax zwei Adressen auf zb zwei Chars im Arbeitsspeicher sind, und ich möcht eigentlich die zwei Chars vegleichen??! Das habe ich auch noch nicht ganz überissen. Vlt kannst du mir das auch erklären. |
Re: [MASM] strlen Funktion
Um die beiden (Ansi-)Chars zu vergleichen, müsstest du folgenden Code ausführen:
Code:
Du musst also auch in Assembler manuell dereferenzieren.
mov cl, [ebx]
cmp cl, [eax] |
Re: [MASM] strlen Funktion
axo also eckige Klammer dereferenziert?
Eine letzte Frage noch ;-) @@: ..... jnz @B Was bedeutet hier das @@ und warum spring ich genau mit @b dort hin. Find das immer wieder in Beispielen, aber niegendst wirds erklärt. |
Re: [MASM] strlen Funktion
@xyz ist ein Sprungziel (entspricht
![]() @@xyz ist das Selbe. Nur verwendet man meißtens für prozedurinterne Sprünge @@ und für den Rest @ Aber wenn du nicht weißt, warum du mit jnz @xyz dort hin springst, dann solltest du dir lieber mal gedanken machen und die Assemblergrundlagen lernen. jnz = jump if not zero (wird über das entsprechende Register geprüft und dieses enthält das Ergebnis des vom vorherigen Vergleichs) |
Re: [MASM] strlen Funktion
Hallo,
sry, du hast glaub ich meine Frage falsch verstanden... ich weiß was Labels sind, was jnz heißt und die Grundlagen hab ich auch so langsam drausen ;-) ich versteh nicht warum der Label @@ heißt aber ich mit @B dort hin springe. Normal habe ich ja zb den Label Error und springe auch mit Error dort hin tu was jnz Error Error : tu was meine Frage bezieht sich drauf, das ich diesmal tu was jnz @B @@ : tu was stehen hab. Und das versteh ich nicht |
Re: [MASM] strlen Funktion
nja, ist wohl alles mehr das selbe, aber mit @@xyz springst du zu @@xyz (hab oben grad gemerkt, daß ich da ein @ vergssen hatte :oops: )
und mit @xyz dann zu @xyz mit @xyz dürfte es eigentlich nicht zu @@xyz springen :gruebel: (dieses @ nimmt man mehr als Kennzeichnung der Labels ... der Übersichtlichkeit halber) ist wohl ähnlich, bei beim Kennzeichnen einer Variable/Konstante mit & , fall der Name nicht eindeutig ist (ich hab mir angewöhnt dieses & immer zu machen ... müßt ich theoretisch aber nicht, wollt es nur einheitlich haben)
Delphi-Quellcode:
[edit] ach menno, immer diese Verschreiber :oops:
const eax = 123;
asm @@mov: mov eax, &eax // entspricht mov eax, 123 jmp @@mov |
Re: [MASM] strlen Funktion
Hallo,
nach ewigen herumprobieren und schließlich einen debugger bin ich auf den Fehler drauf gekommen. Es lag eigentlich gar nicht daran das eine Word Grenze überschritten wird. Der Fehler lag daran, das ich die aktuelle Position in eax Speicher. Nach dem Aufruf von
Code:
wird aber das eax Register überschrieben :-(
invoke MessageBox, 0, ADDR DATA[eax], ADDR AppNameDefault, MB_OK
Hier meine Überarbeitet strlen Funktion
Code:
STRLEN_DATA_TO_CX macro
xor cx,cx xor eax,eax <--- Neu, lösche überschriebenes eax Register mov ax, DATA_POINTER <--- Neu, schreibe meine aktuelle Position wieder hinein .WHILE DATA[eax] != 0 inc cx inc eax .ENDW inc cx <--- Neu, +1 dazu, wegen dem 0 Byte vom Vorstring endm |
Re: [MASM] strlen Funktion
jupp, da mußt du auch aufpassen.
EAX, ECX, EDX, EDI, ESI darfst du und jeder andre unkontrolliert verändern, also beim Aufruf von anderen Prozeduren, solltest du dir die nötigen Felder sichern ... bzw. am Ende deiner Prozedur die sonstigen (hier nicht aufgezählten) Felder wieder herstellen. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:21 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz