Если вы можете использовать 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
, допускающего только это.
Edit: простые старые макросы 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()
прочь, то есть даже если вы скажете static __inline__ ...
, это создаст полную версию таблицы прыжков GetInInterrupt(3)
вместо просто встроенного int3
, а также более простые реализации.
Что вы на самом деле пытаетесь сделать [и вы должны добавить '' al "' (или eax) в свой «сбитый список», иначе компилятор рано или поздно сделает что-то с помощью eax, который разрушит ваши планы здесь. Вы хотите вызвать деление на нулевую ошибку? –
добавление «al» в список закладок - хорошая идея, спасибо. Я действительно хочу изменить $ 0 после команды «int» на значение, хранящееся в переменной «Прерывание» – hrust
Вы не можете этого сделать - код доступен только для чтения. Вам нужно будет написать намного больше кода, включая добавление кода для 'mprotect' или' VirtualProtect', чтобы вы могли указывать код для чтения-записи, а не только для чтения. Почему вы не знаете, какое прерывание вы хотите назвать? –