flat assembler
Message board for the users of flat assembler.
![]() |
Author |
|
Hugh-Aguilar 04 Apr 2021, 03:58
Well, I wrote an assembler for the MSP430.
I previously began work on Simple51 for the 8051 in FASM but gave up on that because FASM is too much work, and the 8051 is pretty much obsolete. My MSP430 assembler called HJA430 is written in VFX. It was pretty straight-forward. I attached the documentation, if anybody is interested. I have yet to test the code on an actual MSP430. I just looked at the code generated, and it seems to conform to what I expect. Some aspects of the MSP430 are just a guess though. For example, if the source is immediate (PC)+ and the destination is symbolic nnn(PC) I am assuming that the PC gets incremented by 2 after the effective address of the destination is calculated by adding PC to nnn. This is just a guess though. As another example, I am assuming that the source operand (such as for symbolic or absolute addressing-mode) is prior to the destination operand (such as for symbolic or absolute addressing-mode). This seems logical because the source is prior to the destination in the source-code, but I'm just guessing. All of these questions could be answered if I had RTL for the MSP430. Is this available anywhere? I assume that there is an MSP430 assembler written in FASM/G -- if so, how did you answer these questions? Is there a simulator available for the MSP430?
_________________ When all else fails, write the source. |
|||||||||||
![]() |
|
revolution 25 Apr 2021, 08:12
We all have different interests and use cases.
So far you are the first to post anything about the MSP430. It might be that your post inspires someone else to take an interest. That would make you the pioneer for others to follow. |
|||
![]() |
|
Hugh-Aguilar 25 Apr 2021, 17:59
revolution wrote: We all have different interests and use cases. I don't want others to follow me --- that is why I don't provide source-code. _________________ When all else fails, write the source. |
|||
![]() |
|
Hugh-Aguilar 02 May 2021, 20:16
Hugh-Aguilar wrote:
The Safety Forth project is still in the works. When that is complete, I will be able to post code such as HJA430 closed-source. People would be able to use HJA430 for developing MSP430 programs, but they wouldn't be able to do a hostile-fork on HJA430 itself. So I would have users, but I would not have followers --- the problem with followers is that they aspire to be leaders, and pretty quickly with minimal work on their part --- by comparison, users don't normally cause much trouble, except for their tendency to ask dumb questions without first reading the manual. HJA430 is written in VFX anyway, so it is not a FASM program. I used my novice-package when writing HJA430, which made the project pretty easy. I rely heavily on linked lists for intermediate data storage. This requires a heap, because the linked list nodes get allocated in the heap and then, when the list is no longer needed, they get deallocated. I have rquotations that get defined in a parent function and the rq (execution token) gets passed into a HOF (higher-order function). The HOF iterates through the list and executes the RQ for every node. The rquotation has access to the parent function's local variables, despite the fact that the HOF has local variables of its own (the rquotation can't have any local variables of its own; it has to use the parent function's local variables). FASM doesn't have a heap, or rquotations. Because of this, porting HJA430 to FASM would be complicated. This can be done though. A good trick for assembling forward references to an unsettled label, is to use the operand of the JMP as a link in a list. The unsettled label has a pointer that is NIL if there are no forward references yet, or is a pointer to the first JMP operand if there is a forward reference. This JMP's operand is NIL if there aren't any more forward references, or it is a pointer to the next JMP operand if there is a forward reference. This would be pretty complicated to do in HJA430 because there are multiple ways to reference an unsettled label. * Conditional jumps can only use 10-bit relative. * The unconditional JMP can use 10-bit relative, 16-bit relative or 16-bit absolute. * The CALL can use 16-bit relative or 16-bit absolute. With rquotations and a linked-list, all of this information about what kind of reference it is, can be stored in the list node. Using the old trick with linking the JMP operands worked well when all of the JMPs used the same addressing mode. It doesn't work so well when the forward references can be of multiple different addressing-modes because there is no place to store this information. Also, the code-blocks have a list of lists. The first node is the first level, the second node is the second level, etc.. Each node is a list of forward references that have to be resolved when the code block finishes with }, and this code block is then removed from the list of lists so that what was the second node is now the first level. So, I could port HJA430 to FASM, but the result would be a much bigger and more complicated program, due to not having a heap and rquotations, etc.. Another problem with porting HJA430 to FASM, is that it would no longer have a macro language. HJA430 written in Forth automatically uses Forth as the macro language. If HJA430 were written in FASM, then it would be necessary for me to write an interpreter for a mini-language that would then be used as the macro language --- if I'm going to write an interpreter though, then I might as well write a Forth system and just keep HJA430 in Forth. So, lots of ideas are possible. I really chose a super-simple technique, of just writing HJA430 in Forth. Considering that this is a fun project and I'm not getting paid, why would I do anything other than the most simple technique? I haven't yet looked at FASM/G. I doubt that it provides the resources needed for code blocks though. If it has a macro language, I doubt that it is capable of doing things such as adding a pre-decrement addressing-mode, which was trivial in HJA430. I'm not really into learning other people's software, such as FASM/G --- I mostly just program in Forth because I learned that way back in 1984, and it still works --- I almost never learn anything new. I posted this on the assumption that the FASM crowd is interested in how assemblers work internally. Nobody has yet responded to this thread though, so it is possible that nobody is interested in the subject, or that everybody thinks that they already know more about the subject than I do. _________________ When all else fails, write the source. |
|||
![]() |
|
Hugh-Aguilar 02 May 2021, 22:10
Hugh-Aguilar wrote: A good trick for assembling forward references to an unsettled label, is to use the operand of the JMP as a link in a list. The unsettled label has a pointer that is NIL if there are no forward references yet, or is a pointer to the first JMP operand if there is a forward reference. This JMP's operand is NIL if there aren't any more forward references, or it is a pointer to the next JMP operand if there is a forward reference. ... I recall using this trick in a 65c02 assembler. All of the forward jumps were 8-bit relative, so I just stuffed each operand with an 8-bit offset to the next operand. I didn't support forward JSR because that doesn't help with structured control-flow, which was the goal. For the MiniForth assembler, none of this is relevant because the MiniForth did not have jumps or branches or calls --- it did not have any way to change the PC except with the NXT instruction --- all control-flow was at the Forth level, but there was no way to change control-flow inside of a primitive except to march forward until you eventually get to the NXT instruction that terminates the primitive. I think this aspect of the MiniForth weirds people out (I know it had that effect on me); there are no loops or conditional execution inside of a primitive, but each primitive just executes straight through until the NXT at the end (it was possible to conditionally load a register, similar to the CMOV instruction in x86). _________________ When all else fails, write the source. |
|||
![]() |
|
Hugh-Aguilar 07 Aug 2021, 03:06
Hugh-Aguilar wrote: ...the MiniForth did not have jumps or branches or calls --- it did not have any way to change the PC except with the NXT instruction --- all control-flow was at the Forth level, but there was no way to change control-flow inside of a primitive except to march forward until you eventually get to the NXT instruction that terminates the primitive. I think this aspect of the MiniForth weirds people out (I know it had that effect on me); there are no loops or conditional execution inside of a primitive, but each primitive just executes straight through until the NXT at the end (it was possible to conditionally load a register, similar to the CMOV instruction in x86). I will post here the description of my TOYF processor that is loosely based on the MiniForth processor (they are both VLIW and oriented toward Forth). Once again, I won't post source-code --- I'm done with giving away source-code --- I don't want 'followers' who say: "When all else fails, steal the source." I'm interested in writing assemblers. My MFX for the MiniForth, and my assembler for the TOYF, are both examples of assemblers that can't be done with FASM/G (but for a different reason than why HJA430 can't be done with FASM/G).
_________________ When all else fails, write the source. |
|||||||||||
![]() |
|
Hugh-Aguilar 15 Jan 2022, 02:44
Hugh-Aguilar wrote:
Well, I'm quite amazed that my MSP430 assembler documentation has been downloaded 205 times and this TOYF documentation has been downloaded 125 times. Most likely this is Red China trying to find something that they can use --- the commies are always lurking on forums such as this --- they rely heavily on stealing our technology because the communist social-system does not reward innovation. I'm reading the book: "To Engineer is Human" (Henry Petroski). He discusses the collapse of the Kansas City Hyatt Regency walkways in 1981, in which 114 people were killed and almost 200 injured. He says: Quote: But explaining what went wrong with the Hyatt Regency walkways and pointing out changes that would have worked, is a lot easier than catching a mistake in a design yet to be realized. After the fact there is a well-defined "puzzle" to solve to show how clever one is. Before the fact one must ... define the design "puzzle" ... This was the case with the MFX assembler. I was never told that the "puzzle" was to out-of-order the instructions. I was told to write the assembler such that the programmer put all of the instructions on each row that would execute in parallel, such that each row of source-code represented one opcode, and the rows just executed sequentially from top to bottom as in any assembler. This would have put the burden of out-of-ordering the instructions entirely on the programmers' unmuscled shoulders, which would have resulted in there not being any programmers (me neither, as I'm not smart enough to do that in my head any more than anybody else is). The project would have failed because few or none of the primitives would have gotten written. Bummer! I would not have taken the blame though, because I just did what I was directed to do --- what I actually did was not what I was directed to do, but instead I defined the puzzle and solved it --- the assembly-language programmer could write his source-code as if the instructions executed sequentially; the business of out-of-ordering the instructions and packing multiple instructions into each opcode would be done under the hood, with the assembly-language programmer not needing to know how this was done, or even know that this was done. This worked well. The MiniForth (built in a Lattice isp1048 PLD) was used in the motion-control board for a laser-etching machine --- the board (the Lattice PLD plus an 8032 helper) cost less and out-performed the competitor's board that used an MC68000 programmed in C (this was in 1994 before the ARM Cortex became dominant, at a time when it was still possible to be innovative and compete successfully with the mainstream processors). My algorithm that I invented for out-of-ordering the instructions is described in the TOYF document. It is not a complicated algorithm. Any reasonably smart programmer can understand this algorithm with a little bit of thought. Any reasonably competent programmer can implement this algorithm (you need to know how to implement a linked list, but that is easy, and that has already been provided in myriad code-libraries). After the fact, it is easy to say: "Anybody could have invented this algorithm and implemented it --- this is kindergarten-level programming." This is why inventing is a bad idea at a job, unless you are the boss --- you will never get praised! If you succeed, many maintenance programmers will take credit. At best you will be described as an early pioneer, but even that much credit is unlikely. Most likely, you will get fired because you are standing in the way of progress. If you fail, of course, you alone will take the blame! You are definitely getting fired in this case. Our capitalist social-system doesn't reward innovation either. P.S. I interviewed at Lockheed Martin to work on their VLIW processor that was used for turning radar-data into images. They don't have an assembler to do the out-of-ordering automatically. They were programming in a spreadsheet with each row representing one opcode and each cell containing an instruction all of which would execute in parallel. I didn't get the job. They seemed to not understand what I was telling them, that this out-of-ordering could be done automatically by the assembler. It is also possible that they did understand this but, like modern-day Luddites, they wanted to continue to get paid by the hour to do this manually. I have never heard of anybody else building a VLIW processor. P.P.S. I knew about out-of-ordering because I had read Abrash's book about the Pentium processor with its U and V pipes, and how it did out-of-ordering at run-time. The MiniForth was more complicated because it had five instructions per opcode executing in parallel, rather than the Pentium's two instructions (U and V). The MiniForth was easier though, because I did the out-of-ordering at compile-time with a Forth program, rather than at run-time with hardware. _________________ When all else fails, write the source. |
|||
![]() |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2023, Tomasz Grysztar. Also on GitHub, YouTube, Twitter.
Website powered by rwasa.