3 ms·
Sorry, I find this quite confusing. I'm familiar with more than one assembly language and SubX -- to the extent I can follow the docs -- seems excessively compl
by fernly 6y ago
Sorry, I find this quite confusing. I'm familiar with more than one assembly language and SubX -- to the extent I can follow the docs -- seems excessively complicated and inconsistent, compared to a conventional one. Actually this may just be bad documentation. Turning to the list of opcodes[1], which exactly are the opcodes in,
01: add r32 to rm32 (add)
03: add rm32 to r32 (add)
05: add imm32 to EAX (add)
....etc
Is "01:" the opcode? Meaning we should memorize the hex values that it is the normal assembler's job to produce? And how does something like
bb: copy imm32 to EBX (mov)
relate to the example code
bb/copy-to-ebx 1/imm32
If "bb" is the opcode, why does it need to be repeated as text (metadata?) saying the same thing, only in a different order to the table? If the way to write a "bb" instruction is the above, what is the way to write an "0f" instruction?
0f 86: jump disp32 bytes away if lesser or equal (addr, float), if ZF is set or CF is set (jcc/jbe/jna)
I mean I'm guessing it would start "0f/" but after that, how much gets repeated and with what metadata?
[1] https://github.com/akkartik/mu/blob/main/subx_opcodes https://github.com/akkartik/mu/blob/main/subx_opcodes
- akkartik 6y agoYeah, OP is probably not the best place to understand what the purpose of this project is. The list of opcodes is just a list for consulting. It's only about the opcodes, it says nothing about the expected arguments and so on. To understand how to invoke an opcode you'd have to read either the forbidding Intel manual or something terser like https://c9x.me/x86 https://c9x.me/x86 as cited at the bottom of OP. The '/copy-to-ebx' after the slashes is just my way of helping the reader understand what the instruction does. I don't want the reader to have to consult the Intel manual for every instruction, even if I'm forcing the writer to do so. So why am I forcing the writer to do so? Mu's goal is to build a computer where compound things can be understood in terms of their constituent parts. Most assemblers are implemented in C, and if you wanted to understand what a line of C does, in a specific context, you might imagine expanding the C into.. its generated Assembly. Now you're in a circular situation where you need to understand Assembly to understand Assembly. So I started out with the goal of implementing an assembler in machine code. And Assembly is surprisingly complex. There's a reason nobody builds it in C anymore. So I ended up on my current trajectory, of making the code writer do more work just so the code reader doesn't have to deal with cycles. With hindsight, it all feels quite inevitable and fore-ordained. You can read more in a 2-part blog post that starts at http://akkartik.name/post/mu-2019-1 http://akkartik.name/post/mu-2019-1, and there's also an academic paper at http://akkartik.name/akkartik-convivial-20200607.pdf http://akkartik.name/akkartik-convivial-20200607.pdf that goes into some of my sociopolitical goals (in a sentence: "everybody should spend some time auditing the software (and laws) that run their society". For a paragraph-length exposition see the top of https://github.com/akkartik/mu#readme https://github.com/akkartik/mu#readme.)
- asrp 6y agoSorry if I've asked these years ago and just don't remember the answer. > The '/copy-to-ebx' after the slashes is just my way of helping the reader understand what the instruction does. I don't want the reader to have to consult the Intel manual for every instruction, even if I'm forcing the writer to do so. Why not make the comment the instruction and the bytes the (maybe even optional?) comment in that case then? From your first post. > The fact that C compilers are written in C contributes a lot of the complexity that makes compilers black magic to most people. Isn't this more a symptom of C though? I'm hoping this is generally not true if you replace C with other languages (but could be very wrong). But more generally, I'm thinking you could make "the compiler's inner workings is not black magic" a constraint rather than make not writing the higher level language in the higher level language the constraint. In my case, I tried that first route and then moved to instead having the compiler written in the higher level language but emitting output that's close enough to (my) handwritten lower level language. I'll have to read your two part post more carefully though. Glad to see this project getting some attention, even though in an unusual fashion.
- akkartik 6y agoGreat questions! I've actually never considered putting the comment first! I'll have to think about that one. You're right to point out that there are two components to "C compilers written in C make compilers seem complex": the metacircularity, and C-specific difficulties. I think I was focusing on the first when I wrote that, but I can't exclude the possibility you raise. A better language might reduce the need to understand it operationally, by looking under the hood to understand what a line of code is translated to. The Mu way may well be a dead end, since the requirement of understanding translated code restricts how complex compiler optimizations can get. You probably don't want to understand Haskell's loop fusion by comparing source and generated code. In my mind there's an idea maze where there are 3 major possibilities for improving the future of software: a) Simple languages and translators that are easy to understand by running them. This is the Mu way. b) Type-driven languages that are easy to understand by reading them. Haskell and OCaml seem to fit here, and they may well be the right answers. c) Complex languages that discourage abstractions atop them. This is the APL way, and it too might end up being the right way. I'm doing a) mostly because it seems to fit my brain better. I just can't seem to get into Haskell or OCaml or APL.