Как мне написать все это в сборке - PullRequest
8 голосов
/ 25 ноября 2011

У меня есть два макроса, один написан на ассемблере, а другой на C. Второй макрос использует первый макрос. Однако я также хочу написать второй макрос в сборке с помощью volatile, чтобы я мог контролировать его размещение в коде. И обратите внимание, что tid - это значение времени выполнения, а не константа, такая как n .

Какой хороший способ написать это в сборке? Кроме того, возможно ли управлять размещением кода на C, подобного сборке, с volatile?

#define SAVE_SP(n) __asm__ __volatile__ ("movq %rsp, msp"#n";" \
     "movq ts"#n", %rsp;" \
     )

#define SAVE_STACK_POINTER( tid ) \
    switch( tid ) \
    { \
        case 0: \
            SAVE_SP( 0 ); \
            break; \
        case 1: \
            SAVE_SP( 1 ); \
            break; \
        case 2: \
            SAVE_SP( 2 ); \
            break; \
        case 3: \
            SAVE_SP( 3 ); \
            break; \
    }

Ответы [ 2 ]

6 голосов
/ 25 ноября 2011

Вы можете задать gcc идею о том, как написать свой код на ассемблере: gcc -S foo.c или gcc -Wa,-alh=foo.s -c foo.c.Вы можете улучшить результаты, конечно.Вам нужно будет сделать немного больше: используйте %0 для параметра, который вы передаете для фрагмента сборки, и объявите регистры, которые вы перекрыли.Посмотрите инструкции ассемблера с операндами выражения C в руководстве GCC , если вы не знакомы.Вот как это может выглядеть (предупреждение, введенное непосредственно в браузер, и на самом деле не знаю синтаксис сборки x86).

#define SAVE_STACK_POINTER(tid) __asm__ __volatile__ (" \
        cmpl $0, %0                                   \n\
        je .SAVE_STACK_POINTER_0                      \n\
        cmpl $1, %0                                   \n\
        je .SAVE_STACK_POINTER_1                      \n\
        cmpl $2, %0                                   \n\
        je .SAVE_STACK_POINTER_2                      \n\
        cmpl $3, %0                                   \n\
        je .SAVE_STACK_POINTER_3                      \n\
        jmp .SAVE_STACK_POINTER_done                  \n\
      .SAVE_STACK_POINTER_0:                          \n\
        movq %%rsp, msp0                              \n\
        movq ts0, %%rsp                               \n\
        jmp SAVE_STACK_POINTER_done                   \n\
      .SAVE_STACK_POINTER_1:                          \n\
        movq %%rsp, msp1                              \n\
        movq ts1, %%rsp                               \n\
        jmp SAVE_STACK_POINTER_done                   \n\
      .SAVE_STACK_POINTER_2:                          \n\
        movq %%rsp, msp2                              \n\
        movq ts2, %%rsp                               \n\
        jmp SAVE_STACK_POINTER_done                   \n\
      .SAVE_STACK_POINTER_3:                          \n\
        movq %%rsp, msp3                              \n\
        movq ts3, %%rsp                               \n\
      .SAVE_STACK_POINTER_done:                       \n\
    " : : "r" (tid))

Более сложный метод предполагает вычисление количества байтов movqmovq - jmp блок берет (примечание: я не проверял, я использую 8) и совершает вычисленный переход в него;что-то вроде

__asm__("                        \n\
    movl %0, %eax                \n\
    mul  8, %eax                 \n\
    add  4, %eax                 \n\
    jmp . + %eax                 \n\
    movq %%rsp, msp0             \n\
    movq ts0, %%rsp              \n\
    jmp .SAVE_STACK_POINTER_done \n\
    …
  .SAVE_STACK_POINTER_done:      \n\
" : : "r" (tid) : "%eax")
1 голос
/ 29 ноября 2011

Предполагая, что вы используете GCC, вы можете попытаться использовать расширение GNU, чтобы отобразить регистр указателя стека на переменную C:

static register int stack_pointer0 asm("msp0");

void myfn () {
  ......
  saved_stack_pointer = stack_pointer0;
  ......
}

ОК, это, вероятно, не делает то, что ваш исходный кодсделал (мне не было ясно, какова была цель), но вы должны быть в состоянии выяснить остальное из этого.

Я думаю, что я правильно понял синтаксис, но извиняюсь, если нет.Я знаю, что это работает для общих регистров, и я довольно уверен, что GCC знает, что делать для специальных регистров, но вы никогда не знаете.

Надеюсь, это поможет.

...