&-operator funktioniert unter nasm nicht!?



  • Hi Leute,

    ich bin noch ein asm-anfänger und arbeite mit nasm, jedoch funktioniert dort der &-Operator für die Substitution von Namen nicht.

    Folgendes Codebeispiel:

    org 100h
    segment .data
        Zaehler db 0
        m0 db 'Message 1',10,13,'$'
        m1 db 'Message 2',10,13,'$'
        m2 db 'Message 3',10,13,'$'
        m3 db 'Message 4',10,13,'$'
    
    segment .text
        mov ecx, 4				;Counter auf 4 setzen
    Schleife:
        lea dx, [m&Zaehler]			;String laden
        mov ah, 9				;Funktion zum ausgeben eines Strings
        int 21h
        loop Schleife			;wenn ecx nicht 0, dann springe zu Schleife
    
    ende:
        mov ah, 4Ch				;beendet das
        int 21h				;Programm
    
    ends
    

    Dort gibt nasm folgenden Fehler aus: '&' operator may only be applied to scalar values

    Was genau bedeutet das und wie kann ich den Code entsprechend zum laufen bekommen?

    Bin für jede Hilfe dankbar.



  • Hi.

    Tja, Assembler ist eben keine Hochsprache. Hier wird das was du schreibst direkt umgesetzt (so sollte es IMHO zumindest sein - deshalb ist MASM auch boese :D). Deshalb kann die Substitution von Variablennamen mit anderen Variablen (die ja schliesslich zur Laufzeit veraendert werden koennen) nicht funktionieren.

    In deinem Fall, wo die Texte alle gleich lang sind, waere es IMHO am einfachsten, vor der Schleife das Offset des ersten Textes zB. in di zu laden, in der Schleife dann zuerst di nach dx zu kopieren und anschliessend die Laenge eines Strings auf di zu addieren.

    Falls die Strings unterschiedlich lang sind, ist es vielleicht am einfachsten, ein Array anzulegen, das die Offsets der Texte beinhaltet. Du koenntest dann vor der Schleife das Offset des Arrays zB. in si schreiben und in der Schleife dann ueber si das Offset des Strings aus dem Array nach dx kopieren und anschliessend si um 2 erhoehen (um das naechste Element des Arrays auszuwaehlen - ich gehe von 16Bit-Offsets im Array aus).

    So, und um dich jetzt noch vollkommen zu verwirren:

    DOS-Programme beinhalten ueblicherweise 16Bit-Code. Die loop-instruktion wird also nur cx beeinflussen und nicht ecx.

    lea nur fuer das Laden eines einfachen Offsets zu missbrauchen, so wie du das in deinem Code tust, ist ineffizient. Deshalb uebersetzen die meisten Assembler sowas schon von selbst als "mov reg, offset".
    Waere also vielleicht sinnvoller, wenn du das schon von selbst "richtig" schreibst.
    Fuer den NASM muesstest du also statt "lea dx, [m0]" -> "mov dx, m0" schreiben.



  • Hi Nobuo T,

    danke für die Antwort, ich werde das mal so versuchen umzusetzen.
    Ich hatte mir das schon fast gedacht, dass das eigentlich nicht normal so funktioniert, das sich durch die Substitution der Variablennamen mit anderen Variablen während der Laufzeit verändern kann, oder so ähnlich.
    Danke auch für den Hinweis mit 'lea'.



  • So, ich habs jetzt endlich fertiggestellt. Hatte wenig Zeit in letzter Zeit um mich darum zu kümmern.
    Die beste und wohl einfachste Lösung für mich bestand jetzt darin, dass ich die Anfangsadressen der Strings in umgekehrter Reihenfolge auf den Stack ablege und dann in der Schleife nach und nach wieder vom Stack hole, eigentlich ganz simpel.

    Hier der Code dazu:

    org 100h
    segment .data
        Zaehler db 0
        m0 db 'Message 1',10,13,'$'
        m1 db 'Message 2',10,13,'$'
        m2 db 'Message 3',10,13,'$'
        m3 db 'Message 4',10,13,'$'
    
    segment .text
        mov cx, 4			;Counter auf 4 setzen
        push WORD m3
        push WORD m2
        push WORD m1
        push WORD m0
    Schleife:
        pop dx				;String vom Stack laden
        mov ah, 9			;Funktion zum ausgeben eines Strings
        int 21h
        loop Schleife			;wenn cx nicht 0, dann springe zu Schleife
    
    ende:
        mov ah, 4Ch			;beendet das
        int 21h				;Programm
    
    ends
    

Anmelden zum Antworten