Enterprise Forever
:UK => Programming => BASIC => Topic started by: gflorez on 2014.August.14. 01:06:14
-
I'm interested in relocatable code, programs that can work independently of the configuration of the EP.
The problem is when you want to make it easily in Basic. RESTORE or ALLOCATE can give you spare memory for your code, but the direction can be different if you have been running another program before or have made immediately a reset.
But if you want the code to work on every EP you must think about relocatable modules.
No, I talk about tiny code with some jumps or calls inside. The Z80 wasn't engineered with relocatable code in mind( except the useful JP(HL) widely used in the EXOS, or the relative jumps, too shorts to be useful).
Then I've though about an easy way to do the trick:
100 ALLOCATE 20
110 CODE ORIGEN=HEX$("00,00,00,01,00,02,00,03,00,04,00,05,00,06,00,07,00,08,00,09")
120 LET CODH=INT(ORIGEN/255)
130 LET CODL=REM(ORIGEN,255)
140 FOR A=0 TO 9
150 READ B,C
160 LET DIREC=(B*255)+C+ORIGEN
170 LET H=PEEK(DIREC)
180 LET L=PEEK(DIREC+1)
190 LET L=L+CODL
200 LET H=H+CODH+INT(L/255)
210 LET L=REM(L,255)
215 PRINT DIREC,PEEK(DIREC),PEEK(DIREC+1)
220 POKE DIREC,H
230 POKE (DIREC+1),L
240 NEXT A
250 DATA 0,0,0,2,0,4,0,6,0,8,0,10,0,12,0,14,0,16,0,18
255 PRINT
260 FOR A=0 TO 9
270 PRINT ORIGEN+(A*2),PEEK(ORIGEN+(A*2)),PEEK(ORIGEN+(A*2)+1)
280 NEXT A
In lines 100-110 we put a test code in the Basic variable memory as usual.
In 120-130 we extract the H and L bytes of the new ORG direction.
Then, in the 140-240 loop we read from DATA in line 250 the absolute directions(ORG=0) we need to relocate .
Then the content of the memory is compared before and after.
-
The 255 values are wrong, use 256!
-
Oh sorry. I'm on holidays without the real thing... no excuses.....Error is my second name....
The program fixed:
100 ALLOCATE 20
110 CODE ORIGEN=HEX$("00,00,00,01,00,02,00,03,00,04,00,05,00,06,00,07,00,08,00,09")
120 LET CODH=INT(ORIGEN/256)
130 LET CODL=REM(ORIGEN,256)
140 FOR A=0 TO 9
150 READ B,C
160 LET DIREC=(B*256)+C+ORIGEN
170 LET H=PEEK(DIREC)
180 LET L=PEEK(DIREC+1)
190 LET L=L+CODL
200 LET H=H+CODH+INT(L/256)
210 LET L=REM(L,256)
215 PRINT DIREC,PEEK(DIREC),PEEK(DIREC+1)
220 POKE DIREC,H
230 POKE (DIREC+1),L
240 NEXT A
250 DATA 0,0,0,2,0,4,0,6,0,8,0,10,0,12,0,14,0,16,0,18
255 PRINT
260 FOR A=0 TO 9
270 PRINT ORIGEN+(A*2),PEEK(ORIGEN+(A*2)),PEEK(ORIGEN+(A*2)+1)
280 NEXT A
-
Alternate idea: do the realocation in machine code.
Write the routine in Turbo Asmon, it is can compile to BASIC program (With Allocate and CODE strings).
ORG 0
JR MAIN
PUSH HL
POP BC
LD HL,(CALL1+1)
ADD HL,BC
LD (CALL1+1),HL
LD HL,(CALL2+1)
ADD HL,BC
LD (CALL2+1),HL
...
RET
MAIN
...
CALL1 CALL SUB1
...
CALL2 CALL SUB2
...
In the BASIC add a variable for the start for example MCODE
Befor it is used CALL USR(MCODE+2,MCODE) which are do the relocation.
-
Thanks Zozo, really your nethod is easy to implement. Only remember, I usually code by hand.....but can do bigger and better things if I begin using an assembler....
Is Turbo Asmon the best?
-
Is Turbo Asmon the best?
Yes, for compile code to BASIC.
For native machine code programs the HEASS are the best, it is can use all memory then you can handle very large sources (with memory expansion). And it is very fast, for example EXDOS 1.3 compile only 43 seconds on 4MHz machine! It is about 300k source in plain text format.
-
Ok. And, about the English manual, is it important?
-
Ok. And, about the English manual, is it important?
English manual for which program? :oops:
-
The two if possible...HEASS and T-ASMON.... Or, can I begin without manuals?
-
try EP Plus. you can write asm into basic lines!
http://ep128.hu/Ep_Konyv/Ep_Plus.htm
-
For more serious amounts of machine code, EXOS supports a relocatable file format, so you can do an EXOS call to load a relocatable user program or device driver into an arbitrary block of memory.
zozo: do you know if anyone actually ever used this in practice? It would mean they would have to have a way of producing the bit stream file format. I remember at IS we used to assemble relocatable modules twice, each time with a different ORG (probably 0 and 100h but I can't actually remember) and then we wrote a little utility program that would compare the two files and thus know which bits need to be relocatable, and output the appropriate bit stream file format.
-
zozo: do you know if anyone actually ever used this in practice?
Yes, BASIC command set expansions are use this format, and some EXOS system extensions are also.
But no too popular used because lack of support in assemblers. Not documented but I found the way in Asmon how possible creat relocatable code. Not too comfortable, but working :-)
At all 16 bit expressions need to set it is relocatable code or absolut value. For example:
PUSH DE
POP IY
.CSEG
CALL CSATSZAM
.ASEG
LD (7FFBH),A
INC DE
DEC B
.CSEG
JP M,ALAPOTCSINAL
It would mean they would have to have a way of producing the bit stream file format. I remember at IS we used to assemble relocatable modules twice, each time with a different ORG (probably 0 and 100h but I can't actually remember) and then we wrote a little utility program that would compare the two files and thus know which bits need to be relocatable, and output the appropriate bit stream file format.
Very interesting idea! Unfortunatelly this utility not published :-(
Now I thinking write similar one :-)
-
Very interesting idea! Unfortunatelly this utility not published :-(
Now I thinking write similar one :-)
I used the same trick with my very elementary "original" CP/M to EP128 porting: I had the disassembled CP/M BDOS from the Net, I assembled it with ORG 0 and ORG 100h. I wrote a simple python script (running on PC): where the byte values were different I stored the positions inside a table and I used ORG 0 version, so I simply had to add the offset. Since I was about relocating to positions on 256 byte boundaries, I only needed to deal with the high bytes (of course the theory works with even byte granulities, but it needs two tables, as some ops may use only low an and high bytes, and such).
-
Its amazing, I`m not the only one thinking about these "odd" things!
I remember that the Interlace mode program is in fact another relocatable module. Loading not needing permisions, implantig their code in System like real virus do....
-
I want to convert a MSX machine code application to Enterprise, it is SETalk, the voice synth.
On MSX it is loaded by a Basic program at a fixed address, but now I want it to work on every Enterprise.
I have been thinking about real relocatable code, not relocatable conversion like it is explained at the beginning on this thread.
---
The real problem I found about doing relocatable code with the Z80 is the impossibility to read the PC register to know the address of the instruction the processor is actually executing.
CALL and JP are the worst instructions to convert to relocatable, but we at least have JP (HL), that eases a lot the conversion.
Also, IS-Basic lets to pass a 16 bit number to the HL register pair on a machine code program created with the command CODE ROUTINE=HEX$("XX","XX", etc), and then the routine called with CALL USR(ROUTINE,ROUTINE)(Thanks Zozo for the tip).
Now we have the start address passed to HL. The routine has been assembled with a ORG 0000h.
SETALK: PUSH AF
PUSH BC
PUSH DE
PUSH HL
CALL PROG
POP HL
POP DE
POP BC
POP AF
I have though that something like this will serve me to do a call:
SETALK: PUSH AF
PUSH BC
PUSH DE
PUSH HL ; is good to store another copy of the start address just in case
LD DE, RET1 ; we need the relative address of the return
PUSH HL
ADD HL, DE
EXX DE, HL
POP HL
PUSH DE ; Now we have the absolute return address on the stack
PUSH HL
LD DE,PROG
ADD HL,DE
POP DE
JP (HL) ; We still have the start address on DE, but we can
; pass more data by the stack if we remember to POP it
; inside the simulated call
;CALL PROG
ret1: POP HL
POP DE
POP BC
POP AF
But surely you know an easier way....
-
It is not the most elegant solution, but if there is any fixed address that is safe to temporarily overwrite, then a JP (HL) (E9h byte) can be stored there and called so that it effectively becomes CALL (HL). Or even something like CALL (IX + DE) with a few more bytes. Possible places to store the JP (HL) at include the beginning of page 0, and usually unused parts of the EXOS stack around AC00h.
-
EXOS have a support for a relocatable modules, header 02h
1) little code needed which is using EXOS 30 for load the remaining code from relocatable module
2) IS-BASIC extension also using relocatable modules, these are handled with simple LOAD command. Then needed to write the thing as new BASIC instructios or functions.
-
The code to convert is very simple and short, it is not necessary to change pages, only an EXOs call to print characters to the EDITOR channel.
I know it is un-elegant and ugly... but it is a challenge for me to write a program that doesn't need absolute addresses nor auto-modifiable code. Doing it needs a twist of the mind. 10 instructions or more in exchange of only one... At least simulating a JP is easier....
I think I have seen that call to a JP (HL) used on EXOS.
I will do a version of each one to see.
-
EXOS have a support for a relocatable modules, header 02h
1) little code needed which is using EXOS 30 for load the remaining code from relocatable module
2) IS-BASIC extension also using relocatable modules, these are handled with simple LOAD command. Then needed to write the thing as new BASIC instructios or functions.
I know, header 02H, once in a time I decoded the "Mordon's quest" adventure only searching for the vocabulary, at the end I found the game rules and the map.... Without EXDOS controller, only tape and a printer, with a Basic listing, reading the flow of 1s and 0s. I was very young and used to thought that I was the only Enterprise owner in Spain. Today I have less knowledge than then...
Recently I have also decoded the first version of the Mouse.xr(extension relocatable) driver. But this time searching the memory of the emulator...
---
I don't want to load Basic extensions, I like the code to run on all Enterprises. But we lack the utility to make relocatable modules.
I remember another app decoded with the emulator, it was that Joystick driver (https://enterpriseforever.com/other-topics/re-looking-for-ep128/msg52656/#msg52656) listing submitted by an user to a Dutch magazine.
On classic times it must have been a very normal application. Why it still doesn't surface?
It is a good challenge, if I decoded the game with a Basic listing, another listing is enough to do the encoding task. Then, once Ziiiped, it can make the task at a reasonable speed. Needed are two binaries of the same file compiled at different addresses, one of them at 0000h.
-
The real problem I found about doing relocatable code with the Z80 is the impossibility to read the PC register to know the address of the instruction the processor is actually executing.
Here's a bit of a wild idea if you know interrupts are enabled:
HALT
DI
DEC SP
DEC SP
POP HL ; HL=address of DI instruction :-)
EI
(untested :mrgreen: )
-
Thanks! It can make the experiment more weird, even without the first absolute address at the start....
-
Simple program to create EXOS module type 7 (relocatable extension):
[attachurl=1]
The input is raw machine code that is compiled at org 0000h, and the code is repeated twice. With sjasm, this is achieved by including the original source file from another file and using MODULE to avoid duplicate labels.
-
Simple program to create EXOS module type 7 (relocatable extension):
Working! :smt038
-
Thanks! I have to try it first. This can work with an extension, like Mouse.xr.
-
:smt041 :smt041 :smt041
-
Some silly questions:
With an Hex editor, I have changed the module type to 02 on byte 1 on the header of the dbasx.xr file created by Zozo. I have also put 0FFh on bytes 4 and 5 of the header(no offset). It has loaded correctly without installing the extension.
-Is this the procedure?
-How can I create raw machine code with sjasm? The executable file is not admitted by reloc.
-
With an Hex editor, I have changed the module type to 02 on byte 1 on the header of the dbasx.xr file created by Zozo. I have also put 0FFh on bytes 4 and 5 of the header(no offset). It has loaded correctly without installing the extension.
-Is this the procedure?
I tried the same, it is even in reloc.cpp as commented out code, but type 2 modules apparently need to be written as BASIC extensions, I do not know how to do that, so I changed it to type 7.
-How can I create raw machine code with sjasm? The executable file is not admitted by reloc.
There is a simple example in the .zip file and also Zozosoft's dbasx extension, you need to compile reloc2.s or dbasx2.s to create a file that is accepted by reloc.exe. reloc2.s contains only these lines:
org 0000h
module Reloc_0
include "reloc.s"
endmod
module Reloc_1
include "reloc.s"
endmod
The actual source code is in reloc.s, the reason why it is compiled in two instances is that reloc.exe needs this to find the absolute addresses (16-bit words) that require relocation.
-
I forgot to remove all ORGs and ENDs from the code....
-
I tried using ASMON in the past to assemble relocatable modules (it was to play around with some BASIC extensions actually). I used .CSEG and .ASEG but I found that it didn't work properly for me (I seem to remember that it didn't write the last byte properly or something). Maybe I was doing something wrong.
But... did you know that Hisoft Devpac will create relocatable modules? And it automatically knows which values are addresses and which aren't. I used it several times successfully to create relocatable modules.
-
did you know that Hisoft Devpac will create relocatable modules? And it automatically knows which values are addresses and which aren't. I used it several times successfully to create relocatable modules.
Yes. Just I don't liked too much the GEN :oops: But I only wrote few examples as relocatable, 99% of my programs are fixed :-)
Today I prefer Sjasm :-)
-
But... did you know that Hisoft Devpac will create relocatable modules? And it automatically knows which values are addresses and which aren't. I used it several times successfully to create relocatable modules.
Then, maybe Devpac was the application used to make those classic relocatable programs.
-
Then, maybe Devpac was the application used to make those classic relocatable programs.
Yes... I don't know for sure but I always assumed that they were written in Devpac. I think in the early days Devpac was the only assembler available, although ASMON appears to have been around in late summer 1986 (according to the IEUG magazines).
-
By the way... Does anyone have the English manual? Thanks
Google translated Magyar (https://translate.google.com/translate?sl=hu&tl=en&js=y&prev=_t&hl=es&ie=UTF-8&u=http%3A%2F%2Fwww.ep128.hu%2FEp_Konyv%2FHISOFT_Devpac.htm&edit-text=&act=url) is very hard for me....
It is not a bad translation, but Google also translates the commands. For example, on some part of the text:
Az
A,, <ENTER>
parancs (az editorból kiadva) általában elegendő a fordításhoz; ez a forrást assembly lista nélkül fogja fordítani.
Is translated as:
The
The "<ENTER>
command (issued from the editor) is generally sufficient for translation; this source will be translated without assembly list.
Then, I have to read constantly the original to see what is the real syntax of the command.
-
By the way... Does anyone have the English manual? Thanks
I have :-) Forgot to scan it :oops:
[attach=1]
-
And, the original Hisoft Pascal manual?
By the way... I have found this resemble of David Link and Dave Nutkins, founders of HISOFT:
HiSOFT has been in existence since 1980, founded by David Link and Dave Nutkins. Originally we created software for the NASCOM 1 kit-built microcomputer but swiftly moved on to the ZX Spectrum, for which we created many esoteric items such as HiSOFT Devpac, HiSOFT C, HiSOFT BASIC, HiSOFT Pascal, UltraKit, Colt and much more.
After great success with the various incarnations of the Spectrum we ported our core titles (Devpac, C++ and Pascal) to many other Z80-based computers; Tatung Einstein, Newbrain, Memotech 512, Amstrad CPC& PCW, Elan Enterprise and more! 'Twas a lot of fun and, undoubtedly, this list will stir as much excitement in some people as David's favourite band since 1971, Genesis, do in him!
After the Z80 processor began to flag (shame!), we moved on to the 68000 which meant moving stuff over to the Atari ST and Commodore Amiga. This, along with many hardware projects (such as Megalosound, Replay 16, Clarity 16, Squirrel SCSI, VideoMaster etc.) kept us going through the 90s until, reluctantly, we were forced to take the PC seriously.
Having forged a close relationship with MAXON Computer in Germany throughout the Amiga and Atari years, it was natural for us to take on the UK mantle for their flagship product, CINEMA 4D, an exciting and now rather important 3D product. HiSOFT promoted, distributed and sold CINEMA 4D from 1997 until 2001, at which point David Link formed MAXON Computer Ltd and moved all things CINEMA 4D under the MAXON umbrella.
David worked at MAXON UK as the CEO until resigning for personal reasons in early 2003, after which he ran a successful pub and café with his partner, without whom it would not have been possible.
David now designs and maintains websites while owning and running a busy pub/guest house in Shanklin, Isle of Wight.
-
I would like to return to this topic, now that I am about to begin to transcript the FisherTechnick CPC Basic listings to IS-BASIC.
Let's say that we can make a mixed Basic-MachineCode program on the Enterprise.
One of the most valuables tools to make a subroutine aware of its position is to pass it its own start address. This method was hinted to me some time ago (https://enterpriseforever.com/programming/where-i-am/msg38070/#msg38070) by Zozo:
If the machine code subroutine has been defined with MC=HEX$("XX,XX,...") then, we can use CALL USR(MC,MC) to pass its start point on the HL register pair. The only drawback is that we lose the option to pass data to the subroutine.
This would be convenient on short routines with a few jumps/calls or fixed positions. But the problems multiply with long code, all the juicy options of the Z80 involve absolute addressing, and it can be a problem to repositioning all the jumps and calls inside a big program.
A solution that I have found is one that has been there all the time: WORD$.
Imagine we have written a MC subroutine to print a text on the screen, for example:
start: ld a, 0 ;Channel to write
ld bc, 5 ;Length of the string
ld de, STRING ;Adress of the string
EXOS 8 ;Write block
ret
STRING: db "Hello"
The Basic program would look like this:
100 ALLOCATE 16
110 CODE TEXTO=HEX$("3E,00,01,05,00,11,XX,XX,F7,08,C9,48,65,6C,6C,6F")
120 CALL USR(TEXTO,0)
But this routine will not work, because we need to give DE the absolute address of the string, which we don't know.... but we already know it, if we modify the line 110:
110 CODE TEXTO=HEX$("3E,00,01,05,00,11")&WORD$(TEXTO+11)&HEX$("F7,08,C9,48,65,6C,6C,6F")
TEXTO is already defined at the start of the line, so when the execution reaches "WORD$(TEXTO+11)" it doesn't give "*** Variable not initialised."
[attachimg=1]
Please don't laugh too hard at me if this is common knowledge....
-
For these problems developed the EXOS header 02, User relocatable modules function.
Just need to allocate memory for it, and load it to the allocated buffer. During the loading the EXOS recalculate the direct addresses to valid address for the current loading location.
Look about IstvanV's SJasmEP project, if I remember right he added support of these.
-
Yes, thanks, IstvanV did a good work on this (https://enterpriseforever.com/programming/easy-relocatable-code-in-basic/msg70156/#msg70156) same thread.
I mean, the WORD$ function has been underused(by me) and it seems that this is the real task(inserted in a CODE definition) for which it was created.
Not so long ago I discovered (https://enterpriseforever.com/programozas/basic/msg74234/#msg74234) another use, to extract the 2 bytes of 16bit numbers:
-
Simple program to create EXOS module type 7 (relocatable extension):
...
The input is raw machine code that is compiled at org 0000h, and the code is repeated twice. With sjasm, this is achieved by including the original source file from another file and using MODULE to avoid duplicate labels.
Thanks, that's a really clever idea! :mrgreen:
I think that I'm going to have to steal that method. ;-)
But... did you know that Hisoft Devpac will create relocatable modules? And it automatically knows which values are addresses and which aren't. I used it several times successfully to create relocatable modules.
Cool, I was wondering if there was any assembler that could create a relocatable module.
Good old Hisoft! :cool:
Today I prefer Sjasm :-)
But of course, I agree with Zozosoft here, these days it is much easier to just build assembly-language programs on a PC, and then test them on ep128emu.
I'm finding that the virtual device feature in zOOm's SJASMPLUS (https://github.com/z00m128/sjasmplus) is making it really easy to do some pretty serious modifications to IS-DOS.