我需要有关使用ASSEMBLY部件的C代码的帮助。 GCC编译程序集时遇到问题,错误:
$ make
gcc -Wall -g -std=c99 -pedantic -c -o sthread.o sthread.c
sthread.c: In function ‘sthread_create’:
sthread.c:159:57: warning: pointer of type ‘void *’ used in arithmetic [-Wpointer-arith]
t->context = __sthread_initialize_context(t->memory + DEFAULT_STACKSIZE, f, arg);
^
gcc -Wall -g -std=c99 -pedantic -c -o queue.o queue.c
as -g -o glue.o glue.s
glue.s: Assembler messages:
glue.s:32: Error: operand type mismatch for `push'
<wbudowane>: polecenia dla obiektu 'glue.o' nie powiodły się
make: *** [glue.o] Błąd 1
有问题的代码:
__sthread_switch:
# preserve CPU state on the stack, with exception of stack pointer, instruction pointer first, reverse order
pushq %rip #line 32
pushf
pushq %rdi
pushq %rsi
pushq %rbp
pushq %rbx
pushq %rdx
pushq %rcx
pushq %rax
# Call the high-level scheduler with the current context as an argument
movq %rsp, %rdi
movq scheduler_context, %rsp
call __sthread_scheduler
答案 0 :(得分:5)
使用X86_64
您无法推送%rip
,实际上根本无法直接访问leaq 0(%rip), %rax # Or any other GPR that is free
pushq %rax
。
如果你仍然需要这样做,你可以
callq . + 5 # no label, hard-code instruction length
# or
callq 1f ; 1: # with a local numbered label
OR
%rip
虽然我不确定为什么你想隐藏list_of_imports = ['from path1.path2.path3 import x', 'from path1.path2.path4 import y', 'from path1.path2.path3 import z', 'from path1.path2.path2 import a']
for statement in list_of_imports:
try:
exec(statement)
except ImportError as e:
continue
,如果你从这里恢复它,执行将继续从推送指令。这有什么价值吗?您需要重新考虑线程切换逻辑。
答案 1 :(得分:1)
要推送RIP,只需执行零位移call
。
call next_insn
next_insn:
因此call
的跳转部分是无操作,因此您只能获得推送返回地址(即当前RIP)的效果。
有趣的事实:call rel32=0
is a special case and doesn't unbalance the return address predictor stack在CPU上比PPro更新。因此call next_insn / pop eax
在32位模式下非常有用,相当于lea (%rip), %rax
。
它仍然是一个分支指令,仍然解码为多个uop(不同于GPR的push
,它是1微融合的uop),所以lea (%rip), %rax
; push %rax
可能更有效率。