Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Професиональное программирование


Информационный Канал Subscribe.Ru

Приветствую.

Сегодня возврат к статьям ассемблерного уровня, 3-я статья из 4-х первых статей
от olegkit.

Кстати - никто не высказал мыслей о развитии темы Макинтош-Юникса...
Жаль - интересно знать ваше мнение автору, на столь редкую тему - интересно или
нет...

А сегодня рассылка вот такая:

Оптимизация для процессоров семейства Pentium: 3.

Оптимизация для процессоров семейства Pentium: 3. Вызов ассемблерных функций
из языка высокого уровня

Вы можете использовать встроенный ассемблер или написать процедуру полностью
на ассемблере и вставить ее в свой проект. Если вы выберете последний вариант,
рекомендуется, что компилятор умел переводить высокоуровневый код напрямую в
ассемблер. Это даст вам гарантию, что вы получите верный метод вызова функции.
Большинство компиляторов C++ умеют это делать.


Методы вызова функций и манглинг имен могут быть достаточно сложными. Существует
много различных соглашений о вызовах функций, и разные марки компиляторов не
совместимы друг с другом в этом отношении. Если вы вызываете ассемблерную процедуру
из C++, самым логичным и совместимым будет объявляление вашей функции как extern
"C" и _cdecl. К имени ассемблерной функции надо прибавить символ подчеркивания
и компилировать ее нужно указав чувствительность к регистрам в именах внешних
функций и переменных (опция -mx).

Если вам нужно использовать перегружаемые функции, перегружаемые операторы, функции-члены
классов и другие расширения C++, тогда вам нужно сначала написать это на C++
и заставить ваш компилятор перевести это в ассемблер, чтобы получить верную информацию
о линковке и методе вызова, так как они могут отличаться у разных компиляторов.
Если вам нужна ассемблерная функция, соглашение о вызове которой отличается от
extern "C" и _cdecl, вам нужно получить ее имя, создаваемое компилятором. Вот
пример перегруженной функции вычисления квадратного корня:

; int square (int x);
SQUARE_I PROC NEAR ; целочисленная функция вычисления квадратного корня
@square$qi LABEL NEAR ; имя, создаваемое компилятором Borland
?square@@YAHH@Z LABEL NEAR ; имя, создаваемое компилятором Microsoft
_square__Fi LABEL NEAR ; имя, создаваемое компилятором Gnu
PUBLIC @square$qi, ?square@@YAHH@Z, _square__Fi
MOV EAX, [ESP+4]
IMUL EAX
RET
SQUARE_I ENDP

; double square (double x);
SQUARE_D PROC NEAR ; функция вычисления квадратного корня с двойной точностью

@square$qd LABEL NEAR ; имя, создаваемое компилятором Borland
?square@@YANN@Z LABEL NEAR ; имя, создаваемое компилятором Microsoft
_square__Fd LABEL NEAR ; имя, создаваемое компилятором Gnu
PUBLIC @square$qd, ?square@@YANN@Z, _square__Fd
FLD QWORD PTR [ESP+4]
FMUL ST(0), ST(0)
RET
SQUARE_D ENDP
Способ передачи параметров зависит от соглашения о вызове функции:

соглашение порядок помещения параметров в стек кто очищает стек

_cdecl обратный вызывающий
_stdcall обратный процедура
_fastcall зависит от компилятора процедура
_pascal прямой процедура
Использование регистров в 16-ти битном режиме или Windows, C или C++: 16-ти битное
значение возвращается в AX, 32-х битное значение в DX:AX, значение с плавающей
запятой в ST(0). Регистры AX, BX, CX, DX, ES и арифметические флаги могут быть
изменены процедурой; другие регистры должны быть сохранены и восстановлены. Процедура
может полагаться на то, что при вызове другой процедуры значение SI, DI, BP,
DS и SS не изменится.

Использование регистров в 32-х битных Windows, C++ и других языках программирования:
целочисленное значение возвращается в EAX, значение с плавающей точкой возвращается
в ST(0). Регистры EAX, ECX, EDX (но не EBX) могут быть изменены процедурой; все
другие регистры должны быть сохранены и восстановлены. Сегментные регистры нельзя
изменять даже временно. CS, DS, ES и SS указываеют на плоский сегмент. FS используется
операционной системой. GS не используется, но зарезервирован. Флаги могут меняться
процедурой, но со следующими ограничениями: флаг направления равен 0 по умолчанию.
Его можно изменить временно, но при выходе из процедуры необходимо очистить.
Флаг прерывания не может быть очищен. Стековый регистр плавающей запятой пуст
при входе в процедуру и должен быть пустым при выходе, если только ST(0) не используется
для возвращения значения. Регистры MMX можно изменять, и если это было сделано,
их нужно очистить с помощью инструкции EMMS перед возвращением или вызовом любой
другой процедуры, которая может использовать регистры плавающей запятой. Все
XMM регистры можно свободно изменять. Правила для передачи параметров и возвращения
значений через регистры XMM объяснены в интеловском документе AP 589. Процедура
может полагаться на неизменность EBX, ESI, EDI, EBP и всех сегментных регистров
при вызове другой процедуры.

Все.

Еще одно, под конец...высказывайте свое мнение по статьям - так как тематика
статей иногда очень различна и если направление никого не интересует, а реакция,
как всегда молчание, ни авторы, ни я не можем принять правильного решения о направлениях...
Хотелось бы на сайте получить от вас желаемые тематики, многие мне пишут, что
с удовольствием написали бфы статьи и материалы, или переводы, но бояться что
будет неинтересно, например: программирование PIC контроллеров.


Всего доброго и удачи вам.
Громозека.

http://shelek.com/club/
http://shelek.com/
http://shelek.com/bn/


http://subscribe.ru/
E-mail: ask@subscribe.ru
Отписаться
Убрать рекламу

В избранное