首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >内联程序集,进入中断

内联程序集,进入中断
EN

Stack Overflow用户
提问于 2013-02-23 16:51:42
回答 2查看 5.9K关注 0票数 1

日安。我遇到了一个几天都无法解决的问题。当我试图用C语言编译这个函数时,会出现错误。

代码语言:javascript
复制
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");
}

我从煤气公司得到的信息如下:

代码语言:javascript
复制
Error: junk '(point)' after expression

正如我所理解的,第二行的指针是错误的,但不幸的是,我无法自己解决它。

谢谢你的帮助。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-02-25 17:48:32

如果您可以使用C++,那么这个:

代码语言:javascript
复制
template <int N> static inline void GetInInterrupt (void)
{
    __asm__ ("int %0\n" : "N"(N));
}

就行了。如果我使用这个模板,比如:

代码语言:javascript
复制
GetInInterrupt<123>();
GetInInterrupt<3>();
GetInInterrupt<23>();
GetInInterrupt<0>();

它创建以下对象代码:

代码语言:javascript
复制
   0:   cd 7b                   int    $0x7b
   2:   cc                      int3
   3:   cd 17                   int    $0x17
   5:   cd 00                   int    $0x0

这几乎是最优的(即使对于int3情况,也就是断点op)。它还将创建一个编译时警告,如果操作数超出了0..255范围,因为N约束只允许这样做。

编辑:当然,普通的C风格宏也可以工作:

代码语言:javascript
复制
#define GetInInterrupt(arg) __asm__("int %0\n" : : "N"((arg)) : "cc", "memory")

创建与C++模板函数相同的代码。由于int的行为方式,最好(通过"cc", "memory"约束)告诉编译器屏障语义,以确保它在嵌入内联程序集时不尝试重新排序指令。

显然,两者的限制是中断号必须是编译时常数这一事实。如果您完全不想这样做,那么创建一个switch()语句(例如,在涵盖所有255个情况的BOOST_PP_REPEAT()的帮助下)比自修改代码更好,例如:

代码语言:javascript
复制
#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为此创建了以下代码:

代码语言:javascript
复制
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

票数 2
EN

Stack Overflow用户

发布于 2013-02-23 21:26:49

下面显示如何写入代码中的某个位置。它确实假设代码一开始是可写的,这在主流操作系统中通常不是这样的,因为这会隐藏一些令人讨厌的错误。

代码语言:javascript
复制
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"解决了这个问题。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15042996

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档