[Assembler] Multiplizieren

Quidoff

Lieutenant
Registriert
Feb. 2005
Beiträge
897
Hi,
ich schreibe gerade ein Programm in Assembler und weiß nicht, wie man richtig multipliziert.

Als Compiler verwende ich MASM32.

Code:
aktualisieren proc
			LOCAL		adr:DWORD
			LOCAL		off:DWORD
			LOCAL		res:DWORD
			

[...] ; off wird initialisiert
			
			MOV		adr, off * 4 + 004FE188h ; diese Zeile erzeugt den Fehler

			ret
aktualisieren endp
Compilerfehler: constant expected

Ich weiß, dass es den Befehl MUL gibt, aber der ist für Konstanten nicht zugelassen.
 
Für welche CPU-Architektur möchtest du das denn schreiben?
 
Für eine 32-Bit Architektur.

Sind die Befehle bei einer 64-Bit Architektur denn anders? Da kommen doch eigentlich nur neue Befehle hinzu.
 
Mit x86 Assembly hab ich zwar nicht so viel Ahnung, aber bei anderen Plattformen (Hitachi sh4 und Mitsubishi m16c) ist es nicht möglich, solch komplexe Ausdrücke in einem Befehl abzuarbeiten. Im Normalfall wird diese Anweisung aufgeteilt in
mov adr, off
mul adr, 4
add adr, 004FE188h

Dieses Beispiel wird wahrscheinlich so nicht funktionieren, aber es soll den grundsätzlichen Aufbau zeigen.

NACHTRAG: Ich hab jetzt erst gelesen, dass du das mit dem mul-Befehl bereits gesehen hast und das diese für Konstanten nicht zugelassen ist. Aber wo ist da das Problem. Ein Prozessor hat Register, du "movest" also die Konstante in ein Register und multiplizierst dann zwei Register miteinander.

Ungefähr so:
mov adr, off
mov r0, 4 ; bei x86 heißen die Register anders
mul adr, r0
add adr, 004FE188h
 
Zuletzt bearbeitet:
@Simpson474
Genau das habe ich gemacht, bevor ich deinen Post gelesen habe ;)

Folgender Code funktioniert.
Code:
aktualisieren proc
			LOCAL		adr:DWORD
			LOCAL		off:DWORD
			LOCAL		res:DWORD
			

[...] ; off wird initialisiert
			
			MOV		eax, off
			MOV		edx, 4
			MUL		edx
			MOV		adr, eax
			ADD		adr, 004FE188h

			ret
aktualisieren endp

Danke für die Hilfe.

Noch eine Frage.
Bei einem DWord-Operanden wird das Register EAX mit dem Faktor multipliziert und das Resultat im Registerpaar EDX:EAX abgelegt. EDX enthält die höherwertigen 32 Bits des Resultats. Carry- und Overflow-Flag werden auf Null gesetzt, wenn EDX Null ist, ansonsten werden beide auf 1 gesetzt. Da das/die Zielregister immer ausreichend groß sind, kann es keinen Überlauf mehr geben.
Quelle

Da ich im Moment nur kleine Zahlen miteinander multipliziere, passt das Ergebnis immer ins eax-Register. Wie würde ich aber bei größeren Zahlen auf die beiden Register edx und eax zugreifen, um das komplette Ergebnis zu erhalten?
 
Zuletzt bearbeitet:
Kommt darauf an, was du mit den Zahlen machen willst. Wenn du Sie nur im Speicher ablegen willst, dann musst du halt zuerst den Wert des EAX-Registers in den Speicher übertragen, dann die Speicherposition um 32 Bit erhöhen und dann das EDX-Register im Speicher ablegen.
 
Wie rechnet man mit einer so großen Zahl weiter?

Die Register sind ja nur 32Bit groß. Lassen sich die Befehle auch auf zwei Register anwenden?
 
Quidoff schrieb:
Wie rechnet man mit einer so großen Zahl weiter?

Die Register sind ja nur 32Bit groß. Lassen sich die Befehle auch auf zwei Register anwenden?

Nein, aber die mathematischen Regeln:evillol:
Bei einer 64 bit Zahl wird z.B. beim Addieren zuerst der niederwertige Teil mit einer zweiten 64 Bit Zahl addiert, dabei der Überlauf beachtet und anschließend unter Berücksichtigung des Überlaufs der höherwertige Teil addiert.

Beispiel
 
Zurück
Oben