美好的一天。 我遇到了一个我几天都无法解决的问题。当我尝试用C语言编译这个函数时出现错误。
void GetInInterrupt(UChar Interrupt)
{
//asm volatile(".intel_syntax noprefix");
asm volatile
(
"movb %0, %%al\n"
"movb %%al, 1(point)\n"
"point:\n"
"int $0\n"
: /*output*/ : "r" (Interrupt) /*input*/ : /*clobbered*/
);
//asm volatile(".att_syntax noprefix");
}
我从天然气那里得到的消息如下:
Error: junk '(point)' after expression
我可以理解第二行中的指针有问题,但不幸的是我无法自己解决。
感谢您的帮助。
答案 0 :(得分:2)
下面显示了如何写入代码中的某个位置。它确实假设代码首先是可写的,这在主流操作系统中通常不是这种情况 - 因为这会隐藏一些令人讨厌的错误。
void GetInInterrupt(UChar Interrupt)
{
//asm volatile(".intel_syntax noprefix");
asm volatile
(
"movb %0, point+1\n"
"point:\n"
"int $0\n"
: /*output*/ : "r" (Interrupt) /*input*/ : /*clobbered */
);
//asm volatile(".att_syntax noprefix");
}
我还简化了代码以避免使用两个寄存器,而只是使用Interrupt
已经存在的寄存器。如果编译器对此有所了解,您可能会发现"a"
代替"r"
1}}解决问题。
答案 1 :(得分:2)
如果你可以使用C ++,那么这个:
template <int N> static inline void GetInInterrupt (void)
{
__asm__ ("int %0\n" : "N"(N));
}
会做的。如果我使用该模板,如:
GetInInterrupt<123>();
GetInInterrupt<3>();
GetInInterrupt<23>();
GetInInterrupt<0>();
创建以下对象代码:
0: cd 7b int $0x7b
2: cc int3
3: cd 17 int $0x17
5: cd 00 int $0x0
这是非常优化的(即使对于int3
情况,这是断点操作)。如果操作数超出0..255
范围,它还会创建编译时警告,因为N
约束仅允许操作数。
编辑:普通的旧式C风格的宏当然也有效:
#define GetInInterrupt(arg) __asm__("int %0\n" : : "N"((arg)) : "cc", "memory")
创建与C ++模板化函数相同的代码。由于int
的行为方式,最好告诉编译器(通过"cc", "memory"
约束)有关屏障语义,以确保它在嵌入时不会尝试重新排序指令。内联汇编。
显然,两者的局限性在于中断号必须是编译时常量。如果您绝对不希望这样,那么创建一个switch()
语句,例如在BOOST_PP_REPEAT()
的帮助下覆盖所有255个案例比自修改代码更好,例如:
#include <boost/preprocessor/repetition/repeat.html>
#define GET_INTO_INT(a, INT, d) case INT: GetInInterrupt<INT>(); break;
void GetInInterrupt(int interruptNumber)
{
switch(interruptNumber) {
BOOST_PP_REPEAT(256, GET_INTO_INT, 0)
default:
runtime_error("interrupt Number %d out of range", interruptNumber);
}
}
这个可以在普通的C中完成(如果你改变了普通__asm__
的模板化函数调用) - 因为boost预处理器库不依赖于C ++编译器...而gcc 4.7.2为此创建了以下代码:
GetInInterrupt:
.LFB0:
cmpl $255, %edi
jbe .L262
movl %edi, %esi
xorl %eax, %eax
movl $.LC0, %edi
jmp runtime_error
.p2align 4,,10
.p2align 3
.L262:
movl %edi, %edi
jmp *.L259(,%rdi,8)
.section .rodata
.align 8
.align 4
.L259:
.quad .L3
.quad .L4
[ ... ]
.quad .L258
.text
.L257:
#APP
# 17 "tccc.c" 1
int $254
# 0 "" 2
#NO_APP
ret
[ ... accordingly for the other vectors ... ]
请注意,如果您执行上述操作...编译器(gcc直到并包括4.8) 智能足以优化switch()
,即使您说{ {1}}它将创建static __inline__ ...
的完整跳转表版本,而不是简单实现的内联GetInInterrupt(3)
。