5 ms·
Compiling to Assembly from Scratch
- ok_dad 2y agoThis is a lot of fun to read, but when I got to the point where I need to run the assembler code in the HELLO WORLD example, I cannot get GAS to work due to being on MacOS on an M2 and not being smart enough to figure out what to install and what magic incantations to run. Does anyone else know? I tried using brew to install a few of the different packages I could find, but couldn't get anything to work properly. In any case, I find it interesting to write a compiler and do want to continue with this book, so perhaps I'll just write the code on my MacBook and then transfer it to my Windows gaming PC to run it on WSL or something :)
- pjmlp 2y agoI got the ebook when it came out, and is relatively nice as ramp up into the world of compiler development.
- stonethrowaway 2y agoSpeaking of embedded systems, I have an old board, an offshoot of Zilog Z80 called Rabbit. I think recently Dave from EEVBlog took apart one of his ancient projects and I was floored to see a Rabbit. Talk about a left hook. Assuming this is Hacker News, I suspect someone probably knows what I’m talking about. The language used (called “Dynamic C”) has some unconventional additions, a kind of coroutine mechanism in addition to chaining functions to be called one after another in groups. It’s mostly C otherwise, so I suspect some macro shennanigans with interrupt vector priority for managing this coroutine stuff. Anyhow, so I’ve got a bunch of .bin files around for it, no C source code, just straight assembly output ready to be flashed. And the text and data segments are often interwoven, each fetch being resolved to data or instruction in real time by the rabbit processor. So I’ve been thinking of sitting down, going through the assembly/processor manual for the board and just writing a board simulator hoping to get it back to source code by blackbox reversing in a sense. I’d have to rummage through JEDEC for the standard used by the EEPROM to figure out what pins it’s using there and the edge triggering sequences. Once I can execute it and see what registers and GPIOs are written when, I can probably figure out the original code path. Not sure if anyone has tips or guides or suggestions here.
- Something1234 2y agoAny chance a decompiler like ghidra might get you part ways there?
- stonethrowaway 2y agoThe closest I came across was a Z80 simulator, I forget the name of it. But it allowed you to step through command by command giving you ability to query the processor state in a terminal. So I don’t know if it would be easier trying to find this, and updating it to support rabbit, vs trying to wedge something into ghidra which itself is an undertaking of a behemoth platform. As far as I know ghidra does not have Z80 support.
- Jtsummers 2y agoGhidra has Z80 support (based on the installation on my laptop), but I've never used it.
- westurner 2y agoAn Emu86.assembler.virtual_machine.Z8Machine (like MIPSMachine, RISCVMachine, and IntelMachine) could be stepped through in a notebook: https://news.ycombinator.com/item?id=41576922 https://news.ycombinator.com/item?id=41576922
- stonethrowaway 2y agoEnded up answering my own question. The Z88-DK[0] seems to be what I found. It supports most Rabbit processors, so I ran one of binaries through it and it spat out assembly my way which seems to make sense. Will have to run it through the simulator and see if I can get it to act like a microcontroller with setting voltage levels on particular pins. [0] https://github.com/z88dk/z88dk https://github.com/z88dk/z88dk
- ggorlen 2y agoAs is often the case, the title is unfortunately overloaded. I initially read this as writing code in the Scratch programming language[1] that compiles to assembly. [1]: https://en.wikipedia.org/wiki/Scratch_(programming_language) https://en.wikipedia.org/wiki/Scratch_(programming_language)
- MiguelX413 2y agoI also misunderstood it in that manner.
- deleted 2y ago[deleted]
- userbinator 2y agoGiven that we've seen things like C compilers written in Bash[1] and TLS libraries in Visual Basic[2], I think it's only a matter of time before someone with the right skills and motivation actually does it (or writes a compiler for $language in Scratch). [1] https://github.com/otakuto/bashcc https://github.com/otakuto/bashcc [2] https://news.ycombinator.com/item?id=35882985 https://news.ycombinator.com/item?id=35882985
- __MatrixMan__ 2y agoMe also. The actual thing is probably pretty cool, but now that my hopes were up I'm finding it insufficiently whimsical.
- ithkuil 2y agoIronically the word "overloaded" is overloaded too.
- hyperbolablabla 2y agoYes, capitalisation of scratch was incredibly misleading in this case. It's easily checkable but slightly annoying. Hard to avoid though!
- HumblyTossed 2y agoEven thought the S in Scratch is uppered, I still read it correctly.
- hirvi74 2y agoGod, the title reminds me of when I when I took an x86 assembly class in college about a decade ago. Only 6 of the dumbest souls in the CS program dared to take the class the semester. The professor for the class was an ex-NASA computer engineer. Our test used to be writing assembly by hand. We were graded for accuracy too. I swear, at that point in time, I could convert between Hex, Dec, Oct, and Binary almost without thinking. I made a D in class with 40+ hours a week of studying. However, I learned more in that one class than my entire degree. Anyway, thank you, OP, for sharing this. I have been looking into picking up ARM as way to crawl out of burnout from my career. It's been a years since I even touched x86 with any seriousness. I will add this book to my list resources.
- mbonnet 2y agoI took a class called Computer Architecture in 2019 that was half Armv7 assembly programming. The tests were handwritten. It set me up for so much success in my subsequent career of embedded flight software. I have also never again reached the high water mark of my programming life, which happened in that class - entering a 10-second ascended state and writing a 60-line complex assembly function in one go, no backspaces, no changes, and it working perfectly.
- alok-g 2y agoEver tried writing machine code (not assembly) by hand? I used to do that a few decades back for an 8-bit microprocessor. I am still looking for good resources on how to do that for a modern processor.
- ReleaseCandidat 2y agoYou look up the opcodes for each assembler instructions in the ISA specifications, like https://www2.eecs.berkeley.edu/Pubs/TechRpts/2016/EECS-2016-118.pdf https://www2.eecs.berkeley.edu/Pubs/TechRpts/2016/EECS-2016-.... Information about the machine code format starts at "2.2 Base Instruction Formats". The actual opcodes you can find in chapter 9,"RV32/64G Instruction Set Listings". But be aware that some assembler instructions (called e.g. pseudo instructions) generate more than one. The linked document is an old one, current ones are at https://riscv.org/technical/specifications/ https://riscv.org/technical/specifications/
- neuroelectron 2y agoCtrl-F "bootstrap" zero hits. That seems strange.
- ReleaseCandidat 2y agoFor a "first" compiler? No, not at all.
- evnix 2y agoI really liked how short and concise these chapters are. What took me months of effort has been condensed to these few chapters and It's well worth the read. Though Why use 32bit instead of 64, why add so much friction for a first time learner.
- halst 2y agoARM32 is much simpler to explain compared to ARM64. Registers are so much simpler, conditional execution is orthogonal, three-operand form is consistent. ARM64 made all the right practical choices, but has doubled the complexity. Still much better than x86 with its 10x complexity. ARM32 is a gem, in my opinion. A truly simple instruction set, and easy to get your hands on with Raspberry Pi or emulation.
- pjc50 2y agoWas slightly assuming from the title that this would be something like "you have brought up a new machine with no tooling whatsoever; how do you bootstrap up to an assembler and your first real language?" such as the PDP-11 front panel toggles. But this version is probably more useful.
- Joker_vD 2y agoWait a bloody second. Why does GAS looks like this for ARM: push {ip, lr} ldr r0, =hello bl printf mov r0, #41 add r0, r0, #1 // Increment pop {ip, lr} bx lr str r0, [r1] /* M[r1] = r0; */ ldr r0, [r1] /* r0 = M[r1]; */ str r0, [r1, #8] /* M[r1 + 8] = r0; */ ldr r0, [r1, #8] /* r0 = M[r1 + 8]; */ str r0, [r1, -r2] /* M[r1 - r2] = r0; */ ldr r0, [r1, -r2] /* r0 = M[r1 - r2]; */ with the destination on the left-hand side, with no "%" before the register names, and with the square brackets for addresses (with relatively sane looking expressions inside those brackets) — basically the same syntax that ARM's own assembler uses, — while x86 gets some absolutely unhinged syntax that looks like it just fell out of the sky (or an abyss for that matter) since it has almost no relation to what's written in the Intel's docs? I always assumed that GAS used some "unified" style for all its targets and disregarded the conventions of the CPU manufacturers but apparently no, it only did that for x86?
- halst 2y agoSuch a sensible syntax, right? The official ARM docs use it too. Not even sure who invented it, ARM or GAS. Anyway, that's another good reason to start with ARM. There's also legacy ARMASM syntax that is barely worth mentioning.
- kragen 2y agoas i understand it, for x86 gas had to be compatible with vendor assemblers that used shitty at&t assembly syntax, but on arm it had to be compatible with arm's assemblers instead btw try .intel_syntax noprefix
- notepad0x90 2y agoit isn't GAS but at&t that I think you're thinking of. but the difference between at&t (with the percent and dest on right) and intel is so minimal, it isn't worth getting frustrated much over, at least in my opinion. Arm can get a bit gnarly too. that bx lr is attempting to switch between arm32 and thumb based on the MSB of 'ip' based on the pop prior. the 'str' is moving data from left to right, but the ldr is moving data from right to left. you also end up doing weird and cumbersome things sometimes because of the instruction width limitations. I think arm64 looks and is much nicer than arm32 and thumb.