Сообщение от
Alex Rider
Вот
тут есть почитать про настройку Code::Blocks + SDCC, там есть примеры ассемблерных вставок, но, вроде, ничего не увидел про передачу параметров.
Во всех случаях возвращается значение в подгруппе DEHL. Если возвращаемое значение 32 бита это в DEHL, если это 16-бит Это в HL, если это 8-бит это в L. Кроме того, во всех случаях ваш подпрограмма не должна изменять IX или IY.
Есть три связи:
Скрытый текст
In all cases the return value is in a subset of DEHL. If the return value is 32-bits it's in DEHL, if it's 16-bits it's in HL, if it's 8-bits it's in L. Also in all cases your subroutine must not modify IX or IY.
There are three linkages:
[свернуть]
1. Normal
Параметры помещаются в стек в правом левом порядке. Стек не должен быть изменен вызываемой функции. Интс 2 байта, Лонги и поплавков 4 байта. Чар выталкивается в 1 байт, но если функция va_arg, символы продвигаются в целое перед толкнул. Возвращаемое значение находится в подгруппе DEHL.
Скрытый текст
Parameters are pushed onto the stack in right to left order. The stack must not be altered by the called function. Ints are 2-bytes, Longs and Floats are 4-bytes. Char is pushed as 1-byte but if the function is vararg, chars are promoted to int before being pushed. Return value is in a subset DEHL.
[свернуть]
extern char *strcpy(char *dst, const char *src);
Код:
_strcpy:
pop af ;; return address
pop de ;; de = char *dst
pop hl ;; hl = char *src
push hl
push de
push af
..
;; return value in HL
ret
2. Fastcall
Реализованные на совместимость z88dk в 3.5.5 купить исправления были применены после этого релиза. Использовать текущий SDCC для обеспечения он работает правильно.
Один параметр передается в регистре в подгруппе DEHL и возвращаемое значение в подгруппе DEHL.
Скрытый текст
Implemented for z88dk compatibility in 3.5.5 but bugfixes were applied after that release. Use the current sdcc to ensure it works properly.
A single parameter is passed by register in a subset of DEHL and the return value is in a subset of DEHL.
[свернуть]
extern int strlen(char *s) __z88dk_fastcall;
Код:
_strlen:
;; hl = char *s
...
;; return value in HL
ret
SDCC не в состоянии генерировать звонки на быстрых функций обработки вызовов с помощью указателей функций, если он не имеет права использовать регистр IY. В z88dk мы делаем функция указатели другой способ, чтобы они всегда работать.
Скрытый текст
sdcc is unable to generate calls to fastcall functions through function pointers unless it is allowed to use the IY register. In z88dk we do function pointers a different way so that they always work.
[свернуть]
3. Callee
Реализованные на совместимость z88dk в 3.5.5 купить исправления были применены после этого релиза. Использовать текущий SDCC для обеспечения он работает правильно.
Параметры помещаются в стек в справа налево для того, как в [B] 1. Normal [/ B], но называется функция отвечает за ремонт стек. Преимуществом является абонент не должен очистить стек после вызова функции каждого. Возвращаемое значение находится в подгруппе DEHL.
Скрытый текст
Implemented for z88dk compatibility in 3.5.5 but bugfixes were applied after that release. Use the current sdcc to ensure it works properly.
Parameters are pushed onto the stack in right to left order as in
1.Normal but the called function is responsible for repairing the stack. The advantage is the caller does not have to clear the stack after every function call. The return value is in a subset of DEHL.
[свернуть]
extern char *strcpy(char *dst, const char *src) __z88dk_callee;
Код:
_strcpy:
pop hl ;; hl = return address
pop de ;; de = char *dst
ex (sp),hl ;; hl = char *src, ret address onto stack
..
;; return value in HL
ret
Я не уверен, что если SDCC может генерировать указатель функции звонки на вызываемого абонента функций. Если он может, они будут по-разному набрали, так что указатели на функции не вызываемого абонента может быть назначен указателей на обычные функции. В z88dk мы делаем функция указатели другой способ, так что все работает прозрачно.
Скрытый текст
I'm not sure if sdcc can generate function pointer calls to callee functions. If it can, they will be typed differently so that pointers to callee functions cannot be assigned to pointers to regular functions. In z88dk we do function pointers a different way so everything works transparently.
[свернуть]
В дополнение к этому есть новые __preserves_regs () атрибут, который может сказать, что компилятор регистрирует функцию АНМ не меняется. На данный момент SDCC использует только информацию о нашей BC и DE, но я включаю все регистры главного набора в только в случае, SDCC расширяет это в будущем:
Скрытый текст
In addition to this there is a new __preserves_regs() attribute that can tell the compiler what registers the asm function does not change. At the moment sdcc only uses information about BC and DE but I include all registers of the main set in just in case sdcc expands this in the future:
[свернуть]
extern int strlen(char *s) __preserves_regs(d,e) __z88dk_fastcall;
Собрать среда для SDCC немного болезненные так много людей встроить свои функции ASM внутри C функций, которые вы можете сделать, но это не самый лучший способ делать вещи. Самый лучший способ, чтобы полностью отдельных ASM функции из кода C. Если вы сделаете это вы будете иметь больше контроля над тем, где ASM код находится в памяти, имея свободу, чтобы присвоить код АНМ в конкретной области или раздела. Также помните, что встроенный монтаж мешает глазок оптимизатора SDCC в:
Скрытый текст
The assemble environment for sdcc is a little bit painful so many people inline their asm functions inside C functions, which you can do, but it is not the best way to do things. The best way is to completely separate asm functions from the C code. If you do this you will have more control over where asm code is placed in memory by having the freedom to assign the asm code to a specific area or section. Also be aware that inlined assembly interferes with sdcc's peephole optimizer:
[свернуть]
Код:
void myfunc(void)
{
.....
// sdcc peepholer can't look into the asm block so it assumes all registers are modified by the "di"
__asm
di
__endasm;
...
}
В z88dk мы ввели встроенные функции, так что общие одиночные инструкции, как ди Е.И. остановке, и т.д. могут быть встроены, не влияя на глазок слишком много:
Скрытый текст
In z88dk we introduced intrinsics so that common single instructions like di, ei, halt, etc can be inlined without impacting the peepholer too much:
[свернуть]
Код:
void myfunc(void)
{
.....
intrinsic_di();
.....
}
Призыв к intrinsic_di() заменяется на "di", прежде чем глазок видит. Функция объявлена как сохранение всех регистров, так что компилятор может сохраняться регистры по вызову.
Скрытый текст
The call to intrinsic_di() is replaced by "di" before the peepholer sees it. The function is declared as preserving all registers so that the compiler is able to persist registers across the call.
[свернуть]