Как вграденото (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

В GCC вие трябва да посочите изрично засегнатите регистри, за да предотвратите повреда на потока на изпълнение:

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

Докато компилаторът е наясно с промените в записите, изброени в изходните операнди, вграденият asm код може да модифицира повече от изходите.[...] изчисленията може да изискват допълнителни регистри, [...] избройте ги в списъка на clobber.

Моля, използвайте аргумента memory clobber, ако вашият код извършва четене или запис на други елементи, различни от вече изброените.

Изтриването на паметта казва на компилатора, че асемблерният код извършва четене или запис от паметта на елементи, различни от изброените във входните и изходните операнди

Справка: https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html

MSVC

В 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 и добавена бележка относно аргумента за изтриване на паметта, следвайки предложенията на Olafs.

person oo_miguel    schedule 29.10.2015
comment
Всъщност вие трябва да специфицирате объркани регистри и дори памет. Това не е задължително. - person too honest for this site; 29.10.2015
comment
@Olaf: Съгласен съм :). Адаптира отговора. - person oo_miguel; 29.10.2015
comment
Споменах и паметта умишлено. Без това да е посочено, gcc може да съдържа стойности от променливи на паметта, напр. масиви/структури/и др. в неизтрити регистри, по този начин вашият код на асемблер може да има достъп до остарели данни, когато ги чете. Това е причината да можете да използвате asm volatile { "" :::"memory" } като бариера за компилатор. - person too honest for this site; 29.10.2015

Има някои допълнителни флагове, които могат да бъдат предадени на вградения код за асемблиране. Един от тях е "clobber list", който показва на 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