Offer for alasm coders alasm

ZXNet echo conference «code.zx»

From Alexander Bondarenko To All 22 April 2004

*** Also sent to CODE.ZX (For those who know how to code...) *** Also sent to ZXNET.SOFT (Softina...) *** Also posted in EKB.PROGRAMMING (Online programming.) Hello, All! To build the capacity of a "smart" library of procedures under I need help from coders. Need ideas, suggestions, etc. I provide a brief description of the library for those who are interested. ================================================================================== LIB+ The LIB+ library (currently in development) is a collection of all sorts of useful procedures and subroutines, so far there are only about 30 of them. She designed for assembler alasm - as the only one in real life, on currently an assembler that supports conditional translation. The general organization of the library is such that the programmer cannot you need to monitor it in no way, except how to determine one service variable (and only if it is needed). For To “call” the library you just need to enter at the end of the program: INCLUDE "LIB+" In this case, it will automatically be determined which procedures need to compile and which ones don't. The program itself has enough explicitly indicate the procedure label somewhere so that it can be used later linked: CALL Procedure or LD BC,Procedure LIB+ file - the main module of the library, defines the statelabel and in case it is used but not defined, makes an INCLUDE of the auxiliary file, which contains procedure. Library auxiliary files contain procedures a certain topic. Total currently exists the following set of these files: SCREEN_P - procedures for working with screen addresses WINFX_R - procedures for various effects with windows on the screen. PR_R - three printing procedures, respectively on 42, 51 and 64 characters per line. Option - for character by character prints, fast. But for text leaflets Another option is preferable - lowercase. MEM128_P - procedures for working with upper memory pages (currently - only for 128k) WINMAN_P - window manager, allows you to specify such and such a window as the current one, or “clear” the parameters of the current window PRNMAN_R - print procedure manager, allows you to set print procedure as current, print from it to current window and immediately switch to others printing procedures. Automatically pairs with WINMAN_R. INPUT_P - keyboard polling procedures (via 48th ROM) These files can be called in a program separately from LIB+, which will allow you to compile sets specific to the topic procedures to a specific place in the code. You can refuse altogetherLIB+, but then you will have to monitor the compilation process yourself. Letter R or P at the end of the auxiliary file name means whether it can exist independently, without the need for other supporting files. If the name ends with _P, which means it can. Library hierarchy: +----->WINMAN_P | | PRNMAN_R-----+ WINFX_R------>SCREEN_P | ^ | | +----------->PR_R------------+--->FONT42, FONT51, FONT64 MEM128_P INPUT_P When using LIB+, you can specify the page after INCLUDE, where the entire set will be loaded during compilation. There is also the ability to load LIB+ in one place, and auxiliary files - to another. This is set by the _LPG1 variable. If she defined, then all auxiliary files will be loaded into page whose number is contained in _LPG1. This is made for partial acceleration of the compilation process. Individual procedures may be modified depending on whether any other procedures are used, more or less related to these. For example, the SET_WIN procedure (task current window), when using the PRNMAN__R module, there will be, in addition setting the screen window itself, recalculating and forcurrent printing procedure. If the PRNMAN_R module is not is used, then in SET_WIN there will not even be a hint of code, involved in this recalculation. Or - all special effects procedures with a window, when using WINMAN_R, are endowed with a second point input (CW_ + name of the special effect procedure) - for working with current window (does not require explicitly setting window parameters). But this "endowment" occurs again if it is somewhere was called. The library allows you to organize the source code of the program more culturally and in some places even “thinks” a little for the programmer. Here is a list of library procedures: SCREEN_P - working with screen addresses SCRADR - calculation of the address on the screen using familiar coordinates in DE (YX) and placing it in HL ATRADR - the same, but for the address in the attributes SCPXADR - the same, but for the address on the screen and by pixel coordinates SCR2ATR - convert screen address to HL for the corresponding attribute. DNHL - recalculation of the screen address in HL by the line below UPHL - the same, but the line is higher DN8HL - the same, but 8 lines lower UP8HL - the same, but 8 lines higher PR_R - printing procedures This module requires 3 font files for procedures - FONT42, FONT51 and FONT64. If labels of the same name are already defined, then the font will not be loaded, which also allows link fonts manually to a specific place in the program.PR42, PR51, PR64 - symbol printing procedures. Printable symbol - in A. GTXY42, GTXY51, GTXY64 - positioning procedures "carriages". DE - print coordinates in matrices. PRLIN42, PRLIN51, PRLIN64 - print one line of a character. A- symbol, DE - print coordinates in matrices, B - line number in familiarity, H is the address of the symbol line. Auxiliary procedures. WINFX_R - a set of special effects. For these procedures, the window coordinates are specified in DE (YX), window dimensions - in BC (height/length). Everything according to acquaintances. CLRSWN (window version - CW_CLRSWN) - clear screen window area FILAWN (CW_FILAWN) - fill the attribute area with a byte windows RMKWIN (CW_RMKWIN) - draw a frame around the window. Frame - rectangular line 1 pixel thick, filled with 0 - around windows (work is carried out on the area bordering the window, so a window should always have this area around it if it is adjacent to the screen border, there will be glitches), and the same line - along the bottom and right border of the window rectangle, filled with 1. SLC_WIN_UP (CW_SLC_WIN_UP) - scrolling the window up by familiar place, with attributes. SLP_WIN_UP (CW_SLP_WIN_UP) - scrolling the window up by a pixel SLP_WIN_DN (CW_SLP_WIN_DN) - scrolling the window down by pixel MEM128_P - procedures for working with upper memory pages. SET_PG - set current page to A PUSH_PG - store the current page number on the stackPOP_PG - restore page number from stack and set her WINMAN_P - small window manager SET_WIN - set the current window (DE - YX, BC - height/length). If the window extends somewhere beyond the screen, then it will adjusted to its size. GET_WIN_INFO - get the parameters of the current window. PRNMAN_R SET_CUR_PR - set the current printing procedure (address - in HL) PR_WIN - print the character (A) in the window PR_STR_WIN - print a string (address in HL, ends with 0 or 13) GTXY_WIN - positioning the carriage inside the window INPUT_P - keyboard polling via 48th ROM INKEY48 - number of the pressed key in A ================================================================================== In general, what exists at the moment is by no means helicopter, there is still plenty of work to be done on the library. I hope for the support of the people. Best regards, Alexander.

From Kirill Frolov To Alexander Bondarenko 5 May 2004

Press RESET immediately, Alexander Bondarenko! On Thu, 22 Apr 04 13:58:20 +0400, Alexander Bondarenko wrote: AB> To build the capacity of the "smart" library of procedures under AB> I need help from coders. Need ideas, suggestions, etc. AB> Here is a brief description of the library for those who are interested. AB> ================================================================================ AB> LIB+ AB> LIB+ library (currently in state AB> developments) is a collection of all sorts of useful AB> procedures and subroutines, so far there are only about 30 of them. She I somehow have similar thoughts, but nothing moves. At the moment there are: 1) integer mathematics. 2) ASCIIZ strings. 3) text console (alas, not compatible with either ANSI or VT100). 4) absolutely minimum for the output in step 3. 5) the beginnings of dynamically loaded modules (DLL) Planned: 6) mathematics with floating point (the code actually already exists) 7) memory manager 8) "Pascal" strings, associative arrays and others data structures (need point 7) 9) file system...10) object implementation of everything else... (instead of point 5.) 11) creation of a simple interpreted language based on 10 clause 7. puzzling... There is a debugged C analogue, it needs to be transferred to Z80 assembler. AB> is designed for alasm assembler - as the only one in real life, on AB> currently an assembler that supports conditional translation. Alas, the glitches there are through the roof. And most importantly, a number of such stupid restrictions that they simply do not allow them to be used (64 characters per line, write only in capital letters - even though I can’t cut it...) I'm counting on ZAS (C) Hitech Software for PC, C preprocessor, and I have SED scripts for converting sources to ZASM or ALASM. Since in "converter" gets pre-processed text, special requirements for the assembler in terms of conditional compilation and all that already not presented. On the other hand, the Spectrum version of the code It turns out that it is only suitable for compilation, it cannot be edited. Well, not everything there is transferred “head-on” either... AB> The general organization of the library is such that it is not possible for the programmer AB> you need to monitor it in any way, except how to determine it AB> one service variable (and only if it is needed). For AB> "calling" the library just needs to be entered at the end of the program: AB> INCLUDE "LIB+" Yes, in Spectrum (as opposed to pisishnoy, for ZAS, although it in CP/M and on Spectrum you can...) versions I do the same. Otherwise no way. But there are also inconveniences: you need to recompile everything at once, symbols from different modules get mixed up. Actually, this is the reason for the bias towards the DLL - actually the only point of contact library and program, its interface remains, but what’s inside already It doesn't matter at all. AB> In this case, it will be automatically determined which procedures AB> should be compiled and which ones should not. The program itself has enough Alas. Fuck it! If there are any fairly complex dependencies, this is bound to cause problems. Like A depends on B and B depends on C. You include A. You include C in the text before inclusions A. It will be a bummer. You have to include one source by N just write (in ZXASM notation) these horrors: IFNDEF blablabla IFUSED blablabla blablabla: function code ENDIF ENDIF Well, often if one function lasts, then the entire module is needed. Lots of inconvenience... AB> SCRADR - calculation of the address on the screen using familiar coordinates AB> in DE (YX) and placing it in HL AB> ATRADR - the same, but for the address in the attributes AB> SCPXADR - the same, but for the address on the screen and by pixel AB> coordinates AB> SCR2ATR - converting screen address to HL for AB> corresponding attribute. AB> DNHL - recalculation of the screen address in HL by the line below AB> UPHL - the same, but with a line higher AB> DN8HL - the same, but 8 lines lower AB> UP8HL - the same, but 8 lines higher This should be done exclusively with macros! Only 28 per CALL There are the same number of clock cycles for juggling registers. What will remain? AB> In general, what exists at the moment is by no means AB> helicopter, there is still plenty of work on the library. AB> I hope for the support of the people. I think the library is useless. Its /Spectrum/ assembler impossible to assemble (in writing this is a standard feature). Yes and the possibilities are very limited. I already talked about the advantages of DLL I described it, but there are plenty of problems there too. You need Spectrum COM! (with an eye on Microsoft). But how can this be realized without thoseI don’t even know the crutches that Microsoft came up with. As long as there is a system modules, but it is already clear that it is missing many things, although he himself principle, in general this is the technical side of the issue, the principle itself combining the code of two programs through a predefined interface it is the same everywhere (see the next letter). A short list (a detailed list does not fit in SPBZXNET’s letter) of my "libraries": [[[ note: in general, many functions in terms of arguments and their purpose compatible with the standard C library. So if it's not clear what a specific function does, I advise you to look at man, or what do you have there... ]]] exit_48 exit_128 exit_trdos exit_run call_magic ; Simulates pressing the Magic button. setim2vec ; Setting the interrupt vector for IM2 mode. im2_enter ; The function stores the contents of all registers on the stack... im2_leave ; The function restores the contents of all registers... setjmp ; The function saves the program context for return... longjmp ; The function returns to the point where setjmp... was called. case ; The case function navigates through the table depending... findfile ; The function searches for a file on the current disk whose name is specified... findfirst ; The function searches on the current disk for the first file specified by the mask... findnext ; The function searches the disk for the next file after... fcbtoname ; The function transfers the file name from the FCB specified by the register...nametofcb ; Функция переносит имя файла из строки заданной регистром... isalnum ; A=char -> A=char, Z=1 if A is digit or letter isalpha ; A=char -> A=char, Z=1 if A is letter isascii ; A=char -> A=char, Z=1 if A is ascii char. isblank ; A=char -> A=char, Z=1 if A is space or tab. isdigit ; A=char -> A=char, Z=1 if A is digit islower ; A=char -> A=char, Z=1 if A is lowercase letter isprint ; A=char -> A=char, Z=1 if A is printable ispunct ; A=char -> A=char, Z=1 if A is puntuation char. isspace ; A=char -> A=char, Z=1 if A is space isupper ; A=char -> A=char, Z=1 if A is uppercase letter isxdigit ; A=char -> A=char, Z=1 if A is hexadermal digit memcmp ; memcmp(DE=*src, HL=*src, BC=size) memmove ; memmove(DE=*dst, HL=*src, BC=size) strglob ; HL=*string, DE=*mask -> Z=1 if found strstr ; HL=*string, DE=*search -> Z=1 & HL=*ptr strlcpy ; strlcpy(DE=*dst, HL=*src, BC=maxsize) -> HL=*0(dst) strlcat ; strlcat(DE=*dst, HL=*src, BC=dstsize) -> HL=*0(dst) strcat ; strcpy(DE=*dst, HL=*src) -> HL=*0(dst) strcpy ; strcpy(DE=*dst, HL=*src) -> HL=*0(dst) strncpy ; strncpy(DE=*dst, HL=*src, BC=maxsize) -> HL=*0(dst) strncat ; strncat(DE=*dst, HL=*src, BC=size) -> HL=*0(dst) strlen ; HL=*string -> HL=BC=length (without term. 0) strchr ; strchr(HL=*str, A=char) -> Z=1 & HL=*char strcmp ; strcmp(DE=*str1, HL=*str2) -> ZF, CF, SFstrncmp ; strncmp(DE=*str1, HL=*str2, BC=size) -> ZF,CF,SF strcmpi ; strcmpi(DE=*str1, HL=*str2) -> ZF,CF,NF strncmpi ; strncmpi(DE=*str1, HL=*str2, BC=size) -> flags strreverse ; reverse string, HL=*string strlower ; convert to lowercase HL=*string strupper ; convert string to uppercase HL=*string strcspn ; HL=*string, DE=*separators -> BC=HL=count strpbrk ; HL=*string, DE=*separators -> Z=1 & HL=*char strrchr ; HL=*string, A=char -> Z=1 & HL=*char strrpbrk ; HL=*string, DE=*separators -> Z=1 & HL=*char strrspnp ; HL=*string, DE=*separators -> Z=1 & HL=*char strsep ; HL=*string, DE=*separators -> Z=1 & HL=*token & DE=*next strspn ; HL=*string, DE=*separators -> BC=HL=count strspnp ; HL=*string, DE=*separators -> Z=1 & HL=*char swab ; swap byte pairs HL=*src, DE=*dst, BC=size tolower ; A=char -> A=lower case char toupper ; A=char -> A=upper case char atow ; HL=*str -> HL=number, DE=*last_char+1 || error CF=1, HL=*err_pos htoa ; hex2ascii A=0..0ffh, HL=str[3] -> HL=*0(str) wtoa ; decimal2ascii HL=string[6], DE=number -> HL=*0(string) ltoa ; long2ascii (DE,BC) HL=string[11] -> HL=*0 amul ; hl = hl + a*de ~338 takts. crc16 ; ix=*data, bc=size, de=polynom, hl=crc -> hl=crc crc16_init ; de=*(512bytes), bc=polynom crc16_fast ; ix=*data, bc=size, de=tab*512, hl=crc -> hl=crc div ; hl = de/bc de = de%bc ~840 takts. flatcher ; ix=data, bc=size -> hl=code i2bcd ; bin(HL) -> bcd(E,H,L) l2bcd ; long_bin(DE,HL) -> bcd(C,D,E,H,L) labs ; long (HL

From Kirill Frolov To Alexander Bondarenko 5 May 2004

Press RESET immediately, Alexander Bondarenko! On Thu, 22 Apr 04 13:58:20 +0400, Alexander Bondarenko wrote: So about the modules: Introduction There is a lot of system-independent code that can be written without modifications, or with minimal effort, used as in TR-DOS programs, both in Aqua-OS and in other D2k and X-DOS, BeeOS... pseudo-operating systems for ZX-Spectrum. Of course, you can always pick up the source texts, but they may be are not available, this may require a certain version of assembler, incompatible with the one used (such as ZASM and ALASM), finally dynamic becomes unavailable (at the time of program execution) uploading code, nor sharing it among several programs. What happens is that programs increase in size, with the fact that they contain almost the same code. And their support, in case when parts of code from different people are used, it becomes simple impossible - for example, if one author released a new version device driver, then how will it force another author to use it in your program, instead of the old version, if the latter does not want engage in any modernization of your program? So there is a real one an example of how to integrate the NEMO-IDE driver into the CD-Walk program it took about 2 years, approximately.What this means is that libraries are needed. Dynamically Loadable, that is, loaded during program execution. Something like *.dll in a Windows environment or *.so in Unix, only simpler, with adjusted for Spectrum specifics and limited resources. For example, now in many programs for the Spectrum (for 2000-2003 year) the so-called memory driver is used, the real clock time ("CMOS"), disk drive driver... On every computer practically the same “driver” with different modifications is built in into each program, or is loaded when the program starts. B in the latter case, almost all programs use an incompatible driver among themselves, despite the fact that all drivers have approximately the same functionality. So why not finally get to dynamic loading of code and a unified method (format) of presentation this code? In the opinion of the author, the requirements for the library are, first of all, extremely easy to download. So that three hundred bytes of code are not required to download a whole OS like Windows-XP(TM) was needed. This is extremely important for library support in the TR-DOS environment and for adapting old programs. The second point is compatibility: there should be enough traditional for Spectrum tools such as ALASM or ZASM, both for creating andand to load the library. However, there is still something to think about... For the IDE controller driver in the CD-Hack program, the author used some kind of dynamically loaded *.dll library in Windows, which allowed: 1. Completely separate programs using the *.dll file and the library - now both the library and the program can develop separately from each other (that is, releasing a new version of the driver does not you have to think about updating the program, and vice versa). 2. Get the ability to dynamically (roughly speaking, they are possible on change) loading any of the available modules of a certain class (in this case, IDE driver). 3. Get the ability to download several different ones at the same time instances of modules of the same class (it is possible to load all at once drivers and use them simultaneously on a machine with several IDE controllers). 4. The same module can be freely used in different programs, which greatly simplifies its maintenance and saves space on disk. A list of advantages over statically inline code can be found continue for a long time... There are also disadvantages. This is still some complication of the program, increasing its volume (for example, due to module loader) and ineffective, from the point of view of optimalcoding, library and program interface. For IDE drivers the author had to invent a simple executable file format libraries that would allow: 1. Specify a list of imported modules and functions, a list exported functions. 2. Loading by absolute and relative (movable module) address. 3. Specify information about the module, such as its class, name and version (it was assumed that there would be a single hierarchical class system so that any program can define purpose of the module). It seems that the described version of *.dll files is not the last, and for now there is opportunity for significant change. For programmers and other "coders" I would suggest in more detail discuss this topic and approve a single format dynamically loadable modules. I wanted to have a more specific list of requirements to the module, and implementation options. My version can be seen at example of IDE drivers... Dynamically loaded module file structure The downloadable module consists of the following parts: * Header containing information necessary for loading the module. * Program code (text) and data. * Information necessary to configure the module to the execution address. Only the title is required. Other parts mayabsent. So, for example, in a module that assumes loading by The absolute address does not need any adjustment to the execution address at all. Module title In the current version, the header is a static record consisting of The 11 fields indicated in the table below, as well as several records of variable length: module name and class, lists of imported and exported functions, strings of text description of the module, and code initialization functions. Static header part The “name” column shows the designation of certain language marks assembler, which serves to access individual fields of the module header. B The "offset from beginning" column indicates the field offset, in bytes, from the beginning of the file or relative to the module's load address in memory. In the column "data type" denotes the data type of the field in C language notation. The types int, unsigned and void* are assumed to be limited to 16 discharges. Table 1. Module header fields +----------------------------------------------------------+ | | offset from | | | | name | began, in | data type | description | | | bytes | | | |--------------+------------+------------+----------------------------|| | | | File label (signature) | | | | | allowing you to distinguish the file | | mod_magic | 0 | char[4] | modules from other types | | | | | files. Any module | | | | | starts with 4 characters in | | | | | ASCII code: <>. | |--------------+------------+------------+----------------------------| | | | | Current header version | | | | | module and bootloader. Module | | | | | can only be downloaded | | | | | in case version | | | | | module and bootloader | | | | | his program used | | | | | match. Version number | | mod_modver | 4 | unsigned | defined by unsigned | | | | | 16-bit number. Version | | | | | consists of both senior and junior || | | | parts, senior 8 categories | | | | | number defining number | | | | | versions determine the major one | | | | | part of the version number, minor | | | | | 8 digits - the lowest part. | |--------------+------------+------------+----------------------------| | | | | Module properties bit field. | | mod_flags | 6 | unsigned | Currently defined | | | | | just one practically no | | | | | flag used. | |--------------+------------+------------+----------------------------| | | | | Module loading address. All | | | | | remaining header fields | | | | | containing addresses will be | | | | | valid only if | | | | | the module will be loaded by | | mod_load | 8 | void * | this address, or if || | | | addresses will be special | | | | | adjusted in a way (for | | | | | this is what the third serves | | | | | component of the module - | | | | | information for setting up | | | | | download address). | |--------------+------------+------------+----------------------------| | | | | Function pointer | | | | | initialization. Given | | mod_start | 10 | void | function must be called | | | | (*init)() | after loading the module and | | | | | setting it to address | | | | | downloads. | |--------------+------------+------------+----------------------------| | | | | At this address | | | | | information for | | mod_end | 12 | void * | module settings to address || | | | downloads, and after setup | | | | | memory can be | | | | | released. | |--------------+------------+------------+----------------------------| | | | | Pointer to list | | mod_export | 14 | void * | exported by the module | | | | | functions. | |--------------+------------+------------+----------------------------| | | | | Pointer to list | | mod_import | 16 | void * | imported libraries and | | | | | functions. | |--------------+------------+------------+----------------------------| | | | | Pointer to text | | mod_name | 18 | char * | class and name string | | | | | module. | |--------------+------------+------------+----------------------------| | | | | Binary version number || | | | module. Module version | | | | | consists of the lowest (low) and | | | | | senior (high) part, and | | mod_version | 20 | unsigned | calculated by the formula: | | | | | version = high*256+low. | | | | | Modules with the same major | | | | | part of the version number | | | | | are considered compatible. | |--------------+------------+------------+----------------------------| | mod_text | 22 | char * | Pointer to string | | | | | text description of the module. | +----------------------------------------------------------+ All module header fields that have a pointer type, except the mod_load field, contain valid values only after loading and configuration module to the download address. Before setting the module to the download address, these fields contain values valid if the module were loaded by the address specified in the mod_load field. Module header version The mod_modver field, a static part of the module header, containsan unsigned 16-bit number specifying the header version number and module loader compatible with it. The bootloader can download module only if its version number exactly matches with the module version number. The current module header version is 0x0101 (decimal 257). There is a certain assembly language mark whose meaning is installed according to the current version of the module loader: MODULE_HEADER_VER equ 0x0101 The version number is divided into major and minor parts, which, when Records are usually separated by a dot. High part of the module version number is determined by the most significant 8 digits of the version number, and the least significant part - lower 8 digits. So the current version is module header 0x0101 (decimal 257) can be written as "1.1", where the one to the left of the dot determines the high part of the number versions. Module properties As stated above, the mod_flags bit field contains information about certain properties of the module. Each property is defined by one set or cleared bit. There are language tags assembler that defines the bitmask of each property bit. On At the moment, one single property is defined: MOD_ABSOLUTE equ 1 This property means when a module has it (the correspondingthe least significant bit of the properties bit field is set) that the module can only be loaded at an absolute address defined by the contents of the mod_load field. Variable Length Records Module name and class Each module must have its own unique name and is associated with the corresponding class of modules. This allows, on the one hand, distinguish between different modules, and on the other hand, determine modules with the same software interface. At the moment, everything this information is encoded into a single text string as a set of classes and module names separated by '/'. So, for example, the driver module The IDE interface for the SMUC controller has the name: "trdos/ide/smuc". The substring after the last character '/' is the name of the module, that's all the rest is class. List of exported functions The list of export functions consists of a number indicating the quantity exported functions, as well as an array of pointers to exported Features: Table 2. List of exported functions +----------------------------------------------------------+ | offset from | data type | description | | start, in bytes | | | |------------------+------------+---------------------------------------|| | | Maximum number exported | | | | functions. Numbering starts from zero, | | 0 | int | like this when exporting just one function | | | | this field will contain 0. The module is not | | | | can export less than one | | | | functions. | |------------------+------------+---------------------------------------| | | | Pointer to the exported function, | | | | in other words, the memory address, by | | | | which this | | | | function. The pointer is | | 2+2*N | void (*f)() | valid only after setting | | | | module to the download address. If | | | | the contents of this field are 0, which means | | | | this function number is free and not | | | | exports no function. | +----------------------------------------------------------+ Import listThe import list is an array of records, each of which represents the name of the imported module and a list (by number) of functions required in this module (in reality this is a transition table, see next message) Text description string ASCIIZ string, no more than 255 characters... Doesn't make much sense. Module initialization function Called once after loading the module... Relocation table Can be cut off from the module after it has been loaded and configured to work address. Consists of an entry indicating the total number of configurable addresses and a list of these addresses relative to the download address specified in the mod_load field (see above). After configuring the module, all addresses in the header will be directly (i.e. will contain absolute addresses) point to the records corresponding to them. Customization for everyone addresses, assumes that the configured address is necessarily a word (16 bit) and the setting is performed according to the formula (in C language notation): (uint16_t *)A[0] - mod_load + real_load_address Well, that's all for now. The rest is not written, but it gives an idea, probably...

From Kirill Frolov To Alexander Bondarenko 5 May 2004

Press RESET immediately, Alexander Bondarenko! On Thu, 22 Apr 04 13:58:20 +0400, Alexander Bondarenko wrote: So I continue about modules. In the previous letter there was a description, It may not be entirely clear from it how it all works. I'll try explain. So there is 1) a program, 2) a module. Separate from each other. The module contains functions called by the program. FUNCTIONS ONLY. If the address of a variable is required, you will have to define a function, returning this address upon request. But the entire interface consists EXCLUSIVELY FROM FUNCTIONS. So that the program can be compiled successfully (even in ZXASM), and somehow all this could be combined, instead of those functions that are in module, the following are substituted into the program at the compilation stage: "stubs": function1: JP function1_no function2: JP function2_no ... Here "function1_no" is the function number in the module. ALL FUNCTIONS IDENTIFIED BY NUMBERS. And "function1" is the actual name functions. Such a “stub” is included as a library, of course In addition, the module loader is turned on... Actually, this is what it looks like stub, this is an element of the module import table (see previous. message). It's all about the bootloader: after loading the module, all numbers functions are replaced by their addresses! In total we have only 10 cycles "overhead" for each function call. Well, there are still many possibilitiesopen, like switching cans on the go, or “transparent” call traces... Now regarding the OOP region. This is made a little more complicated, when it comes to virtual functions. Multiple inheritance impossible, but I don’t even know where to apply it... The gist is this: if the function is non-virtual, then it is called that way (yes, I’m talking about assembler I’m still saying!), but for convenience, it is given a name: classname_functionname. Simply a reference to the object is passed to HL. Nothing new... If the function virtual, then again a “plug” similar to the one given above is used: virtual_function1: ld a, virtual_function1_num * 3 jp call_virtual virtual_function2: ld a, virtual_function2_num * 3 jp call_virtual ... Similarly, here virtual_function1 is the name of the function, and the file with such definitions is included as a library. And virtual_function1_num is function number, not in the module, but in the class. Everyone in every class virtual functions are numbered. When a class is inherited, the number is only increases and you can add new virtual functions, nothing it is no longer possible to exclude, replace, or change numbers (therefore multiple inheritance is not possible, as in C++). The number is multiplied by 3 for ease of calculation, and the most interesting thing next is the function call_virtual. It is used to call virtual functions by number, here is its text:call_virtual: push hl push af ld a, (hl) inc hl ld h, (hl) ld l, a pop af add a,l ld l, a subl ld h, a ex (sp), hl ret At the input, a pointer to an object is passed in the HL register (as when calling any functions of the class), and in register A - the number of the virtual function. The remaining registers and stack can be used to transfer function arguments. And here it is necessary to say the most important thing - every an instance of a class that has virtual functions must have a certain structure, namely a table of addresses of virtual functions. It is believed that the class has a virtual function, the first word (two bytes) uses a pointer to a table of virtual functions. This necessarily. And the virtual function table itself represents something like this (hence, by the way, the number is multiplied by 3): class_vtbl: jp vfunction1 jp vfunction2 ... Here vfunction1 is already the absolute address of the function. This table it is common for the entire class, but may differ for inherited classes (only in the larger direction, see above). Thus, really, "overhead" From memory it turns out 2 bytes per object and table per class. And by beats it turns out to be as much as a hundred cycles. But how quickly and noticeable inconvenience I don't know. Well, the object itself, from the assembler point of view, looks like this: org 0 ; this is so that it is convenient to calculate the offsets,; class definitions are included before ; all other code (as opposed to ; libraries) class_pvtbl dw class_vtbl ; pointer to virtual function table class_blablala db 0 class_bablablabla dw 0 ; data... class_sizeofequ$; class instance size Instead of "class" you should substitute the name of the class. To create a new one instance, you just need to allocate memory and call the constructor (or delegate memory allocation to the constructor... if it knows how to do it) -- the constructor cannot be virtual in any case. Destructor maybe. The constructor must fill in the fields of the structure... The class is inherited simply: org 0 class2_blablabla dw 0 ; data... class2_sizeofequ $ Well, here it’s somehow inconvenient with the assembler, it’s not thought out, there is something else to think about... So this is what I mean: I would like to unite the object paradigm (I just showed how it is implemented in Z80 assembler) and the system modules. And besides, endow them (the system of modules) with properties COM-specific: unambiguous identification of compatible interfaces (although I don't like it with UUID...), selecting one specific interface of several provided by the module, representing the interface as class, with the expectation that there may be several independentits instances (in the example with CD-Hack - two controllers at the same time) etc... Well, of course you need some kind of directory of these modules, so what? I've made Microsoft and I don't like it at all anymore. Maybe my idea with In terms of names/classes, it's not that bad. I don't even know. Then I would like to be able to have an interface with named functions to be called from a scripting language. Because by numbers if necessary all these classes have definitions. Uncomfortable...

From Alexander Bondarenko To Kirill Frolov 9 May 2004

*Hello, Kirill!* Catch my ideas about the subject "Re: Suggestion for coders on alasm", about which your footcloth to comrade was chattering on May 05, 2004. Alexander Bondarenko. AB>> LIB+ library (currently in state AB>> developments) is a collection of all sorts of useful AB>> procedures and subroutines, so far there are only about 30 of them. She KF> I have similar thoughts, but nothing moves. KF> Currently there are: KF> 1) integer mathematics. [cut] KF> 11) creation of a simple interpreted language based on 10 In principle, I also lead to the fact that we should have something like this. KF> clause 7. puzzling... There is a debugged C analogue, it is necessary KF> transfer to Z80 assembler. Can you tell me more about this manager? AB>> is designed for alasm assembler - as the only one in real life, on AB>> currently an assembler that supports conditional translation. KF> Alas, the glitches there are through the roof. And most importantly, a number of these KF> stupid restrictions that simply don’t allow them to use (64 KF> character in a line, write only in capital letters - at least don’t cut KF> I can...) Well, that's understandable. In the alasma of logs there is tyeva hycha. But unfortunately he (of all existing in real life) - the most advanced and popular. So for now I'm on it I'm still doing it. If only because you shouldn’t forget about real people either. KF> I'm counting on ZAS (C) Hitech Software for PC, sish KF> preprocessor, and I have SED scripts for converting sources to ZASM KF> or ALASM. Everything is fine, but in order to see after compilation what you got there, you need write files to trdshniki, launch emul, launch from it already compiled program. And if suddenly some glitch arose, but the program is healthy... In alasma it’s just You launch STS, which also shows labels instead of addresses. What to do here? Hy You can launch STS too, but there will be no markers. KF> Since pre-processed text gets into the "converter", KF> special requirements for the assembler in terms of conditional compilation and everything KF> this is no longer presented. On the other hand, "Spectrum" KF> the version of the code is suitable only for compilation, it KF> cannot be edited. Well, not everything there is transferred “head-on” either... Still tempting. :) AB>> The general organization of the library is such that it is not possible for the programmer AB>> you need to monitor it in any way, except how to determine it AB>> one service variable (and only if it is needed). For AB>> “calling” the library just needs to be entered at the end of the program: AB>> INCLUDE "LIB+" KF> Yes, in Spectrum (as opposed to writing, for ZAS, although it KF> in CP/M and on the Spectrum you can...) versions I do the same. Otherwise KF> nothing. But there are also inconveniences here: you need to recompile everything at once KF> symbols from different modules get mixed up. Actually, this is the reason for the bias KF> towards the DLL - actually the only point of contact KF> of the library and program, its interface remains, but what’s already inside KF> not important at all. AB>> In this case, it will be automatically determined which proceduresAB>> need to be compiled and which ones should not. The program itself has enough KF> Alas. Fuck it! If there are any fairly complex dependencies, KF> this is bound to cause problems. Like A depends on B KF> and B depends on C. You include A. You include C in the text before KF> inclusions A. It will be a bummer. You have to include one source by N KF> just write (in ZXASM notation) these horrors: KF> IFNDEF blablabla KF> IFUSED blablabla KF> blablabla: KF> function code KF> ENDIF KF> ENDIF Yes, there is such nonsense there... :) And in Alaska this is organized simply: IF (?blablalbla-1) blablabla function code ENDIF "?blablabla" gives 1 if blablabla above was accessed somewhere, but This label has not yet been defined. If we define it, then ?blablabla will give 0. Hy and if blablabla was not called or defined, then ?blablabla will give #ffff. Not a standard syntax, but it works. :) And about the fact that one thing depends on the other. First, a simple development option events. My procedures are divided into files not only by topic, but also byin terms of levels of dependence. And the library control file (which includes these auxiliary files) is included at the very end of the program, when it is known what needs to be turned on. First level (generally independent procedures) They are compiled as a last resort. And first of all, those are compiled procedures (read - subprograms), which have the highest level of dependence tall. Therefore, if it turns out that blablabla calls ogogo, then after compilation blablabla the value ?ogogo will be equal to 1. And if this ogogo is called separately from blablabla, then everything will be fine too. It's all the same until the mark defined, but used, the compiler remembers the places where it is addressed. A then, at the end of the compilation, it arranges the value of this label accordingly. places, if she has decided by this moment. Well, a difficult option (just yours) - then it should also fail here. C because y us will already be defined, so when compiling B into a call there are no problems address C will be substituted. KF> Well, often if one function is needed, then the entire module is needed. KF> A lot of inconvenience... It depends on the internal structure of this module... You can also place there the procedures are in order of "dependency". AB>> SCRADR - calculation of the address on the screen using familiar coordinates [cut] AB>> UP8HL - the same, but 8 lines higher KF> This should be done exclusively with macros! For one CALL only KF> 28 cycles, the same amount of register juggling. What will remain? This is understandable. I haven’t implemented the macro part of the library yet, but just in case The case included these cases in the form of procedures. AB>> In general, what exists at the moment is by no means AB>> helicopter, there is still plenty of work on the library. AB>> I hope for the support of the people. KF> I think the library is useless. No, for those who code purely in alasma, it can be useful. At least at least, besides me, who wants it :), there are a dozen more personalities (were in our talking time). KF> It is impossible to assemble it with the /Spectrum/ assembler (in written form KF> standard feature). And the possibilities are very limited. About KF> I have already described the advantages of DLL, but there are also problems there KF> is enough. You need Spectrum COM! (with an eye on Microsoft). Accordingly, an axis is needed. KF> But how can this be implemented without the crutches that I came up with KF> I don’t even know the microsoftware. As long as there is a system KF> modules, but it is already clear that it lacks many things, although itself KF> principle, in general this is the technical side of the issue, the principle itself KF> combining the code of two programs through a predefined interface KF> it is the same everywhere (see the next letter). KF> A short list (a detailed list does not fit in SPBZXNET's letter) of mine KF> "libraries": Can I get a detailed list for e-soap? [further cut] Thank you, I will keep all these benefits in mind. /That’s all, Kirill, you can scroll further.../ pese: Of course, I understand everything about ZAS’s coolness. I'm crazy myself. Yes, if only everything coders climbed onto it overnight, most likely, the effect of this would be more than positive. But for now, the majority of people are sitting behind the alyasm. Even some emulators.

From Alexander Bondarenko To Kirill Frolov 10 May 2004

*Hello, Kirill!* Catch my ideas about the subject "Re: Suggestion for coders on alasm", about which your footcloth to comrade was chattering on May 05, 2004. Alexander Bondarenko. Damn, you still come to the conclusion: it’s easy to complicate, it’s difficult to simplify. ;))))))))) /That’s all, Kirill, you can scroll further.../