"Затирание" содержимого регистров
До настоящего момента времени, мы явно указывали компилятору (посредством параметров ввода и вывода) какие регистры процессора мы используем, и генератор кода компилятора вынужден был это учитывать.
Однако, что произойдет в том случае когда мы используем какой-либо регистр процессора, а компилятор об этом не знает?
Можно догадаться, что в таком случае компилятор тоже будет использовать этот регистр процессора, а результатом этого будет какой-нибудь "сюрприз" при работе программы.
Следовательно, использование в коде ассемблера какого-либо регистра процессора, о котором компилятору ничего не известно, может привести к каким-нибудь побочным эффектам в инструкциях (например, mull, сохраняющая результат своего действия в двух регистрах eax и edx) или в действиях, описанных в коде ассемблера, подобно следующему:
Asm ("movl %0, %%ebx" & "movl %%ebx, %1", Inputs => Unsigned_32'Asm_Input ("=g", Input), Outputs => Unsigned_32'Asm_Output ("g", Output)); |
Здесь, компилятор не подозревает о том, что регистр ebx уже используется. В подобных случаях, необходимо использовать параметр Clobber, который дополнительно укажет компилятору регистры, используемые в коде ассемблера:
Asm ("movl %0, %%ebx" & "movl %%ebx, %1", Inputs => Unsigned_32'Asm_Input ("=g", Input), Outputs => Unsigned_32'Asm_Output ("g", Output), Clobber => "ebx"); |
Как видно из этого примера, параметр Clobber является простой строкой, которая содержит список используемых регистров процессора.
Для случаев использования параметра Clobber
необходимо сделать два дополнительных замечания:
Кроме перечисления используемых регистров в параметре Clobber, существует еще два именованых параметра которые удобно использовать в некоторых случаях:
использование регистра cc указывает, что могут быть изменены флаги
использование регистра memory указывает, что может быть изменено расположение в памяти