SDCC изменилось, как куча инициализируется так ЭЛТ размещены там должен быть изменен немного. Лучше начать с того, что обеспечивает SDCC и устранить то, что вам не нужно:Несколькими страницами назад есть даже модифицированный crt0.s...
Скрытый текст
sdcc has changed how the heap is initialized so the crt posted there should be changed a little bit. It's best to start with what sdcc provides and eliminate what you don't need:
[свернуть]
Многие люди путают ЭЛТ, потому что они не знают, как современная работать монтажники. Код Монтаж и данные помещаются в контейнеры, здесь называют ".area" s по SDCC. Код и данные могут быть помещены в эти контейнеры из любой точки исходного кода. Ссылка должна быть рассказана, где эти контейнеры помещают в памяти. В этом ЭЛТ, существует список зон, которые просто указывает компоновщику порядок, в котором эти контейнеры должны появиться в памяти. Так как эти контейнеры не имеют ORG адреса, связанные с ними, они будут появляться один за другим в памяти.Код:.globl _main .area _HEADER (ABS) .org 0x0000 ;--code-loc 0x0006 init: ;; Set stack pointer directly above top of memory. ld sp,#0x0000 ;; Initialise global variables call gsinit call _main jp _exit ;; Ordering of segments for the linker. .area _HOME .area _CODE .area _INITIALIZER .area _GSINIT .area _GSFINAL .area _DATA .area _INITIALIZED .area _BSEG .area _BSS .area _HEAP .area _CODE _exit:: di halt .area _GSINIT gsinit:: ld bc, #l__INITIALIZER ld a, b or a, c jr Z, gsinit_next ld de, #s__INITIALIZED ld hl, #s__INITIALIZER ldir gsinit_next: .area _GSFINAL ret
Площадь _GSINIT требуется, потому что без него программу C статические данные не будут установлены по умолчанию. SDCC также разместить код здесь к нулю сегмент BSS и инициализировать кучу, если программа использует кучу.
CRT размещенные лезвие (я думаю) немного путь обратно теперь немного неправильно, потому что куча инициализируется по-разному. Если вы посмотрите в библиотеку z80 вы найдете "heap.s":
Скрытый текст
Many people are confused by the crt because they don't know how modern assemblers work. Assembly code and data are placed into containers, here called ".area"s by sdcc. Code and data can be placed into these containers from anywhere in the source code. The linker needs to be told where these containers are placed in memory. In this crt, there is a list of areas that simply tells the linker the order that those containers should appear in memory. Since these containers do not have ORG addresses associated with them, they will appear one after the other in memory.
The _GSINIT area is required because without it the C program's static data will not be initialized. SDCC will also place code here to zero the BSS segment and to initialize the heap if the program uses the heap.
The crt posted by Blade (I think) a little way back is now a little bit wrong because the heap is initialized differently. If you look into the z80 library you will find "heap.s":
[свернуть]
Здесь можно увидеть SDCC будет размещать код инициализации в _GSINIT и он будет размещать 1k кучи в области _HEAP. Лезвие имеет отдельный код, который инициализирует кучу, что больше не требуется. Это изменение произошло после выхода 3.5.5, но SDCC готовится к отпуску 3.6 в ближайшее время.Код:;; Stubs that hook the heap in .globl ___sdcc_heap_init .area _GSINIT call ___sdcc_heap_init .area _HEAP ___sdcc_heap:: ;; For now just allocate 1k of heap. .ds 1023 .area _HEAP_END ___sdcc_heap_end:: .ds 1
Скрытый текст
where you can see SDCC will place initialization code into _GSINIT and it will place 1k of heap into the _HEAP area. Blade has separate code that initializes the heap that is no longer required. This change came after the 3.5.5 release but SDCC is preparing for a 3.6 release soon.
[свернуть]
Да, вы должны отделить каждую функцию в своем собственном файле. Встроены в сборе никогда не должны быть использованы для библиотеки, кроме как быстрый метод для программиста C размещать код ассемблера в программу C. В SDCC это было сделано таким образом, потому что SDCC Бэкэнд не проста в использовании.В библиотеках сдцц и z88dk многое есть в открытом виде, можно подсмотреть или использовать то, что уже скомпилино в библиотеки.
Для библиотеки, прототип функции в заголовочном файле сообщает компилятору, как вызвать библиотечную функцию ASM. Тогда фактическая функция Библиотека написана в собственном файле АНМ. Все АНМ файлы, составляющие библиотеку затем собраны в библиотеке. В этой форме компоновщик сможет выделить только те функции, программа пользователя использует. Когда код ASM существует независимо, как это, он должен быть назначен в область так, чтобы компоновщик знал, куда его в выходной двоичный. Когда асмовый встроены в коде C, компилятор Си управляет в данный момент активную область.
Вы можете увидеть, как мы делаем это в z88dk - есть библиотека тысяч ASM функции там. Простой пример может быть string.h с его sdcc Файл заголовка и его осуществления ASM .
z88dk не использовать бэкенд SDCC в. Он использует z80asm качестве ассемблера, так что все ASM использует стандартный Zilog обозначения. Если вы используете базовую программу SDCC в необходимо использовать специальный синтаксис asz80. Кроме того, мы делаем много вещей, чтобы исправить несколько небольших проблем в SDCC и генерировать в оптимальный код, как это возможно, что не делается в SDCC, так заголовки и реализация будет немного странно.
Пример из заголовка файла:
Скрытый текст
Yes you must separate each function into its own file. Inlined assembly should never be used for a library except as a quick method for a C programmer to place asm code into a C program. In sdcc it's been done this way because the sdcc backend is not easy to use.
For a library, the function prototype in the header file tells the compiler how to call the asm library function. Then the actual library function is written in its own asm file. All the asm files making up the library are then compiled into a library. In this form the linker will be able to pick out only those functions the user program uses. When your asm code exists independently like this, it must be assigned to an area so that the linker knows where to place it in the output binary. When asm is inlined in C code, the C compiler is managing the currently active area.
You can see how we do it in z88dk -- there are a thousand asm library functions there. An easy example might be string.h with its sdcc header file and its asm implementation.
z88dk does not use sdcc's backend. It uses z80asm as assembler so all asm uses standard Zilog notation. If you are using sdcc's backend you must use the special asz80 syntax. Also, we do many things to fix several small problems in sdcc and to generate as optimal code as possible that is not done in sdcc, so the headers and implementation will be a little bit strange.
An example from the header file:
[свернуть]
Это для функции STRLEN (). #define Вы видите, чтобы исправить трудности SDCC с генерации указателя функции вызовов азЬсаИ функции. Простой прототип будет просто первая линия:Код:extern size_t strlen(char *s) __preserves_regs(d,e); extern size_t strlen_fastcall(char *s) __preserves_regs(d,e) __z88dk_fastcall; #define strlen(a) strlen_fastcall(a)
Скрытый текст
This for function strlen(). The #define you see is to fix sdcc's difficulties with generating function pointer calls to fastcall functions. A simple prototype would just be the first line:
[свернуть]
который будет использовать стандартную связь и заходит так далеко, чтобы сказать компиляции, которая регистрирует D и Е являются неизменными функцией.Код:extern size_t strlen(char *s) __preserves_regs(d,e);
Реализация ASM делится a z80 часть с чистым интерфейсом реестра и C Интерфейс . Здесь я только показывать интерфейс C для стандартной связи. АзЬсаИ связь не имеет накладных расходов. Директивы ассемблера приведены для z80asm. Для asz80 вы должны использовать ".globl" и ".area".
Мы отделить интерфейс C от z80 для нескольким причинам. Одним из них является мы хотим поддержать любую компилятор, а другой мы хотим интерфейс АНМ для ассемблерщиков без накладных расходов C. Это также влияет на саму библиотеку, потому что это программа на языке ассемблера, что вызывает функции, определенные в себе. Программа на самом деле сделал меньше, обеспечивая использовать библиотеку по собственным кодом не приносит в накладных C.
Существует немного кривой обучения, но как только вы его, это все довольно легко.
Скрытый текст
which will use standard linkage and goes so far as to tell the compile that registers D and E are unchanged by the function.
The asm implementation is divided into a z80 part with pure register interface and a C interface. Here I am only showing the C interface for standard linkage. The fastcall linkage has no overhead. The assembler directives shown are for z80asm. For asz80 you would use ".globl" and ".area".
We separate the C interface from the z80 for a couple of reasons. One is we want to support any C compiler and the other is we want an asm interface for assembly language programmers without C overhead. This also affects the library itself because it is an assembly language program that calls functions defined in itself. The program is actually made smaller by ensuring the library's use of its own code does not bring in the C overhead.
There is a little bit of learning curve but once you have it, it's all fairly easy.
[свернуть]


Ответить с цитированием
