Вы можете задать 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))
Более сложный метод предполагает вычисление количества байтов movq
movq
- 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")