Можно ли получить доступ к 32-битным регистрам в C? Если да, то как? А если нет, то есть ли способ встроить ассемблерный код в C? Кстати, я использую компилятор MinGW. Заранее спасибо!
Можно ли получить доступ к 32-битным регистрам в C?
Ответы (7)
Если вы хотите только читать регистр, вы можете просто:
register int ecx asm("ecx");
Очевидно, это связано с созданием экземпляров.
Другой способ — использование встроенной сборки. Например:
asm("movl %%ecx, %0;" : "=r" (value) : );
Это сохраняет значение ecx
в переменной value
. Я уже публиковал аналогичный ответ здесь.
К каким регистрам вы хотите получить доступ?
Регистры общего назначения обычно не доступны из C. Вы можете объявить регистровые переменные в функции, но это не указывает, какие именно регистры используются. Кроме того, большинство компиляторов игнорируют ключевое слово register и автоматически оптимизируют использование регистров.
Во встроенных системах часто необходимо получить доступ к периферийным регистрам (таким как таймеры, контроллеры прямого доступа к памяти, контакты ввода/вывода). Такие регистры обычно отображаются в память, поэтому к ним можно получить доступ из C...
определяя указатель:
volatile unsigned int *control_register_ptr = (unsigned int*) 0x00000178;
или с помощью препроцессора:
#define control_register (*(unsigned int*) 0x00000178)
Или вы можете использовать процедуру сборки.
Для использования языка ассемблера есть (как минимум) три возможности:
- Отдельный исходный файл .asm, связанный с программой. Подпрограммы ассемблера вызываются из C как обычные функции. Это, вероятно, наиболее распространенный метод, и его преимущество заключается в том, что аппаратно-зависимые функции отделены от кода приложения.
- Поточная сборка
- Встроенные функции, выполняющие отдельные инструкции языка ассемблера. Это имеет то преимущество, что инструкция языка ассемблера может напрямую обращаться к любым переменным C.
Вы можете встроить сборку в C
http://en.wikipedia.org/wiki/Inline_assembler
пример из википедии
внешняя внутренняя ошибка;
int funcname(int arg1, int *arg2, int arg3)
{
int res;
__asm__ volatile(
"int $0x80" /* make the request to the OS */
: "=a" (res) /* return result in eax ("a") */
"+b" (arg1), /* pass arg1 in ebx ("b") */
"+c" (arg2), /* pass arg2 in ecx ("c") */
"+d" (arg3) /* pass arg3 in edx ("d") */
: "a" (128) /* pass system call number in eax ("a") */
: "memory", "cc"); /* announce to the compiler that the memory and condition codes have been modified */
/* The operating system will return a negative value on error;
* wrappers return -1 on error and set the errno global variable */
if (-125 <= res && res < 0) {
errno = -res;
res = -1;
}
return res;
}
Я не думаю, что вы можете сделать их напрямую. Вы можете выполнять встроенную сборку с кодом, например:
asm (
"movl $0, %%ebx;"
"movl $1, %%eax;"
);
Если вы на 32-битном процессоре и используете адекватный компилятор, то да. Точные средства зависят от конкретной системы и компилятора, для которого вы программируете, и, конечно, это сделает ваш код настолько непереносимым, насколько это возможно.
В вашем случае с MinGW вы должны посмотреть на синтаксис встроенного ассемблера GCC. а>.
Вы можете, конечно. «MinGW» (gcc) позволяет (как и другие компиляторы) встроенную сборку, как уже показывают другие ответы. Какая сборка, зависит от процессора вашей системы (вероятность 99,99%, что это x86). Однако это делает вашу программу не переносимой на другие процессоры (не так уж плохо, если вы знаете, что делаете и почему).
Соответствующая страница, посвященная сборке для gcc, находится здесь и здесь и, если хотите, также здесь. Не забывайте, что он не может быть конкретным, так как он зависит от архитектуры (gcc может компилироваться для нескольких процессоров)
как правило, нет необходимости обращаться к регистрам ЦП из программы, написанной на языке высокого уровня: языки высокого уровня, такие как C, Pascal и т. д., специально придуманы для того, чтобы абстрагировать базовую машину и сделать программу более машиноподобной. независимый.
я подозреваю, что вы пытаетесь что-то сделать, но понятия не имеете, как использовать обычный способ сделать это.
многие доступы к регистрам скрыты в конструкциях более высокого уровня или в системных или библиотечных вызовах, что позволяет вам избежать кодирования «грязной части». расскажите нам больше о том, что вы хотите сделать, и мы можем предложить вам альтернативу.