Как встроенный (x86) ассемблер влияет на ход выполнения программы?

Я пытаюсь понять, как такие фрагменты вызываются во время выполнения:

__asm{
    PUSH ES
    MOV CX,0
    //... More x86 assembly
};

Не повредит ли настройка регистров выполнение потока программы?

Например: если CX выше содержит какое-то значение, не будет ли это означать, что это значение регистра больше не будет действительным?

Заботится ли компилятор об этих зависимостях или выполнение фрагмента происходит при особых обстоятельствах?

В каких компиляторах использование встроенной сборки непрозрачно?


person Mini Fridge    schedule 29.10.2015    source источник
comment
Попробуйте посмотреть на получившийся ассемблерный код всей функции.   -  person Eugene Sh.    schedule 29.10.2015
comment
В таких вопросах рассказать нам компилятор было бы шикарно. GCC (с расширенной сборкой) обрабатывает это иначе, чем, например, clang.   -  person cadaniluk    schedule 29.10.2015
comment
Это скорее зависит от компилятора. Некоторые компиляторы ожидают, что все регистры будут сохранены, в то время как некоторые пытаются отслеживать использование регистров кода для вас, а другие требуют, чтобы вы вручную размечали затертые регистры. Встроенная сборка по своей сути специфична для компилятора, поэтому вам придется прочитать правила в руководстве по компилятору.   -  person doynax    schedule 29.10.2015


Ответы (2)


ССАГПЗ

В GCC вам необходимо явно указать затронутые регистры, чтобы предотвратить повреждение потока выполнения:

asm [volatile] ( AssemblerTemplate
                  : OutputOperands
                  [ : InputOperands
                  [ : Clobbers ] ])

Хотя компилятор знает об изменениях записей, перечисленных в выходных операндах, встроенный ассемблерный код может изменить не только выходные данные.[...] вычисления могут потребовать дополнительных регистров, [...] перечислите их в списке затирания.

Пожалуйста, используйте аргумент memory clobber, если ваш код выполняет чтение или запись для других элементов, отличных от перечисленных.

Засоритель памяти сообщает компилятору, что ассемблерный код выполняет чтение или запись в память элементов, отличных от тех, которые перечислены во входных и выходных операндах.

Ссылка: https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html

МСВК

С другой стороны, в MSVC вам не нужно сохранять регистры общего назначения:

При использовании __asm ​​для написания на ассемблере функций C/C++ вам не нужно сохранять регистры EAX, EBX, ECX, EDX, ESI или EDI. [...]

Вы должны сохранить другие используемые вами регистры (такие как регистры DS, SS, SP, BP и флаги) для блока __asm. Вы должны сохранить регистры ESP и EBP, если у вас нет причин их менять.

Ссылка: https://msdn.microsoft.com/en-us/library/k1a8ss06.aspx


РЕДАКТИРОВАНИЕ: изменено следует на должно для gcc и добавлено примечание об аргументе затирания памяти, следуя предложениям Олафа.

person oo_miguel    schedule 29.10.2015
comment
На самом деле вам должно указываться затертые регистры и даже память. Это необязательно. - person too honest for this site; 29.10.2015
comment
@ Олаф: я согласен :). Адаптировал ответ. - person oo_miguel; 29.10.2015
comment
Память я тоже упомянул намеренно. Без этого списка gcc может хранить значения из переменных памяти, например. массивы/структуры/и т.д. в незатертых регистрах, поэтому ваш ассемблерный код может получить доступ к устаревшим данным при их чтении. По этой причине вы можете использовать asm volatile { "" :::"memory" } в качестве барьера компилятора. - person too honest for this site; 29.10.2015

Есть несколько дополнительных флагов, которые можно передать во встроенный ассемблерный код. Одним из них является «список затирания», который указывает компилятору C/C++ список регистров, которые будут изменены блоком ассемблерного кода.

Обратите внимание, что способ указания этих дополнительных флагов зависит от компилятора (он совершенно другой в Microsoft Visual C++, GCC и т. д.).

Для GCC см., например:

https://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html#ss5.3

person BrunoLevy    schedule 29.10.2015
comment
Он явно спрашивает о (Microsoft) Visual C++. - person Jonathon Reinhart; 29.10.2015
comment
@JonathonReinhart: последнее редактирование также добавило GCC к тегам. - person Michael Foukarakis; 29.10.2015
comment
Встроенный ассемблер зависит от реализации. Как написано, ваш ответ вызывает впечатление, что существует один общий синтаксис/семантика. Пожалуйста, отредактируйте. - person too honest for this site; 29.10.2015