|
|
 | | From: | Albert van der Horst | | Subject: | retroforth 386 assembler | | Date: | 12 Jan 2005 04:35:53 +0100 |
|
|
 | It took the better part of an evening but here it is: an assembler for retroforth at the 386 level without sib byte. (You may add the Pentium instructions of a recent post, but I don't think floating point and the scaled index byte are retro.)
I felt very, well, retro. Debugging a source with no possibility to load files or blocks. ( Pasting in and redirection worked reasonable in linux KDE). The very basic debugging aids like .s and dump are missing from retroforth. It doesn't help that there is no prompt. So there is no difference between correct execution and an infinite loop.
Don't think that I wrote r@ and dsp@ in assembler. I used the parse and unparse programs to go back and forth between retro blocks with machine code and assembler.
If you do something substantially more difficult than the ``nip'' example at the end, I would advise to use the fully documented, great assembler at forthassembler.html You have than syntax checking during development. The syntax of this assembler may be cumbersome, but once errorfree it is unambiguous. The testset contains all possible combinations. I leave it as an exercise to pull the testset through retroforth.
--------------8<---------------8<------------------8<-----------8<---- | Words needed extra in behalf of miniassembler | ----------------------- compatibility prelude --------------------
' | alias \
macro
\ ISO : r@ $04ee83 3, $0689 2, $58 1, $50 1, ;
\ Return the data stack POINTER as before execution of this word. : dsp@ $04ee83 3, $0689 2, $c68b 2, ;
forth
: depth $8049daf dsp@ - 2 >> ;
\ Note retroforth's +! is not ISO-compatible. : !+ swap +! ;
\ Print top 3 stack items : .s cr rot dup . rot dup . rot dup . cr ;
\ -------------------- assembler proper ----------------------
hex
\ -------------------- retroforth specific ------------- \ --assembler_generic split 1pi fir 1family, ) \ A4sep27 AvdH : split dup 8 >> swap $ff and ; \ Split X : REMAINDER and ls BYTE \ Post INSTRUCTION of LENGTH. Big endian specific! : post swap , 1 cells - allot ; \ Fixup with ms byte of FIX below ADDR, leave next FIX ADDR : fix| 1 - >r split r@ !+ r> ; : 1pi create , does> @ 1 post ; \ 1 byte post-it opcode : 2pi create , does> @ 2 post ; \ 2 byte post-it opcode : 3pi create , does> @ 3 post ; \ 3 byte post-it opcode \ Fixup from behind starting with ls byte. : fir create , does> @ here swap repeat swap fix| swap 1+ until drop ; \ Create a family adding INC to OPCODE with COUNT members : 1family, repeat >r dup 1pi over + r> until drop drop ; : 2family, repeat >r dup 2pi over + r> until drop drop ; : 3family, repeat >r dup 3pi over + r> until drop drop ; : family|r repeat >r dup fir over + r> until drop drop ; : (C,) 1, ; : (W,) 2, ; : (L,) , ;
\ -------------------- system independant -------------
\ --assembler_i86_fixups_1 [AX] AX| AX|) CF: ?32 | A4sep27 AvdH
40 00 4 family|r ZO| BO| XO| R| 05 fir MEM| | instead of ZO| BP| ) 01 00 8 family|r [AX] [CX] [DX] [BX] ~SIB| [BP] [SI] [DI] 01 00 8 family|r AL| CL| DL| BL| AH| CH| DH| BH| 01 00 8 family|r AX| CX| DX| BX| SP| BP| SI| DI| 08 00 8 family|r AL'| CL'| DL'| BL'| AH'| CH'| DH'| BH'| 08 00 8 family|r AX'| CX'| DX'| BX'| SP'| BP'| SI'| DI'| 08 00 6 family|r ES| CS| SS| DS| FS| GS| 0100 0000 2 family|r B| X| 0200 0000 2 family|r F| T|
\ Use any primed thingies with AS: prefix . ) 6 fir MEM|' 1 0 8 family|r [BX+SI]' [BX+DI]' [BP+SI]' [BP+DI]' [SI]' [DI]' [BP]' [BX]' \ --assembler_commaers ) \ A4sep27 AvdH
\ O=obligatory R=Relative I=Immediate ) ' (W,) alias OW, ' (L,) alias IL, ' (L,) alias (RL,) ' (W,) alias IW, ' (W,) alias (RW,) ' (C,) alias IB, ' (C,) alias (RB,) ' (L,) alias L, ' (W,) alias SG, ' (W,) alias W, ' (C,) alias P, ' (C,) alias B, ' (C,) alias IS,
\ --assembler_i86_opcodes_1 ) \ A4sep27 AvdH 08 06 4 1family, PUSH|ES, PUSH|CS, PUSH|SS, PUSH|DS, 08 07 4 1family, POP|ES, -- POP|SS, POP|DS, 08 26 4 1family, ES:, CS:, SS:, DS:, 08 27 4 1family, DAA, DAS, AAA, AAS, 01 00 2 family|r B'| X'| 08 04 8 1family, ADDI|A, ORI|A, ADCI|A, SBBI|A, ANDI|A, SUBI|A, XORI|A, CMPI|A, 02 A0 2 1family, MOV|TA, MOV|FA,
70 1pi J, \ As in J, L| Y| S, ) 01 00 2 family|r Y| N| 02 00 8 family|r O| C| Z| CZ| S| P| L| LE|
08 40 4 1family, INC|X, DEC|X, PUSH|X, POP|X, 90 1pi XCHG|AX, \ --assembler_i86_opcodes_2 ) \ A4sep27 AvdH 08 00 8 2family, ADD, OR, ADC, SBB, AND, SUB, XOR, CMP, 02 84 2 2family, TEST, XCHG, 01 98 8 1family, CBW, CWD, IR2, WAIT, PUSHF, POPF, SAHF, LAHF, 02 A4 6 1family, MOVS, CMPS, -- STOS, LODS, SCAS, 08 B0 2 1family, MOVI|BR, MOVI|XR, 08 C3 2 1family, RET, RETFAR, 08 C2 2 1family, RET+, RETFAR+, 01 C4 2 2family, LES, LDS, 00C6 2pi MOVI, 0CD 1pi INT, 01 CC 4 1family, INT3, -- INTO, IRET, 01 D4 4 1family, AAM, AAD, -- XLAT, 01 E0 4 1family, LOOPNZ, LOOPZ, LOOP, JCXZ, 02 E4 2 1family, IN|P, OUT|P, 2 EC 2 1family, IN|D, OUT|D, 01 E8 2 1family, CALL, JMP,
0088 2pi MOV, 008C 2pi MOV|SG, 008D 2pi LEA, EA 1pi JMPFAR, EB 1pi JMPS, 9A 1pi CALLFAR, A8 1pi TESTI|A, \ --assembler_i86_opcodes_3 ) \ A2oct21 AvdH 01 F0 6 1family, LOCK, -- REPNZ, REPZ, HLT, CMC, 01 F8 6 1family, CLC, STC, CLI, STI, CLD, STD, | 38FE 800 80 8 2family, ADDI, ORI, ADCI, SBBI, ANDI, SUBI, XORI, CMPI, 0800 83 8 2family, ADDSI, -- ADCSI, SBBSI, -- SUBSI, -- CMPSI, 800 10F6 6 2family, NOT, NEG, MUL|AD, IMUL|AD, DIV|AD, IDIV|AD, 0800 00FE 2 2family, INC, DEC, 0800 10FF 4 2family, CALLO, CALLFARO, JMPO, JMPFARO,
0200 0000 2 family|r 1| V| 0800 00D0 8 2family, ROL, ROR, RCL, RCR, SHL, SHR, -- SAR, 0800 C0 8 2family, ROLI, RORI, RCLI, RCRI, SHLI, SHRI, -- SARI,
00F6 2pi TESTI, 008F 2pi POP, 30FF 2pi PUSH, 00AF0F 3pi IMUL,
decimal
\ ---------------------- a small test ------------------------------ \ retroforth specific
: nip [ LEA, SI'| BO| [SI] 4 B, ] ;
.." test of nip" 1 2 3 4 .s nip .s
--------------8<---------------8<------------------8<-----------8<----
Groetjes Albert -- Albert van der Horst,Oranjestr 8,3511 RA UTRECHT,THE NETHERLANDS To suffer is the prerogative of the strong. The weak -- perish. albert@spenarnc.xs4all.nl http://home.hccnet.nl/a.w.m.van.der.horst
|
|
 | | From: | Marc Olschok | | Subject: | Re: retroforth 386 assembler | | Date: | Thu, 13 Jan 2005 16:34:24 +0000 (UTC) |
|
|
 | Albert van der Horst wrote: >[...] > I felt very, well, retro. Debugging a source with no possibility to load > files or blocks. ( Pasting in and redirection worked reasonable > in linux KDE). > The very basic debugging aids like .s and dump are missing from > retroforth.[...]
You can grab a (very simple) dump and some other utilities from . There was a small block-editor included in version 7.4. Together with the file-words you can edit and save your source.
Marc
|
|
 | | From: | Jerry Avins | | Subject: | Re: retroforth 386 assembler | | Date: | Thu, 13 Jan 2005 13:57:48 -0500 |
|
|
 | Marc Olschok wrote:
> Albert van der Horst wrote: > >>[...] >>I felt very, well, retro. Debugging a source with no possibility to load >>files or blocks. ( Pasting in and redirection worked reasonable >>in linux KDE). >>The very basic debugging aids like .s and dump are missing from >>retroforth.[...] > > > You can grab a (very simple) dump and some other utilities from > . > There was a small block-editor included in version 7.4. Together with > the file-words you can edit and save your source. > > Marc
Augmented .S and DUMP to suit my taste; MAXXforth:
2VARIABLE X.R 7 0 X.R 2! \ Argument and print routine
\ : .S_WIDTH ( n -- ) X.R CELL+ ! ;
: (.S) DEPTH 0= IF CR ." Empty " ELSE DEPTH DUP ." Depth (decimal): " .D CR 0B MIN DUP 0 DO DUP PICK X.R 2@ EXECUTE 1- LOOP DROP THEN CR ;
: .S [ ' .R CFA ] LITERAL X.R ! (.S) ; : U.S [ ' U.R CFA ] LITERAL X.R ! (.S) ;
: >CHAR ( n -- c ) DUP 9 > 7 AND + 30 + ;
\ DUMP
: key-check ( start-of-line -- start-of-line | nothing ) ?TERMINAL IF KEY 1B = IF SPACE ." OK " DROP QUIT ELSE BEGIN ?TERMINAL UNTIL KEY 1B = IF SPACE ." OK " DROP QUIT THEN THEN THEN ;
: dump-header ( -- ) CR 7 SPACES 10 0 DO I >CHAR EMIT 2 SPACES LOOP 10 0 DO I >CHAR EMIT LOOP ;
: dump-line ( start-of-line -- start-of-next-line ) CR DUP BASE @ >R HEX 4 U.R SPACE 10 0 DO SPACE DUP I + C@ 10 /MOD >CHAR EMIT >CHAR EMIT LOOP 2 SPACES 10 0 DO DUP I + C@ DUP 1F 80 WITHIN IF EMIT ELSE DROP ." ." THEN LOOP 10 + R> BASE ! key-check ;
: DUMP ( start count -- ) SWAP 10 /MOD 10 * SWAP ROT + 10 /MOD SWAP 0= 1+ + DUP >R dump-header 0 DO dump-line LOOP DROP R> 9 > IF dump-header THEN SPACE ;
Jerry -- Engineering is the art of making what you want from things you can get. ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ
|
|
 | | From: | crc | | Subject: | Re: retroforth 386 assembler | | Date: | 15 Jan 2005 17:42:30 -0800 |
|
|
 | I don't define QUIT in RetroForth. Use of a nested definiton is the best way to test it though.
Something like:
: foo bye ; : bar foo ; : baz bar ; baz
should be enough to mess up the returns stack a bit. If it can exit successfully, then your "bye" works ok.
-- Charles
|
|
 | | From: | PhiHo Hoang | | Subject: | Re: retroforth 386 assembler | | Date: | Sat, 15 Jan 2005 21:48:45 -0500 |
|
|
 | charles.childers
>I don't define QUIT in RetroForth.
Just replace :
interpret:
with :
code 'QUIT', interpret
> Use of a nested definiton is the > best way to test it though. > > Something like: > > : foo bye ; > : bar foo ; > : baz bar ; > baz > > should be enough to mess up the returns stack a bit. If it can exit > successfully, then your "bye" works ok. >
Hooray ! Yes, it works :-)
Thanks,
Cheers,
PhiHo
|
|
 | | From: | crc | | Subject: | Re: retroforth 386 assembler | | Date: | 12 Jan 2005 15:30:58 -0800 |
|
|
 | I'm very impressed with this. I've made a few changes to make it work on RetroForth 7.6. While I still find the syntax a bit convulated; it works wonderfully from what I can see so far.
|
|
 | | From: | Albert van der Horst | | Subject: | Re: retroforth 386 assembler | | Date: | 13 Jan 2005 12:38:37 GMT |
|
|
 | In article <1105572658.876232.282450@c13g2000cwb.googlegroups.com>, crc wrote: >I'm very impressed with this. I've made a few changes to make it work >on RetroForth 7.6. While I still find the syntax a bit convulated; it >works wonderfully from what I can see so far.
There is a price to pay for simplicity.
You can use ciasdis for syntax checking though: Example --------------------------- ciasdis 0 ORG \ Don't forget this, or you will regret it. OK CODE JAN ADD, OK X| F| AX'| R| BX| OK ADD, OK ADD, ADD,? ciforth ERROR # 26 : AS: PREVIOUS INSTRUCTION INCOMPLETE ------------------------- To recover after an error just start a new word: CODE JAN ADD, OK >
Did you find parse and unparse usefull that I sent the other day?
Groetjes Albert
--
-- Albert van der Horst,Oranjestr 8,3511 RA UTRECHT,THE NETHERLANDS One man-hour to invent, One man-week to implement, One lawyer-year to patent.
|
|
 | | From: | crc | | Subject: | Re: retroforth 386 assembler | | Date: | 13 Jan 2005 15:08:36 -0800 |
|
|
 | Yes, those parse/unparse programs are quite helpful. I'm starting to make sense of the assembly syntax now; with luck I'll be able to write words using it soon.
|
|
 | | From: | crc | | Subject: | Re: retroforth 386 assembler | | Date: | 13 Jan 2005 14:56:11 -0800 |
|
|
 | Since I don't mind lowercase chars in a dump, I use:
: h. hex . decimal ; : dump over h. repeat >r dup c@ h. 1+ r> until cr ;
I've been using varients of this "dump" word for a couple of years now.
I really like the code in the S0x files. Would it be ok for me to add them to the code library? And if so, what license/copyright information should be included with them?
You'll be seeing the block editor again soon; a slightly updated version will be included in 7.7. (The block editor plays a major role in the work I'm doing on 8.0). I have some words that will allow loading and saving of a blockfile under Linux and am working on implementations of these words for the Windows, FreeBSD, and BeOS/Generic/Generic+libdl.so ports.
|
|
 | | From: | Marc Olschok | | Subject: | Re: retroforth 386 assembler | | Date: | Fri, 14 Jan 2005 15:39:31 +0000 (UTC) |
|
|
 | crc wrote: >[...] > I really like the code in the S0x files. Would it be ok for me to add > them to the code library? And if so, what license/copyright information > should be included with them?
You are welcome to include them, I am glad that they might be useful to somebody else.
I would feel rather stupid, if I put more restrictions on these files than on the underlying Forth. Since Retroforth is given available 'completely free' the same can be applied to the above files.
> > You'll be seeing the block editor again soon; a slightly updated > version will be included in 7.7. (The block editor plays a major role > in the work I'm doing on 8.0). I have some words that will allow > loading and saving of a blockfile under Linux and am working on > implementations of these words for the Windows, FreeBSD, and > BeOS/Generic/Generic+libdl.so ports. >
Good news. Best regards, Marc
|
|
 | | From: | PhiHo Hoang | | Subject: | Re: retroforth 386 assembler | | Date: | Sat, 15 Jan 2005 12:11:32 -0500 |
|
|
 | charles.childers wrote:
[SNIP]
> > You'll be seeing the block editor again soon; a slightly updated > version will be included in 7.7. (The block editor plays a major role > in the work I'm doing on 8.0). I have some words that will allow > loading and saving of a blockfile under Linux and am working on > implementations of these words for the Windows, FreeBSD, and > BeOS/Generic/Generic+libdl.so ports. >
This is cool.
I also like to suggest adding to rf.asm:
eval_cb:
upsh [esp + 4] ; Start of bootstrap upsh [esp + 8] ; Length of bootstrap call eval ; Interpret bootstrap
ret
with eval_cb exported, IA32FVM wrapper now can run either Win32For or RetoForth kernel via [Setup] , [RetroForth] and [R4Blocks] sections in IA32FVM.ini
[Setup] Forth= RetroForth ; Forth = Win32Forth
[RetroForth] HPK = RF.dll Extend = R4Blocks R4 = 1 DLL = 1 Interp = 1
[R4Blocks] B000 = Block 000 B001 = Block 001 B002 = Block 002 B003 = Block 003 B004 = Block 004
as a result, RF.dll is now 4KB
To further reduce the size of RF.dll, bye is now a "high level" word in in block B000 ;-)
: bye [ $5b 1, ] ;
Some pusha popa were also commented out.
If you can find time to review these changes , they will be emailed to you .
Cheers,
PhiHo
|
|
 | | From: | Coos Haak | | Subject: | Re: retroforth 386 assembler | | Date: | Sat, 15 Jan 2005 20:48:39 +0100 |
|
|
 | Op Sat, 15 Jan 2005 12:11:32 -0500 schreef PhiHo Hoang:
> To further reduce the size of RF.dll, bye is now > a "high level" word in in block B000 ;-) > >: bye [ $5b 1, ] ; > Are you sure there is nothing on the returnstack that you can just pop a register and do a return? What if you put BYE deep in a series of nested words?
Why not (under Windows/Dos) like this: : bye [ $4cb4 2, $21cd 2, ] ;
And the lowest byte on the data stack is returned to the OS too ;-) -- Coos
|
|
 | | From: | PhiHo Hoang | | Subject: | Re: retroforth 386 assembler | | Date: | Sat, 15 Jan 2005 19:58:20 -0500 |
|
|
 | Coos Haak wrote:
>> To further reduce the size of RF.dll, bye is now >> a "high level" word in in block B000 ;-) >> >>: bye [ $5b 1, ] ; >> > Are you sure there is nothing on the returnstack that > you can just pop a register and do a return?
Honestly, no, I am not. :-)
> > What if you put BYE deep in a series of nested words? >
Actually, the original code word for bye is :
code 'bye', windows_bye mov dword [rf_eax], eax mov dword [rf_esi], esi pop ebx ret
where
rf_eax rd 1 rf_esi rd 1
and
retroforth_interpreter: call retroforth_attach mov eax, dword [rf_eax] mov esi, dword [rf_esi] call interpret ret
retroforth_init: call init_retroforth mov dword [rf_eax], eax mov dword [rf_esi], esi ret
After a bit of refactoring bye just became:
code 'bye', windows_bye pop ebx ret
hence
: bye [ $5b 1, ] ;
Well, I am not quite sure how good is this bye.
After RetroForth was started up the snippet :
words QUIT
was repeated 10 times then a sequence of 11 bye ended that RetroForth session.
> > Why not (under Windows/Dos) like this: > : bye [ $4cb4 2, $21cd 2, ] ; > Trying the same test, after the first
words QUIT
then a bye , RetroForth crashed.
> And the lowest byte on the data stack is returned > to the OS too ;-)
Maybe RetroForth didn't like that lowest byte ;-)
I am willing to do some further testing if there is some further tests besides that
words QUIT bye
Cheers,
PhiHo
|
|
|