Разница в компиляторах начинается на уровне нюансов. Оптимальным, на мой взгляд, является XC8. К тому же потом можно легко перейти на XC16 и XC32. Но, как я уже сказал, бесплатная версия отличается полным отсутствием оптимизации. По моим наблюдениям это дает раза в 2 - 2.5 больший объем кода и скорость работы раза в 3 ниже, чем с оптимизацией лицензии PRO (там есть возможность 2 месяца бесплатно тестировать PRO). Стоимость лицензии PRO для XC8 варианта "рабочая станция" составляет 995 USD, что многовато для начинающих и тех, кто не зарабатывает этим деньги. Подписка в России не продается, проверял сам.
Mikro C бесплатно позволяет генерировать до 2 кБ кода. Не работает под Linux (для меня очень критично). Платная версия стоит 249 USD. Особого ничего сказать не могу, только немного погонял на простеньком примере. IDE навороченная, но это к компиляции имеет довольно опосредованное отношение. Кстати, этот же производитель делает и компилятор Pascal и Basic.
CCS использую сам. Версия командной строки для Linux. Есть и версия с IDE. Без IDE может компилировать только один файл, но это легко обходится через include, хотя добавляет неудобств. У компилятора разные версии, PCB, PCM, PCH, PCD под base-range, mid-range, extended mid-range, PIC24. И покупать их надо по отдельности. От прочих компиляторов отличается скрытостью описаний контроллеров и некой оберткой маскирующей физические отличия контроллеров. То есть, прочитав документацию на контроллер прямо так один в один к компилятору ее не применить. Зато появляется переносимость, так как функции работы, например с PWM будут работать на любом контроллере, даже если у него регистры по иному устроены. Опять таки, у него приличная библиотека, встроенная. Например, там можно писать программу совершенно не обращая внимания есть встроенный I2C master в контроллере, или он будет эмулироваться программно встроенной библиотекой. При этом можно получить и стандартные имена, например, бита запуска таймера, но они будут не в .h фале, а в программе функцией genenv (отрабатывает на уровне компиляции, а не выполнения). То есть, всю эту обертку можно легко обойти, если надо. У меня PCML, версия командной строки Linux, покупал за 150 USD.
Что касается трансляции команд С в команды контроллера, то ничего мистического там нет и все видно в asm файле для любого компилятора. Конечно, там будет много такого, чего Вы не напишете сами, но это необходимо, так как в любом случае есть некая "среда времени выполнения" (run-time environment). Она есть у любого компилятора для любой целевой архитектуры. Но если Вы пишете действительно большую программу, то объем кода на ассемблере будут сравнимым со сгенерированным компилятором С кодом. Зато пишется быстрее.
И ничего там само не будет выполняться. Все точно так же, как на ассемблере. Есть проверка в программе на ассемблере, выполняется пару раз за программу, точно так же будет и для С с оператором if. Цикл так цикл. Только надо учитывать, что цикл лучше делать не с автоинкрементом, а с автодекрементом. Просто в итоговом коде это будет чуть быстрее. И "дерганье ногой" делается элементарно. И прерывания будут работать точно так же.
Что бы стало понятнее, можете прислать мне пример программы на ассемблере, для начала простой. Я отвечу, как это будет на C. Оттранслирую в XC8 и CCS, пришлю lst файлы, добавив туда немного комментариев для большей понятности. Конечно, полностью сгенерироваггый код комментировать и описывать не буду, но основные моменты помечу.
Но вообще, если разберетесь собственно с С и будете понимать, как работает контроллер, то разобраться в другом компиляторе не составит большого труда. Переписать программу будет немного муторно, но вполне выполнимо. Сложнее, когда новый компилятор менее функционален и наворочен, чем ранее используемый.
Поверьте, для Вас будет гораздо большим открытием тот факт, что не всегда написанное на С будет выполняться

Про модификатор voltile для переменных промолчу, тут регистров общего назначения нет, почти все делается через WREG, так что они все volatile получаются. А вот логические выражения запросто могут закончить вычисляться до окончания собственно выражения, просто результат станет известен заранее. И если Вы в таком выражении используете автоинкремент, например, а эта часть выражения окажется пропущенной, причем во время выполнения, то автоинремента не будет. И искать, без понимания того, как логические выражения вычисляются, Вы это будете долго. И отладчик не поможет, так как такой пропуск может выполняться не каждый раз (например, не каждую итерацию цикла). Кстати, это работа оптимизатора компилятора.
Мир вокруг нас разумен настолько, насколько разумны мы сами. Профессионал не обязательно говорит умные слова, но зная самые глубины, способен объяснить их любому "на пальцах".