In der Assemblersprache von 0 auf 100 erhöhen

7

Das ist ein komischer Kauz, aber ich habe heute mit dem GNU-Assembler herumgestochert (ich möchte zumindest die Syntax lesen können) und versuchte, dieses kleine erfundene Beispiel von mir zum Laufen zu bringen. Nämlich will ich einfach von 0 bis 100 gehen und die ganze Zeit Zahlen ausdrucken. Ein paar Minuten später komme ich daher:

%Vor%

Alles was ich davon bekomme ist 3 immer wieder gedruckt. Wie ich schon sagte, nur ein kleines erfundenes Beispiel, also mach dir keine Sorgen, es ist kein Leben oder Tod Problem.

(Die Formatierung ist ein wenig durcheinander, aber nichts Wichtiges).

    
Bernard 21.08.2008, 06:20
quelle

6 Antworten

12

Sie können nicht darauf vertrauen, was eine aufgerufene Prozedur für eines der Register bedeutet. Schieben Sie entweder die Register auf den Stapel und entfernen Sie sie nach dem Aufruf von printf oder halten Sie die Werte für Inkrement und Endpunkt im Speicher und lesen / schreiben Sie sie in die Register, so wie Sie sie brauchen.

Ich hoffe, das folgende funktioniert. Ich gehe davon aus, dass Pushl ein äquivalentes Popl hat und du ein paar zusätzliche Zahlen auf den Stack schieben kannst.

%Vor%     
seanyboy 21.08.2008, 07:47
quelle
6

Ich kenne mich mit _printf nicht aus, aber könnte es sein, dass es eax verändert? Printf sollte die Anzahl der gedruckten Zeichen zurückgeben, in diesem Fall zwei: '0' und '\ n'. Ich denke, es gibt das in eax zurück, und wenn du es erhöhst, bekommst du 3, und damit druckst du weiter. Sie könnten besser ein anderes Register für den Zähler verwenden.

    
Nathan Fellman 21.08.2008 06:28
quelle
5

Sie können sicher Register verwenden, die "gespeichert werden", ohne sie selbst speichern zu müssen. Auf x86 sind dies edi, esi und ebx; andere Architekturen haben mehr.

Diese sind in den ABI-Referenzen dokumentiert: Ссылка

    
alex strange 04.09.2008 02:32
quelle
3

Gut geschriebene Funktionen werden normalerweise alle Register auf den Stapel schieben und sie dann aufklappen, wenn sie fertig sind, damit sie während der Funktion unverändert bleiben. Die Ausnahme wäre eax, die den Rückgabewert enthält. Bibliotheksfunktionen wie printf werden höchstwahrscheinlich auf diese Weise geschrieben, also würde ich nicht tun, wie Wedge es vorschlägt:

  

Sie müssen dasselbe für jede andere Variable tun, die Sie haben. Die Verwendung von Registern zum Speichern von lokalen Variablen ist ziemlich weitgehend Architekturen vorbehalten, die über genügend Register verfügen, um sie zu unterstützen (z.B. EPIC, amd64, etc.)

In der Tat kompilieren Compiler, soweit ich weiß, Funktionen, um genau mit diesem Problem umzugehen.

@seanyboy, deine Lösung ist übertrieben. Alles, was benötigt wird, ist, eax durch ein anderes Register wie ecx zu ersetzen.

    
Nathan Fellman 21.08.2008 09:46
quelle
1

Nathan ist auf dem richtigen Weg. Sie können nicht davon ausgehen, dass die Registerwerte nach dem Aufruf einer Subroutine nicht geändert werden. In der Tat ist es am besten anzunehmen, dass sie modifiziert werden, sonst würde das Unterprogramm nicht in der Lage sein, es zu tun (zumindest für Architekturen mit niedrigen Registerzahlen wie x86). Wenn Sie einen Wert beibehalten möchten, sollten Sie ihn im Speicher ablegen (z. B. auf den Stapel schieben und den Standort verfolgen).

Sie müssen dasselbe für jede andere Variable tun, die Sie haben. Die Verwendung von Registern zum Speichern von lokalen Variablen ist ziemlich weitgehend Architekturen vorbehalten, die über genügend Register verfügen, um sie zu unterstützen (z.B. EPIC, amd64, etc.)

    
Wedge 21.08.2008 08:00
quelle
-1

Sie könnten es so umschreiben, dass Sie Register verwenden, die nicht geändert werden sollen, z. B. %ebp . Stellen Sie nur sicher, dass Sie sie am Anfang auf den Stapel schieben und am Ende Ihrer Routine wieder loslassen.

%Vor%     
Brad Gilbert 21.08.2008 20:48
quelle

Tags und Links