Использование регистра ЦП C++

После некоторого исследования я думаю, что лучший ответ Xerces, поскольку это реализует весь XSD, является межплатформенным и широко используется. Я создал маленький проект Java на github для проверки из командной строки с помощью синтаксического анализатора JRE по умолчанию, который обычно является Xerces. Это может использоваться в Windows/Mac/Linux.

существует также версия C++ Xerces, доступного, если Вы использовали бы это. Утилита StdInParse может использоваться для вызова его из командной строки. Кроме того, комментатор ниже указывает на этот [еще 115] полная утилита .

обертки, Вы могли также использовать xmllint, который является частью libxml. Можно было уже установить его. Использование в качестве примера:

xmllint --noout --schema XSD_FILE XML_FILE

Одна проблема состоит в том, что libxml не реализует всю спецификацию, таким образом, можно столкнуться с проблемами: (

, С другой стороны, если Вы находитесь в Windows, можно использовать msxml, но Вам будет нужна своего рода обертка для вызова его, такие как GUI один описанный в этом статья DDJ. Однако кажется, что большинство людей в Windows использует XML-редактор, такой как Блокнот ++ (как описано в ответ Nate ) или Блокнот 2007 XML как [1 111] предложенный SteveC (существует также несколько коммерческих редакторов, которых я не упомяну здесь).

Наконец, Вы найдете, что различные программы, к сожалению, дадут различные результаты. Это происходит в основном из-за сложности спецификации XSD. Можно хотеть протестировать схему с несколькими инструментами.

ОБНОВЛЕНИЕ : я подробно остановился на этом в сообщение в блоге .

10
задан jakobengblom2 3 December 2009 в 12:04
поделиться

5 ответов

Заявление об ограничении ответственности: я не знаю MIPS, но я знаю некоторые x86, и я думаю, что принцип должен быть таким же.

В обычном соглашении о вызове функций компилятор будет поместите значение n в стек, чтобы передать его функции foo . Однако существует соглашение fastcall , которое вы можете использовать, чтобы указать gcc вместо этого передать значение через регистры. (MSVC также имеет эту опцию, но я не уверен, каков ее синтаксис.)

test.cpp:

int foo1 (int n) { return ++n; }
int foo2 (int n) __attribute__((fastcall));
int foo2 (int n) {
    return ++n;
}

Компиляция вышеуказанного с помощью g ++ -O3 -fomit-frame-pointer -c test.cpp , я получаю для foo1 :

mov eax,DWORD PTR [esp+0x4]
add eax,0x1
ret

Как видите, оно читается в значении из стека.

А вот foo2 :

lea eax,[ecx+0x1]
ret

Теперь это берет значение прямо из регистра.

Конечно, если вы встроите функцию, компилятор сделает простое добавление в теле вашей более крупной функции, независимо от указанного вами соглашения о вызовах. Но когда вы не можете встроить его, это произойдет.

Заявление об ограничении ответственности 2: я не говорю, что вы должны постоянно пересматривать компилятор. Вероятно, в большинстве случаев это непрактично и необходимо. Но не думайте, что он создает идеальный код.

Редактировать 1: Если вы говорите о простых локальных переменных (а не об аргументах функций), то да, компилятор разместит их в регистрах или в стеке по мере того, как он

Редактировать 2: Похоже, что соглашение о вызовах зависит от архитектуры, и MIPS передаст первые четыре аргумента в стеке, как сказал Ричард Пеннингтон в своем ответе. Так что в вашем случае вы не

9
ответ дан 3 December 2019 в 14:06
поделиться

Yes. There is no rule that "variables are always allocated on the stack". The C++ standard says nothing about a stack.It doesn't assume that a stack exists, or that registers exist. It just says how the code should behave, not how it should be implemented.

The compiler only stores variables on the stack when it has to - when they have to live past a function call for example, or if you try to take the address of them.

The compiler isn't stupid. ;)

12
ответ дан 3 December 2019 в 14:06
поделиться

Да, хороший оптимизирующий C / C ++ оптимизирует это. И даже НАМНОГО подробнее: См. Здесь: Обзор компилятора Феликса фон Лейтнера .

Обычный компилятор C / C ++ в любом случае не помещает каждую переменную в стек. Проблема с вашей функцией foo () может заключаться в том, что переменная может быть передана через стек в функцию (это определяет ABI вашей системы (оборудование / ОС)).

С помощью C ] register , вы можете дать компилятору подсказку , что, вероятно, было бы хорошо сохранить переменную в регистре. Пример:

register int x = 10;

Но помните: компилятор может не хранить x в регистре, если хочет!

8
ответ дан 3 December 2019 в 14:06
поделиться

The answer is yes, maybe. It depends on the compiler, the optimization level, and the target processor.

In the case of the mips, the first four parameters, if small, are passed in registers and the return value is returned in a register. So your example has no requirement to allocate anything on the stack.

Actually, truth is stranger than fiction. In your case the parameter is returned unchanged: the value returned is that of n before the ++ operator:

foo:
    .frame  $sp,0,$ra
    .mask   0x00000000,0
    .fmask  0x00000000,0

    addu    $2, $zero, $4
    jr      $ra
    nop
6
ответ дан 3 December 2019 в 14:06
поделиться

Поскольку ваша функция example foo является функцией идентификации (она просто возвращает ее аргумент), мой компилятор C ++ (VS 2008) полностью удаляет этот вызов функции. Если я изменю его на:

int foo( int n ) {
   return ++n;
}

, компилятор вставит это в

lea edx, [eax+1] 
2
ответ дан 3 December 2019 в 14:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: