Met*_*est 8 c linux x86 assembly gcc
我有两个宏,一个是用汇编编写的,另一个是用C编写的.第二个宏使用第一个宏.但是,我还想在volatile中使用程序集编写第二个宏,因此我可以在代码中控制它的位置.请注意,tid是运行时值,而不是像n那样的常量.
在汇编中写这个的好方法是什么?另外,是否可以通过volatile来控制C代码的放置?
#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; \
}
Run Code Online (Sandbox Code Playgroud)
您可以向gcc询问如何在汇编中编写代码:gcc -S foo.c
或者gcc -Wa,-alh=foo.s -c foo.c
.当然,您可能希望改进结果.您需要做一些额外的工作:使用%0
您为程序集块传递的参数,并声明您已经破坏的寄存器.如果您不熟悉,请在GCC手册中查找带有C表达式操作数的汇编程序指令.这可能是这样的(警告,直接输入到浏览器中,并不真正了解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))
Run Code Online (Sandbox Code Playgroud)
票友方法会涉及搞清楚每个多少字节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")
Run Code Online (Sandbox Code Playgroud)