Тогда мне скорее непонятно откуда этот call взялся.
Вообще, sdcc не спрашивает про точку входа, игнорирует main, и всегда в начало бинарника кладет первую функцию первого файла. Поэтому я, дабы с ним не бороться, просто первой функцией кладу
Код:
void main_jump() __naked 
{
 jp _main
}
Но в случае, когда GSINIT не пустой, это не сработает.

Почему исходник в 100 строк (из которых половина - ассемблер) линкуется в 4кб бинарь? Я не использую никакие стандартные либы, указываю явно только собственные rel-ы от своих исходников.
Может где-нибудь явно ORG указано? Тогда промежуток между участками кода нулями забивается.
Еще если используются инициализированные массивы, то код тоже разрастается до гигантских размеров - но это как раз за счет GSINIT.