00:00:00 --- log: started forth/21.04.04 00:14:22 So, I thought of a simple way to approach profiling. Might nnot be the most memory efficient, but it's easy to implement annd provides a lot of data. 00:15:50 --- join: f-a joined #forth 00:16:40 So the idea is to allocate a memory buffer the same size as the part of my system where the code and definition lists reside. Fill it with zero data and point a spare register at it. Then overwrite the first few bytes of NEXT with a jump instruction to a "new NEXT," which does an "inc qword [+] 00:16:58 Run my application for a while and then restore the original NEXT. 00:17:18 Now that buffer will be full of count values, and they'll tell me exactly what regions in my image received the most attention. 00:17:44 A post-processor could associate word name information and so on with all of that data. 00:18:03 --- part: f-a left #forth 00:19:32 If I wanted to I could reduce the buffer size by only covering a portion of the whole image, but that would mean a new NEXT with more in it. But that might be preferable; don't know yet. 01:01:45 --- quit: pointfree (Quit: Connection closed for inactivity) 01:16:35 KipIngram, McCabe's "Forth Fundamentals Vol I" seems to be made of unobtainium. I've never been able to get hold of a copy. Someone should scan it. 01:18:31 there's two on amazon.de for a thousand bucks each .... 01:19:17 veltas, I've noted yours down for future inclusion should a future arise where I have such a page. It actually may happen this month. :-) 01:20:58 kiedtl, read the welcome message to #forth. If you have 2+ stacks and speak RPN then you're welcome here. We might even be a bit more flexible than that. 01:49:35 --- quit: shmorgle (Ping timeout: 265 seconds) 01:55:29 --- join: tech_exorcist joined #forth 02:02:04 --- quit: tech_exorcist (Remote host closed the connection) 02:02:26 --- join: tech_exorcist joined #forth 02:03:37 --- quit: tech_exorcist (Remote host closed the connection) 02:04:03 --- join: tech_exorcist joined #forth 02:04:30 --- quit: tech_exorcist (Remote host closed the connection) 02:04:51 --- join: tech_exorcist joined #forth 02:05:24 --- quit: tech_exorcist (Remote host closed the connection) 03:29:55 ecraven, indeed... definitely unobtainium! ;-) 03:37:26 Well, I'd scan mine, but I can't bear to dismantle it. It's a fairly low quality paperback, and I'm pretty sure it wouldn't surfive being opened onto a flat bed to every page. :-( 03:37:53 Maybe I can figure out a wa to take pictures of the pages, with the book held more gently open. 03:38:12 Maybe with one of those camera apps that do page strightening. 03:38:30 It reall is an excellent book. 03:48:38 I have one of those scanners that flattens bent pages actually... :-) 03:48:49 It also does OCR. 03:49:23 I can't even find a reference to the author to find out if he's still alive. 03:56:04 KipIngram: way back when I just took photos from above a book with a normal camera, still better than *not* having it at all 04:10:33 I've heard things about using forth as a macroassembler, how does that work? Could I use a forth as a cross-macro-assembler? 04:10:52 (wanting to experiment with uxn but the official assembler is insanely ugly) 04:10:56 (wanting to experiment with uxn but the official assembler is insanely ugly and forth is incer) 04:37:23 --- join: tech_exorcist joined #forth 04:57:49 ecraven: I've got an app that straightens pages on my android - I'll take a look into it. 04:58:46 KipIngram: that'd be great. but anything is better than nothing at all, so if you can share just plain pictures, someone else can look into prettying things up ;) 05:03:59 Yep - remind me in a few days if I haven't said anything more about it. 05:26:18 --- quit: rpcope (Ping timeout: 260 seconds) 05:31:21 --- join: rpcope joined #forth 05:58:48 --- join: f-a joined #forth 05:59:06 nihilazo, what cpus would you be targeting. For ones less complex than the x86 then yes assemblers in forth can be quite practical. Beyond that, an assembler for complex CPUs is as big a project as the forth itself sometimes. 05:59:30 the CPU is the UXN virtual machine, which is very simple 05:59:34 https://wiki.xxiivv.com/site/uxambly.html 05:59:51 nihilazo, ah then a forth assembler is pretty straightforward and likely a very good idea. 06:00:35 where would I start with building a forth assembler? 06:01:30 I am using 06:03:38 where si the link… 06:04:21 http://www.bradrodriguez.com/papers/tcjassem.txt 06:04:34 thanks! 06:06:16 there is a part 2 — well everything is good — here http://www.bradrodriguez.com/papers/ is good 06:07:19 thanks 06:15:33 --- quit: gravicappa (Ping timeout: 240 seconds) 06:27:56 I feel like maybe building a forth assembler for uxn might be less easy becasue uxn is itself a stack machine? Although that might make writing a forth assembler easier 06:37:57 actually it shouldn't be hard 06:38:09 I'm just not sure how to deal with uxn's callback things and stuff 06:38:22 (to be honest, I don't understand how the normal assembler works lol) 07:11:05 --- quit: tech_exorcist (Quit: tech_exorcist) 07:14:54 --- join: tech_exorcist joined #forth 07:15:51 I think it would be easier 07:16:35 proteusguy: nice 07:16:51 I mean, I think it might be easier? 07:16:52 idk tbh 07:20:48 I don't see how it could be harder 07:21:15 No operands to specify will simplify things 07:21:50 Even simple assembly like Z80 is a lot of work 07:22:33 Well Z80 is one of the more complicated 8-bit architectures 07:23:57 the thing I'm least sure how to do is that the uxn expects certain things in certain places 07:23:58 You can write a "restricted" x64 assembler though, without it becoming a massive headache. I've done up the moves, conditional and unconditional jumps, and arithmetic / logic instructions. 07:24:22 You really don't need that crazy big instruction set for 99.9% of what you might want to do. 07:24:38 In my case I want just enough assembly to write my "virtual instruction" layer. 07:24:49 like, it seems to have three locations (0200, 0204, 0208) which are called RESET, ERROR, and FRAME in the demo code 07:24:58 and I think the uxn VM executed specifically what is at those locations 07:25:03 but idk how to do that with forth given that labels are harder 07:25:08 (the ROM file starts at 0200) 07:25:15 It took about 2 4k disk blocks, used inefficient like old Forth, to hold that partial assembler. 07:25:22 Maybe 2 and a half. 07:25:59 If you really think on the addressing modes, you can render them in an algorithm fairly cleanly. 07:26:09 --- join: gravicappa joined #forth 07:28:44 hmm, yeha 07:29:37 I think the main thing idk about right now is how to deal with those things that eeds to be at specific addresses. In all of the demo code they're jumps to a few different labels 07:29:38 https://git.sr.ht/~rabbits/uxn/tree/master/item/projects/examples/dev.console.usm 07:30:03 (in the existing uxn assembler, |0200 means "at 0200") 07:30:35 ^whatever is the realative address of a label ,whatever is an absolute address of a label 07:30:37 it's a very odd asm 07:38:40 --- quit: Zarutian_HTC1 (Read error: Connection reset by peer) 07:38:58 --- join: Zarutian_HTC joined #forth 07:40:37 like, I read that thing about building an assembler in forth that f-a sent but I'm not sure how to deal with having to have certain things be at certain addresses in a forth assembler 07:40:43 maybe I'm overthinking it or missing an obvious trick 07:43:14 That doesn't really come up - generally speaking the instructions you actually use (to write primitives) just operate on the stack and things obtained from the stack. 07:43:53 Everywhere in memory you need to get to you will have a pointer to laying around somewhere. 07:44:37 I think a appropos comment would be to say that you really don't need to deal with labels in Forth assembly. 07:44:52 The Forth dictionary supplies all your "memory roadmap" needs. 07:45:53 Well, you might think of using a label for the short jumps in conditional primitives, but I implemented that with something similar to how IF THENN is handled. 07:46:18 leave the backpatch address on the stack, and fill in its content when you know what it needs to be. 07:46:35 Honestly, for primitives, though, you could just count bytes and code jump distances manually. 07:47:02 You don't wind up writing some big sprawling thing in assembly - it's just a whole flock of short little snips. 07:47:32 Lemme see if I can get some syntax examples for you. 07:50:22 Here are the two main blocks of my assembler - there's some usage of it near the end. 07:50:24 https://imgur.com/a/hS2224d 07:50:42 If you want it you can scratch my code generator algorithm out of that. 07:51:07 I might use some words you're not familiar with, that I cooked up myself - feel free to ask questions. 07:51:23 I'm about to go on the road for the bulk of the day, though, so it will probably be tonight before I can answer. 07:52:45 thanks 07:53:29 I understand "The Forth dictionary supplies all your "memory roadmap" needs." for things i'm defining myself but I'm not sure for things the machine itself needs to be at specific addresses 07:54:32 Like what, for example? 07:55:22 I do some system calls in mine, for keyboard / disk/ display service. 07:55:43 And I allocate a couple of blocks with syscalls, right at the beginning, which I then use for the system. 07:56:40 on uxn, the machine has specific addresses it looks for to start, so it starts executing at 0200, and then executes starting at 0208 every frame it draws 07:57:12 Oh, well, those are just numbers, right? 07:57:19 You have to code them into your startup code. 07:57:42 In Forth variables leave an address on the stack, but nothing stops you from creating a constant and then treating it like a variable. 07:57:57 I'm confused 07:58:03 It's one of the great things - you can just poke at anything you want to. 07:58:27 this assembler isn't a forth running on the machine, it's a forth running on x86 that I am using to write an assembler for uxn 07:58:48 Ah, you're cross-compiling. 07:59:21 Ok, well, the same applies - you have to hard code target resource access. Only downside is you just can't test it incrementally very well 08:00:01 --- quit: f-a (Quit: leaving) 08:00:22 What's uxn? 08:01:05 it's this weird VM https://wiki.xxiivv.com/site/uxn.html 08:01:20 I want to write an assembler for it, and I wanted to try writing a forth assembler 08:02:15 Oh, cool. Ok. Well, like I said I'm hitting the road here any minute, but I'll look that over later. I'd be glad to give you some counsel if you want it. 08:02:46 thanks 08:02:50 I think it'll turn out to be easier than you think - something will go click and then you'll have it down. 08:03:03 Should get back here arounnd 5pm (seven hours). 08:04:33 ok 08:07:07 I might just write a header into the file that has those pointers in it? idk 08:50:25 reading here, http://www.bradrodriguez.com/papers/tcjassem.txt in special cases, (resident vs cross compilation) 08:50:52 it says that defining works analogous to those on the dictionary for the target machine is good to do 08:51:48 but do I need to have a dictionary then? 09:05:38 or do I need to make a seperate dictionary for the target stuff? 09:06:20 nihilazo, what kind of assembler? you could use a format that looks like traditional assembly in your source file and write a forth program to assemble that 09:06:37 or make forth words that output binary data so the assembly source is read into the forth prompt 09:07:06 I was initially going to go for the first but then somebody said about the second 09:07:16 the second seems more powerful but it would be hard to do some specific things i want to do? 09:07:18 idk 09:07:41 the second is less flexible and potentially harder to read the source but easier to implement 09:12:31 hmm, yeah 09:12:48 I would like to have some higher level constructs like an IF ... ELSE ... THEN and some other stuff 09:12:48 idk 09:13:02 and being able to use all of forth to create macros in the second type seems very powerful 09:13:14 really I'm not sure what i want to do exactly 09:15:06 the one described on that page seems to be the second type 09:20:52 Easier to implement is usually the best choice. Forth programs empower users more when they're shorter and easier to understand 09:21:21 If there is a point to Forth that is one of the points 09:23:28 true 09:24:30 It's got a very open source spirit in a way 09:25:16 the thing with doing it in the way where the assembler is inside forth is cool 09:25:29 but I'm not sure how to put stuff at very specific addresses without doing jumps 09:25:34 s/jumps/labels/ 09:26:34 You can have labels 09:27:05 Just don't centre the universe around them 09:32:41 I'm not sure how to do that in an assembler that's inside forth 09:32:43 I guess? 09:32:43 idk 09:33:09 really I only need one thing (being able to have a few jumps at specific places that go to parts of the code I actually write) 09:38:27 just not sure the best way to do that 09:45:12 I'm probably overthinking it 09:49:02 --- quit: dave0 (Quit: dave's not here) 10:08:22 --- join: Zarutian_HTC1 joined #forth 10:08:22 --- quit: Zarutian_HTC (Read error: Connection reset by peer) 10:42:29 --- quit: Zarutian_HTC1 (Ping timeout: 260 seconds) 11:06:45 --- quit: gravicappa (Ping timeout: 260 seconds) 11:08:25 --- join: gravicappa joined #forth 11:22:30 OK I think building a good forth assembler is beyond my abilties rn 11:22:36 I'm confused by everything lol 11:23:20 http://www.bradrodriguez.com/papers/tcjassem.txt says for compiling for another machine I should define there, tc, etc which is fine but idk where to stop that code 11:23:53 just like, have a huge CREATE [whatever] and allot 64k to it because that's the max program size? 11:23:54 I'm confused 11:45:03 --- quit: tech_exorcist (Ping timeout: 265 seconds) 12:16:33 --- join: tech_exorcist joined #forth 12:16:44 --- quit: tech_exorcist (Remote host closed the connection) 12:19:51 --- join: Zarutian_HTC joined #forth 12:19:53 --- join: tech_exorcist joined #forth 12:54:09 --- quit: tech_exorcist (Remote host closed the connection) 13:06:16 --- join: tech_exorcist joined #forth 13:09:40 --- quit: gravicappa (Ping timeout: 240 seconds) 13:10:58 --- quit: tech_exorcist (Read error: Connection reset by peer) 13:23:47 --- join: f-a joined #forth 13:46:11 --- join: tech_exorcist joined #forth 13:52:30 --- join: shmorgle joined #forth 13:56:44 --- quit: f-a (Read error: Connection reset by peer) 14:00:58 --- join: f-a joined #forth 15:06:21 --- quit: f-a (Quit: leaving) 15:37:26 Hi guys. I'm home. 15:37:42 nihilazo - going to look at that website. 15:40:44 That's a rather strange looking assembly language. 15:43:22 nihilazo: What your were told before, about the 64k buffer and so on. When you cross compile for another system, you must distinguish the stuff you mean to go to your target vs. the stuff you mean to act on your host. The 64k buffer would be intended to be a memory image of what your target's memory will look like when you load and run your program. 15:44:07 Somehow you have to specify a starting place, where your compiled code will begin. In normal Forth systems that piece of information lives in a variable DP and the word HERE does DP @. 15:44:21 For cross compiling you would have something like target_dp. 15:44:40 That's a variable in the host system, that tells you where to put the next byte of machine code in the target system image. 15:46:12 You create Forth words (that run on your host) that produce machine code bytes for the target. Whenever you execute one of those, it pokes each byte it produces into the target image location at the next location. 15:46:32 So, say you have the next byte of target assembl on the stack. You'd have something like 15:46:57 : assemble target_dp @ c! 1 target_dp +! ; 15:48:01 If you are going to need to jump somewhere in your image, you have to note down somewhere what the target is (just save the value in target_dp when that byte is generated), and then you can put that saved address into the jump instruction as the target. 15:48:16 This is really as straightforward as it can be, once you get the hang of it. 15:49:04 The hard part is understanding your target instruction set well enough to craft a set of words that will be your assembly opcodes that produce the correct bytes. 15:50:39 Usually the opcode itself is easy. In your target it looks like that produce 5 bits of your instruction byte. Then you have to also craft a lexicon for expressing the addressing mode that gives you the other three bits. You'll then type some set of words like and it will put the byte together and then it will assemble it. 15:50:53 I can try to answer questions if you have any. 16:01:56 nihilazo: In some of the earlier assembles I used way back in the day there would be an ORG directive - for origin. If your processor started executing code at address 0x200, then you'd just stick an "org 0x200" in there. The processor starts up the way it does because the hardware is designed that way, and you just "accommodate it." Give it what it wants. 16:02:17 The assembler can't figure out where to start, but it can move the pointer along correctly as you generate bytes of content. 16:04:09 It looks like the least significant 5 bits of your opcode bytes are the opcode. There's a table of them here: 16:04:11 https://wiki.xxiivv.com/site/uxambly.html 16:04:15 0x00 through 0x1F. 16:04:38 So I'd start by defining words that take their names from that table near the start of that web page - for instance, 16:04:53 : SWP 5 ; 16:05:46 So for each instruction you'll start by giving the opcode. Then you'll follow that with words that specify the address mode in some convenient way (yet to be worked out) and OR those bits into the top three bit locations of the 5-bit value you start with. 16:07:24 I haven't sussed out the address modes yet. 16:10:01 Hmmm. Looks like it's got a rather interesting way of managing the return stack. 16:16:43 Ok, so opcode bits are bits [04:00]. Bit 05 is a long/short specifier - looks like if it's set you use the top two bytes of the stack as a 16-bit address. If bit 05 is clear, you use the top one byte of the stack as a *relative* address. I guess that's relative to the instruction pointer. 16:17:49 Looks like you specify that in their suggested assembly langage by appending 2 to the opcode. So LIT or LIT2, 16:18:05 Not sure yet what the meaning of that would be for all opcodes. 16:18:35 Maybe SWP is swap th top two bytes of the stack, SWP is swap ht top two 16-bit pairs? 16:18:57 Bit 06 specifies the return stack as the target of the operation. 16:19:43 Looks like you append r to the mnemonic for that. 16:20:08 So now we can have LIT, LIT2, LITr, and LIT2r 16:29:47 nihilazo: This is rather different from Forth, even though it is a stack machine. These code bytes have an "encoded structure," where bits in the opcode bytes mean specific things. In Forth the number you lay down is an address related to where that generating word is in memory - it's just the address that particular routine happens to sit at. So there's no correllation whatsoever between the code bytes and 16:29:49 what the code bytes do. 16:30:28 Forth words that are written in machine code are usually called "primitives," and they can do absolutely anything you want them to. 16:41:58 --- quit: APic (Ping timeout: 245 seconds) 17:09:50 --- join: mark4 joined #forth 17:14:32 So it looks like it would be fairly easy to implement a bytecode interpreter for this little setup. 17:37:34 --- quit: tech_exorcist (Quit: tech_exorcist) 17:43:55 --- join: APic joined #forth 17:50:27 --- quit: APic (Ping timeout: 265 seconds) 17:56:06 nihilazo: How did you happen upon this website? It's a fairly esoteric collection of little toys. 18:41:17 --- join: boru` joined #forth 18:41:19 --- quit: boru (Disconnected by services) 18:41:22 --- nick: boru` -> boru 18:45:15 --- join: APic joined #forth 18:49:28 --- quit: APic (Ping timeout: 240 seconds) 18:50:39 --- quit: crc (Ping timeout: 250 seconds) 18:54:45 --- join: APic joined #forth 18:56:18 --- join: crc joined #forth 19:18:05 --- quit: nitrix (Quit: Genius is one percent inspiration and ninety-nine percent perspiration) 19:24:37 --- join: nitrix joined #forth 19:55:13 KipIngram, your assembler generates x86_64 asm code or actually generates binary machine op codes? 19:57:27 Oh, it generates machine code. 19:58:04 Just to be clear, it's in no way the complete instruction set. 19:58:09 Not even close. 19:58:22 But it's a decently broad swath of useful instructions. 19:59:57 The screen shot I posted earlier leaves out a small bit. It was just easy to get those two screens up together in my editor, and the "heart of it" is in there. 20:00:19 That view is of a two-block screen oriented editor in action. 20:00:36 I can use vim keystrokes to move around in those buffers and edit the content. 20:01:38 KipIngram, that's an impressive project that can generate binary code for x86_64. Very cool. Are you publishing it? 20:02:49 Not yet; that's the first I've shared it. 20:23:14 And thank you. I just started at some of the big, important (and long-historied) instructions until I could see a pattern come out. 20:24:07 I think the instruction set must have been more sensibly organized in the beginning, so the old instructions organize up better than the newer ones. 20:24:58 --- join: dave0 joined #forth 20:28:50 maw 20:29:31 Hey hey. 20:29:42 Is it done yet? ;-) 20:33:29 is anything every really done? ;-) 20:33:37 * dave0 all philosophical 20:35:20 but to answer your question... no it's not :-p 20:35:39 i'm cleaning up some code and wrestling with gcc 20:36:21 i want my code to run on a DOS.COM file 20:36:32 eventually it will become a boot loader 20:36:45 because forth seems perfect for a boot loader 20:37:49 tiny code, and if there's a boot failure, i can drop into the REPL so the computer is still useable 20:44:00 I was joking - it's a bit of work you're looking at. 20:46:16 lol okay :-) 20:46:45 i'm trying to get gcc to produce a dos file to run under dosbox 20:49:08 That's not something it does? 20:59:29 i did it with command line switches and it's a bit of a hack 20:59:50 i'm going through the documentation on the gnu linker to make a script for it 20:59:56 (i'm running on NetBSD) 21:05:42 --- quit: mark4 (Ping timeout: 246 seconds) 21:10:42 ficl is used as a boot loader for I think one of the OpenSolaris based installers 21:14:25 I really like the idea of a Forth bootloader. 21:14:43 I've contemplated trying to make mine a reasonable shell. 21:37:01 --- join: mark4 joined #forth 22:07:35 Here's an "entire" forth that fits into a boot loader. SectorForth - pretty cool. https://github.com/cesarblum/sectorforth 22:08:03 dave0, KipIngram FYI 22:08:21 nice 22:08:42 wait the WHOLE thing in 512 bytes? 22:08:54 Two hours into this talk is a brief overview of it: https://www.youtube.com/watch?v=SEUhcxSyTk4&t=7505s 22:09:05 dave0, yep... it's a minimalistic forth. 22:29:50 --- quit: proteus-guy (Quit: Leaving) 22:35:59 --- join: proteus-guy joined #forth 22:36:29 --- join: proteus-person joined #forth 22:36:59 --- quit: proteus-person (Remote host closed the connection) 22:43:16 --- quit: Zarutian_HTC (Remote host closed the connection) 22:46:19 --- quit: cantstanya (Ping timeout: 240 seconds) 22:53:52 --- join: cantstanya joined #forth 22:56:23 --- quit: cantstanya (Remote host closed the connection) 22:59:00 --- join: cantstanya joined #forth 23:16:33 --- join: gravicappa joined #forth 23:59:59 --- log: ended forth/21.04.04