die mit diesen beiden beginnen lassen Speicher nach den ausführbaren hinein geladen):
6D 79 73 74 72 69 6E 67 mystring
B9 00 00 00 00 ¹....
die letzten 4 Nullen sind Adresse ‚m‘ Byte von ‚mystring‘, wie ich entschieden es wird an der Adresse 0 kompiliert. Die ersten 8 Bytes sind die Zeichenkettendaten (ASCII-codiert), B9
ist mov ecx,imm32
Befehlsopcode.
Sie können keine Zeichenfolge in ecx
setzen, ecx
ist 32 Bits breit (4 Bytes), während Zeichenfolge viele Bytes haben kann. Also mit ecx
können Sie höchstens 4 Bytes von String abrufen, aber das würde mov ecx,DWORD [str1]
erfordern, das würde den Wert 0x7473796D
in ecx
setzen (x86 ist Little Endian, also das erste Byte 6D
ist der niedrigste Wert in DWORD (32b) Wert).
Aber mov ecx,str1
Lasten ecx
mit str1
Symbol, die Adresse des ersten 'm'
Byte (0x00000000
).
Um zwei Strings zu vergleichen, laden Sie beide Adressen in einige Register, laden dann die Bytes von diesen Adressen und vergleichen sie nacheinander, bis Sie einen Unterschied (oder Ende der Zeichenkette) finden (es gibt schnellere Algorithmen, aber Sie sind komplexer und erfordern, dass Sie die Länge des vorausgehenden Strings kennen, während Byte-für-Byte-Vergleich problemlos mit C-ähnlichen, nullterminierten Strings arbeiten kann.
Über Länge der Schnur sprechen, sollten Sie irgendwie definieren. In C ist es üblich, null nach dem letzten Zeichen der Zeichenkette zu setzen (das wäre in diesem Beispiel B9
voraus), in C++ std::string
ist die Struktur, die die Länge als Wert für direkten Abruf/Vergleich hält. Oder Sie können es in der Quelle fest codieren, wie Ihre outputlen
.
Wenn Sie in Assembler programmieren, sollten Sie immer wissen, wie viele Bits Sie verarbeiten, und die richtige Registergröße wählen (oder den Wert erweitern) und die Speicherpuffergröße korrigieren, um den gewünschten Wert zu verarbeiten.
Mit Strings bedeutet das, dass Sie sich für die Codierung von Strings entscheiden müssen. ASCII ist 8 Bit pro Zeichen (1 Byte), UTF-8 hat eine variable Anzahl von Bytes pro Zeichen, eine frühe Version von UTF-16 (UCS-2) hatte 2 Byte pro Zeichen (wie Java, aber das aktuelle Utf-16 hat eine variable Länge), Utf-32 ist 4 Bytes pro Glyphe festgelegt. Also mit ASCII-codierte Zeichenfolge, um es zu holen ist das erste Zeichen zu tun (oder mov ecx,str1
mov al,[ecx]
->al = 6Dh = 'm'
) Mit Utf-32, um zweites Zeichen zu holen, müssten Sie mov eax,DWORD [utf32str + 4]
tun. Mit Utf-8 kann das einzelne Zeichen maximal 1 bis 6 Bytes haben, also müssen Sie das ziemlich komplex handhaben, um gültigen utf-8-Code zu erkennen und die korrekte Anzahl an Bytes zu lesen.Aber wenn Sie nur wissen wollen, ob zwei utf-8-Strings Bit-gleich sind, können Sie sie byteweise vergleichen, ohne Glyphen selbst zu behandeln.
Natürlich sollten Sie wissen, die Größe der Register und auf x86 die Art und Weise, wie Sie Unter-Teil einiger Register, dh. wie ax
Teil (untere 16b) aus ganzen eax
(32b), oder wie ah
: al
(hohe 8b: niedrige 8b) bilden zusammen ax
.
Ich hoffe, dass Sie danach verstehen, dass Sie zwei Zeiger vergleichen hat (str1
vs str2
), die immer ungleich sein wird, wie sie im Speicher zu anderen Byte zeigen. Anstatt den Inhalt im Speicher zu vergleichen (Strings).
Gibt es einen Grund, warum Sie die Adressen von separaten Stringliterale vergleichen? – EOF
@EOF Was meinst du genau? Ich bin neu in der Montage. Ich möchte die Strings vergleichen. –
Kennen Sie zufällig C? Wenn dies der Fall ist, ist dies der gleiche Fehler wie beim Vergleich von C-Strings mit 'ptr1 == ptr2' anstelle von' strcmp (ptr1, ptr2) '. – EOF