Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   [MASM] strlen Funktion (https://www.delphipraxis.net/128086-%5Bmasm%5D-strlen-funktion.html)

ferby 23. Jan 2009 20:07


[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:
STRLEN_DATA_TO_CX macro
   xor cx, cx
   dec ax

@@:
   inc ax
   inc cx
   cmp   DATA[eax], 0
   jnz @B

   dec cx
endm
Version 2:
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:
DATA db 05,01,"aaa1a",00, 05,01,"a2a",00, 05,01,"3cd",00, 04,01
Ich nehme mal an ich habe hier einen Denkfehler :-(


Falls ihr aus den Codeschnippsel jetzt nicht schlau werdet^^,
hier das ganze Programm (aber ich nehm an der Fehler liegt in den Codeschnippsel)

Code:
;                           ### 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
Das Programm soll nichts anderes tun als drei Message Boxes auszugeben mit dem Inhalt:
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

himitsu 24. Jan 2009 10:08

Re: [MASM] strlen Funktion
 
ist dir schon aufgefallen, daß du auf meißt nur AX setzt und mit EAX prüfst?

Code:
STRLEN_DATA_TO_CX macro
   @@loop:
   inc eax      <<<<< hier
   inc cx
   cmp DATA[eax], 0
   jnz @@loop
   dec cx
endm
was glaubst du denn, was passiert, wenn beim weiterechnen die WORD-Grenze überschritten wird?

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

ferby 24. Jan 2009 11:08

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.

Apollonius 24. Jan 2009 11:12

Re: [MASM] strlen Funktion
 
Um die beiden (Ansi-)Chars zu vergleichen, müsstest du folgenden Code ausführen:
Code:
mov cl, [ebx]
cmp cl, [eax]
Du musst also auch in Assembler manuell dereferenzieren.

ferby 24. Jan 2009 11:23

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.

himitsu 24. Jan 2009 12:53

Re: [MASM] strlen Funktion
 
@xyz ist ein Sprungziel (entspricht Delphi-Referenz durchsuchenlabel in Delphi)

@@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)

ferby 24. Jan 2009 13:38

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

himitsu 24. Jan 2009 13:47

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:
const eax = 123;

asm
  @@mov:
  mov eax, &eax
  // entspricht
  mov eax, 123
  jmp @@mov
[edit] ach menno, immer diese Verschreiber :oops:

ferby 24. Jan 2009 16:29

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:
invoke MessageBox, 0, ADDR DATA[eax], ADDR AppNameDefault, MB_OK
wird aber das eax Register überschrieben :-(


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

himitsu 24. Jan 2009 17:36

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 19:03 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz