Informationen, die besagen, dass die Inline-Assembly einen bestimmten Speicherbereich liest

GCC (alle Versionen, die ich bequem testen kann) zeigt an, dass eine Inline-Assembly-Anweisung eine bestimmte Speicherregion liest (ausgedrückt als Zeigerp und eine Größen) mit diesem zugegebenermaßen umständlichen Konstrukt:

asm ("..." : : "m" (*(struct { char x[n]; } *)p));

Das funktioniert jedoch nicht in Clang (3. [45]), es wird ein schwerer Fehler angezeigt:

 error: fields must have a constant size: 'variable
      length array in structure' extension will never be supported
 asm ("..." : : "m" (*(struct {char x[n];} *)p));
                                    ^

Ist es (idealerweise) ein anderes Konstrukt, das in beiden Compilern den gleichen Effekt erzeugt, oder (falls dies nicht der Fall ist) ein anderes Konstrukt, das nur in clang den gleichen Effekt erzeugt?

Beachten Sie, dass ich für den Fall, dass es mir wichtig ist, keine tatsächlichen Montageanweisungen einfüge. Der Zweck des Konstrukts besteht darin, den Compiler anzuweisen, ein scheinbar totes @ nicht zu löschememset. Somit könnte das "andere Konstrukt" durchaus überhaupt keine Inline-Montage beinhalten. Bitte schlagen Sie jedoch Konstrukte vor, die wie folgt lautewillkürlic memory oder generieren Sie zusätzlichen Code, wenn es keine Alternative gibt. Schlagen Sie auch NICHT @ vmemset_s, explicit_bzero, o.ä; Dies ist ein Versuch,implementiere ein Fallback für diese Funktionen, ohne den Compiler hacken zu müssen.

Full-Scale-Demo-Programm folgt -

#include <string.h>

extern void foo(const char *a, const char *b, const char *c, char *d);

void bar(const char *x, char *y, size_t n)
{
  char w[16];
  char v[n];
  memset(w, 0x11, n);
  memset(v, 0x22, n);

  foo(w, v, x, y);

  memset(w, 0, 16);
  memset(v, 0, n);
  asm ("" : : "m" (*(struct {char _[n];} *)v));
}

- wie von gcc 5.0 um @ kompilie-O2 -S, x86-64, CFI goo elided -

bar:
        pushq   %rbp
        leaq    15(%rdx), %rax
        movq    %rsp, %rbp
        pushq   %r14
        andq    $-16, %rax
        movq    %rsi, %r14
        pushq   %r13
        movl    $17, %esi
        movq    %rdi, %r13
        pushq   %r12
        leaq    -48(%rbp), %rdi
        pushq   %rbx
        movq    %rdx, %rbx
        subq    $16, %rsp
        subq    %rax, %rsp
        call    memset
        movq    %rbx, %rdx
        movq    %rsp, %rdi
        movl    $34, %esi
        call    memset
        movq    %r14, %rcx
        movq    %r13, %rdx
        movq    %rsp, %rsi
        leaq    -48(%rbp), %rdi
        call    foo
        movq    %rbx, %rdx
        xorl    %esi, %esi
        movq    %rsp, %rdi
        call    memset
        leaq    -32(%rbp), %rsp
        popq    %rbx
        popq    %r12
        popq    %r13
        popq    %r14
        popq    %rbp
        ret

- das Ziel ist es, das @ zu bekommselbe Numme des Blockspeichers füllt sich mit Klirren. Zwei ist falsch, aber vier ist auch falsch.

Antworten auf die Frage(0)

Ihre Antwort auf die Frage