Интерфейс с компилятором языка C
В этом разделе описывается интерфейс компилятора языка C фирмы HiTech Software (
http://www.htsoft.com) с программой на языке ассемблера.
Передача аргументов
Функция может принимать некоторое число аргументов передаваемых вызывающей программой. Аргументами функции могут быть переменные (значения) любых типов.
Для функций, объявленных в стиле K&R, когда аргументы функции не входят в её прототип, все аргументы передаются через стек как описано ниже. Для функций объявленных в стиле ANSI-C, когда в прототип функции входит информация о аргументах функции, передача аргументов осуществляется через регистры микропроцессора DE, BC и через стек. В любом случае, все 8-разрядные значения предварительно расширяются до 16-и разрядов, старшие разряды при этом никак не используются.
Если функция объявлена в стиле ANSI-C, первый аргумент функции, в том случае, если он является 8-и или 16-разрядным значением, передаётся в регистре DE микропроцессора. В регистре E передаётся 8-разрядный аргумент. В противном случае, первый аргумент передаётся через стек.
Если функция объявлена в стиле ANSI-C, второй аргумент функции, в том случае, если он является 8-и или 16-разрядным значением, передаётся в регистре BC микропроцессора. В регистре E передаётся 8-разрядный аргумент. В противном случае, второй аргумент передаётся через стек.
Третий и остальные аргументы функции всегда передаются через стек. Аргументы функции размещаются на стеке в обратном порядке, то-есть последний аргумент помещается на стек в первую очередь, а третий аргумент, в случае если оба первых аргумента передаются через регистры DE и BC, помещается на стек в последнюю очередь. Аргументы, занимающие в памяти один байт (8-разрядные), как уже говорилось, обязательно всегда расширяются до 16-и разрядов и следовательно на стеке занимают по два байта. Аргументы, занимающие в памяти 3 байта, расширяются до 32-х разрядов и помещаются на стек в 4 байта. Аргументы большей разрядности занимают на стеке ровно столько байт, сколько требуется для их сохранения, то-есть, например, если есть некий тип данных занимающий в памяти ровно 5 байт то он и на стеке займёт 5 байт если будет передан аргументом функции.
В случае, если функция объявлена в стиле ANSI-C и хоть один аргумент был передан через стек, то вызываемая функция обязана снять со стека все аргументы перед возвратом, а вызывающая программа может об этом не беспокоиться. В случае, когда функция объявлена в стиле K&R, вызывающая программа обязана извлечь из стека все аргументы переданные через стек.
Возврат результата
Функция может возвращать результат. Результатом может быть одна переменная (значение) любого типа. Способ, каким результат возвращается в вызываемую функцию определяется типом переменной результата. Все 8-разрядные значения предварительно расширяются до 16-разрядов, старшие разряды при этом не используются и могут содержать произвольное значение. Если результат умещается в 16 разрядов, то он возвращается в регистре HL. Если результат умещается в 32 разряда, то он возвращается в регистрах HL и DE: в регистре DE младшие разряды, а в регистре HL старшие. Результат большей разрядности (например массив или структура) помещается в статическую временную переменную, и в регистре HL возвращается указатель на эту переменную (нетрудно заметить, что в данном случае функция не может быть «реентрантной»).
Регистры микропроцессора
Функция может изменить содержимое любых регистров микропроцессора кроме SP и IX. Регистр SP всегда увеличивается на 2 при возврате из функции за счёт извлечения со стека адреса возврата. Дополнительно он может быть изменён в случае, если функция обязана извлечь аргументы из стека («Передача аргументов»). В регистре IX хранится указатель кадра стека вызывающей функции, поэтому вызываемая функция перед возвратом обязана восстановить содержимое регистра IX.