日安。我遇到了一个几天都无法解决的问题。当我试图用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正如我所理解的,第二行的指针是错误的,但不幸的是,我无法自己解决它。
谢谢你的帮助。
发布于 2013-02-25 17:48:32
如果您可以使用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情况,也就是断点op)。它还将创建一个编译时警告,如果操作数超出了0..255范围,因为N约束只允许这样做。
编辑:当然,普通的C风格宏也可以工作:
#define GetInInterrupt(arg) __asm__("int %0\n" : : "N"((arg)) : "cc", "memory")创建与C++模板函数相同的代码。由于int的行为方式,最好(通过"cc", "memory"约束)告诉编译器屏障语义,以确保它在嵌入内联程序集时不尝试重新排序指令。
显然,两者的限制是中断号必须是编译时常数这一事实。如果您完全不想这样做,那么创建一个switch()语句(例如,在涵盖所有255个情况的BOOST_PP_REPEAT()的帮助下)比自修改代码更好,例如:
#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(),也就是说,即使您说static __inline__ ...,它也会创建GetInInterrupt(3)的完整跳转表版本,而不是像更简单的实现那样只创建内联的int3。
发布于 2013-02-23 21:26:49
下面显示如何写入代码中的某个位置。它确实假设代码一开始是可写的,这在主流操作系统中通常不是这样的,因为这会隐藏一些令人讨厌的错误。
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"解决了这个问题。
https://stackoverflow.com/questions/15042996
复制相似问题