gcc 4.2.4: Как отменить оптимизацию функции ?
Вопрос такой:
Есть функция:
Код:
PUBLIC WORD tty_getpos(void)
/*
Возвращает текущую позицию курсора.
Эта функция обращается к регистрам
контроллера ЭЛТ.
*/
{
BYTE l, h;
__outb(POS_REG, CRT_PORT);
h = __inb(CRT_PORT + 1);
__outb((POS_REG + 1), CRT_PORT);
l = __inb(CRT_PORT + 1);
return ((h<<8) + l);
}
/*
Возвращает текущую позицию курсора.
Эта функция обращается к регистрам
контроллера ЭЛТ.
*/
{
BYTE l, h;
__outb(POS_REG, CRT_PORT);
h = __inb(CRT_PORT + 1);
__outb((POS_REG + 1), CRT_PORT);
l = __inb(CRT_PORT + 1);
return ((h<<8) + l);
}
Пусть Вас не смущают все эти BYTE, WORD и PUBLIC - это мои типы, они объявлены в h-файле, дело не в этом... Проблема в функциях __inb() и outb(). Данные функции объявлены в заголовке asm.h как static inline и с ними получается ерунда: при любом уровне оптимизацииб большем или равном 1 компилятор совершенно искажает код и в результате функция tty_getpos возвращает совсем не то, что надо. Если оптимизацию совсем отключить, то tty_getpos возвращает правильный результат, но теряется вся прелесть inline-функций - они становятся обычными функциями. Так вот вопрос: а нельзя ли gcc дать какой-нибудь ключик, или прагму, чтобы он оптимизацию в целом выполнил, а туда куда мне не надо не лез?
Спасибо!
- Код asm.h с вашими inb/outb, а так же то, что вас не устраивает на выходе компилятора в дизассемблере в студию. от Ramon, 08 марта 2012 года
pragma pack
Используй
Код:
/*
Возвращает текущую позицию курсора.
Эта функция обращается к регистрам
контроллера ЭЛТ.
*/
PUBLIC WORD tty_getpos(void) {
BYTE l, h;
#pragma pack(0)
__outb(POS_REG, CRT_PORT);
h = __inb(CRT_PORT + 1);
__outb((POS_REG + 1), CRT_PORT);
l = __inb(CRT_PORT + 1);
#pragma pack()
return ((h<<8) + l);
}
Возвращает текущую позицию курсора.
Эта функция обращается к регистрам
контроллера ЭЛТ.
*/
PUBLIC WORD tty_getpos(void) {
BYTE l, h;
#pragma pack(0)
__outb(POS_REG, CRT_PORT);
h = __inb(CRT_PORT + 1);
__outb((POS_REG + 1), CRT_PORT);
l = __inb(CRT_PORT + 1);
#pragma pack()
return ((h<<8) + l);
}
Цитата: mike
Используй pragma pack
Код:
/*
Возвращает текущую позицию курсора.
Эта функция обращается к регистрам
контроллера ЭЛТ.
*/
PUBLIC WORD tty_getpos(void) {
BYTE l, h;
#pragma pack(0)
__outb(POS_REG, CRT_PORT);
h = __inb(CRT_PORT + 1);
__outb((POS_REG + 1), CRT_PORT);
l = __inb(CRT_PORT + 1);
#pragma pack()
return ((h<<8) + l);
}
Возвращает текущую позицию курсора.
Эта функция обращается к регистрам
контроллера ЭЛТ.
*/
PUBLIC WORD tty_getpos(void) {
BYTE l, h;
#pragma pack(0)
__outb(POS_REG, CRT_PORT);
h = __inb(CRT_PORT + 1);
__outb((POS_REG + 1), CRT_PORT);
l = __inb(CRT_PORT + 1);
#pragma pack()
return ((h<<8) + l);
}
Какая связь между выравниванием данных и inline-функциями?
2 Topic starter
Читал, что все методы класса, реализованные в заголовках, становятся inline вне зависимости от того, был ли этот спецификатор. Можно поэкспериментировать на эту тему.
Оказыватся надо было употребить волшебное словечко __volatile__.
Вот мой файл asm.h:
Код:
#undef _ASSEMBLER_
#ifndef __ASM_H__
#define __ASM_H__
#include <defs.h>
INLINE BYTE __inb(WORD port)
{
BYTE result;
__asm__ __volatile__ (
"inb %w1, %b0\n" : "=a"(result) : "d"(port)
);
return result;
}
INLINE VOID __outb(BYTE val, WORD port)
{
__asm__ __volatile__ (
"outb %b0, %w1\n" : : "a"(val), "d"(port)
);
}
#endif
#ifndef __ASM_H__
#define __ASM_H__
#include <defs.h>
INLINE BYTE __inb(WORD port)
{
BYTE result;
__asm__ __volatile__ (
"inb %w1, %b0\n" : "=a"(result) : "d"(port)
);
return result;
}
INLINE VOID __outb(BYTE val, WORD port)
{
__asm__ __volatile__ (
"outb %b0, %w1\n" : : "a"(val), "d"(port)
);
}
#endif
Все неприятности были от того, что не было слова __volatile__ в операторе __asm__.