Frage

Ich bin mit Borland Turbo C ++ mit einigen inlined Assembler-Code, so vermutlich Turbo Assembler (TASM) Stil Assembler-Code. Ich möchte Folgendes tun:

void foo::bar( void )
{
    __asm
    {
      mov eax, SomeLabel
      // ...
    }
    // ...
SomeLabel:
    // ...
}

So ist die Adresse von SomeLabel in EAX gelegt. Das funktioniert nicht, und der Compiler beklagt. Nicht definiert Symbol ‚SomeLabel‘

In Microsoft Assembler (MASM) die Dollarzeichen ($) als aktuellen Standort Zähler dient, die für meine Zwecke nützlich wäre. Aber auch hier scheint dies nicht in Borlands Assember (expression Syntaxfehler) zu arbeiten.

Update: Um etwas genauer zu sein, muß ich die Compiler die Adresse bewegt er sich in EAX als Konstante während der Kompilierung / Verknüpfung und nicht zur Laufzeit erzeugen, so dass es wie „mov eax, 0x00401234“ kompiliert <. / p>

Kann jemand vorschlagen, wie diese Arbeit zu bekommen?

UPDATE: So reagieren Sie auf Pax Frage (siehe Kommentar) Wenn die Basisadresse zur Laufzeit durch die Windows-Lade der DLL / EXE PE Bild noch durch die Windows-Lade verlegt werden und die Etiketten-Adresse wird gepatcht geändert wird Zeit vom Lader läuft die Wieder basierte Adresse zu verwenden, um ein Compiler / link Zeitwert für das Adressetikett verwendet, ist kein Problem.

Vielen Dank im Voraus.

War es hilfreich?

Lösung

Das letzte Mal habe ich versucht, einige Assembler-Code Borland-kompatibel zu machen ich über die Begrenzung kam, dass man nicht vorausReferenz Etiketten. Nicht sicher, ob das, was Sie laufen in hier.

Andere Tipps

Alles, was ich über Borland finden schlägt vor, dies sollte arbeiten. Ähnliche Fragen auf anderen Seiten ( hier und hier ) legen nahe, dass Borland vorwärts Verweise für Etiketten verarbeiten kann, besteht jedoch darauf, Etiketten außerhalb ASM Blöcke zu sein. Doch wie Ihr Etikett war bereits außerhalb der asm-Block ...

Ich bin gespannt, ob Ihr Compiler Ihnen erlauben würde, dieses Etikett in verwenden, zum Beispiel eine JMP-Anweisung. Wenn sie mit ihm (zugegebenermaßen auf einem völlig anderen Compiler) Herumspielen, fand ich eine nervtötende Tendenz der Compiler über Operandentypen zu beschweren.

Die Syntax ist ganz anders, und es ist mein erster Versuch Inline-asm in einer langen Zeit, aber ich glaube, ich habe oft genug munged unter gcc zu arbeiten. Vielleicht, trotz der Unterschiede, das von einem gewissen Nutzen sein könnte:

#include <stdio.h>
int main()
{
    void *too = &&SomeLabel;
    unsigned int out;
    asm
    (
      "movl %0, %%eax;"
      :"=a"(out)
      :"r"(&&SomeLabel)
    );
SomeLabel:
    printf("Result: %p %x\n", too, out);

    return 0;
}

Dies erzeugt:

...
        movl    $.L2, %eax
...
.L2:

Der Operator && eine Nicht-Standard-Erweiterung ist, würde ich nicht erwarten, dass es als gcc irgendwo anders zu arbeiten. Hoffentlich kann dies ein paar neue Ideen ... Viel Glück aufgewühlt!

Edit: Obwohl es als Microsoft spezifisch aufgeführt ist, hier ist eine andere Instanz von Etiketten zu springen.

3 Vorschläge:

1) legte einen '_' vor dem SomeLabel in der Versammlung so wird es „mov eax, _SomeLabel “. In der Regel wird der Compiler einen hinzufügen, wenn es C in Montage übersetzt.

oder

2) setzen Sie das Etikett in einem Montageabschnitt. Dadurch wird der Compiler aus der Addition der ‚_‘ verhindern.

oder

3) Kommentar die Baugruppe aus, kompiliert und schauen in der List-Datei (* .lst) zu sehen, was der Markenname wird.

Ist der Turbo C ++ Umgebung eine Möglichkeit haben, um Optionen für TASM (Ich weiß, dass einige der Borland-IDEs haben)?

Wenn ja, ob die Option Wechsel für "Maximum geht (/ m)" auf 2 oder mehr hilft (es auf 1 Pass Standard könnte).

Auch, wenn Sie eine lange Markennamen verwenden sind, die ein Problem darstellen könnte - zumindest ein IDE hatte die Standardeinstellung 12. Ändern Sie setzen die „maximale Symbollänge (/ mv) Option“

.

Diese Information basiert auf Borland RAD Studio-IDE:

ein paar mehr Dinge (Schüsse im Dunkeln), um zu versuchen:

  • Sie, ob die folgende Montageanleitung verwendet hilft:

    mov eax, offset SomeLabel
    
  • Die meisten Compiler kann eine Assembler-Liste des Codes erzeugen sie erzeugen (nicht sicher, ob Turbo C ++ können, da CodeGear / Embarcadero Position sie als freie, nicht-professionellen Compiler).

    Versuchen Sie eine Liste mit C-Code erzeugen, die hat ein Etikett verwendet (als goto Ziel zum Beispiel), mit einiger Inline-Montage in der gleichen Funktion - aber versuchen Sie nicht aus der Anordnung das Etikett zuzugreifen. Dies ist, so dass Sie einen Compiler ohne Fehler und eine Assembler-Liste zu bekommen. So etwas wie:

    int foo()
    {
        int x = 3;
        printf( "x =%d\n", x);
        goto SomeLabel;
                               //
        __asm {
            mov eax, 0x01
        }
                               //
    SomeLabel:
        printf( "x =%d\n", x);
                               //
        return x;
    }
    

    an der Assembler-Liste suchen und sehen, ob die generierte Assembly die Labelnamen in eine Art und Weise verziert, die Sie in der Inline-Assembly zu replizieren möglicherweise in der Lage.

Von dem, was ich mich erinnere, Sie nicht ein externes (C ++) Etikett in Ihrer Inline-Assembly verwenden können, obwohl Sie TASM-Stil Etiketten in der asm-Block haben kann, die von der Montageanleitung selbst verwiesen werden kann. Ich glaube, ich würde einen Flag verwenden und eine Post-Assembler switch-Anweisung Verzweigung zu handhaben. Zum Beispiel:

int result=0;

__asm__ {
    mov result, 1
}

switch (result){
    case 1:  printf("You wanted case 1 to happen in your assembler\n"); break;
    case 0:  printf("Nothing changed with the result variable.. defaulting to:\n");
    default: printf("Default case!\n"); break;
}

Ich weiß nicht, über Ihre Compiler / Assembler speziell, aber ein Trick, die ich benutzt habe ziemlich viel rufen Sie die nächste Position ist und dann den Stapel in die Register Pop. Seien Sie sicher, dass der Anruf, den Sie nur machen schiebt die Absender-Adresse.

Ich denke, das Problem, das Sie in laufen ist, dass ein Etikett im __asm Block und das Label in dem C ++ Code sind zwei völlig verschiedene Dinge. Ich würde nicht erwarten, dass Sie von Inline-Assembler eines C ++ Etikett auf diese Weise verweisen könnten, aber ich muß sagen, dass es eine sehr lange Zeit, seit ich Turbo C ++ verwendet habe.

Haben Sie die lea Anweisung statt mov versucht?

nur raten, da ich nicht Inline-Assembler mit jeder C / ++ Compiler verwendet habe ...

void foo::bar( void )
{
    __asm
    {
      mov eax, SomeLabel
      // ...
    }
    // ...
    __asm
    {
      SomeLabel:
      // ...
    }
    // ...
}

Ich weiß nicht, die genaue Syntax von TASM.

Dies ist eine Variante von Ivan Vorschlag aber gibt diesen einen Versuch:

void foo::bar( void )
{
    __asm
    {
      mov eax, offset SomeLabel
      // ...
    }
    // ...
    __asm SomeLabel:
    // ...
}

Hier ist eine mögliche Methode:

// get_address
// gets the address of the instruction following the call
// to this function, for example
//     int addr = get_address (); // effectively returns the address of 'label'
//   label:
int get_address ()
{
    int address;
    asm
    {
        mov eax,[esp+8]
        mov address,eax
    }
    return address;
}
// get_label_address
// a bit like get_address but returns the address of the instruction pointed
// to by the jmp instruction after the call to this function, for example:
//     int addr;
//     asm
//     {
//       call get_label_address // gets the address of 'label'
//       jmp label
//       mov addr,eax
//     }
//     <some code>
//   label:
// note that the function should only be called from within an asm block.
int get_label_address()
{
    int address = 0;
    asm
    {
        mov esi,[esp+12]
        mov al,[esi]
        cmp al,0ebh
        jne not_short
        movsx eax,byte ptr [esi+1]
        lea eax,[eax+esi-1]
        mov address,eax
        add esi,2
        mov [esp+12],esi
        jmp done
    not_short:
        cmp al,0e9h
        jne not_long
        mov eax,dword ptr [esi+1]
        lea eax,[eax+esi+2]
        mov address,eax
        add esi,5
        mov [esp+12],esi
        jmp done
    not_long:
        // handle other jmp forms or generate an error
    done:
    }
    return address;
}
int main(int argc, char* argv[])
{
    int addr1,addr2;
    asm
    {
        call get_label_address
        jmp Label1
        mov addr1,eax
    }

    addr2 = get_address ();
Label1:
    return 0;
}

Es ist ein bisschen hacky aber es funktioniert in der Version von Turbo C ++, die ich habe. Es ist fast sicher ist abhängig von den Compiler und Optimierungseinstellungen.

eine der Optionen wäre separates "nackt" (Prolog-less) Verfahren SomeLabel zu verwenden anstelle von Label

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top