Live data from Hacker News

Compiling to Assembly from Scratch

keleshev.com

41–50 of 51 posts

Re: Compiling to Assembly from Scratch

#41
post #35
post #12

God, 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 witho…

this could be easy or hard depending on what you had to write in assembly on the test. like it wouldn't be that hard to write a subroutine to add up an array of integers or something addem: xor eax, eax loop: test ecx, ecx jnz ok ret ok: add eax, [ebx + ecx * 4] dec ecx jmp loop (i haven't tested this, it'd be hilarious if i got it wrong)

The assembly on the test was much larger than the snippet you provided. I wish a kept a copy of the old test so I could just copy and example problem. Honestly though, that wasn't the worst part of the tests. It was the most dangerous though because many of the questions/instructions relied on previously completed questions/instruction to be correct.

So, like if you passed a wrong value to a certain register, then downstream, every problem that used that register would be off.

The tests were often 4 pages front and back with the handwritten assembly, definition matching, word problems, essay responses, etc.. We had like 75 minutes to take the test too. This was all at a public, no-name state university too. I was no MIT student or anything.

Anyway, I'll never forget the first day of class. Our professor said we were to have 4 tests and a final and some labs.

My friend in the class: "If we make a 100 on all 4 tests, do we have to take the final?"

The professor: "Hell, if you make 100 on 4 test, then I will let you write the final."

My friend: "Why? Has no one ever done that before?"

Professor: "No, in fact, in the 20 years I have taught this class, no one has ever scored a 100 on any test."

We all knew we were in for hell after that.

Re: Compiling to Assembly from Scratch

#42
post #41
post #35

Earlier quoted context omitted.

this could be easy or hard depending on what you had to write in assembly on the test. like it wouldn't be that hard to write a subroutine to add up an array of integers or something addem: xor eax, eax loop: test ecx, ecx jnz ok ret ok: add eax, [ebx + ecx * 4] dec ecx jmp loop (i haven't tested this, it'd be hilarious if i got it wrong)

The assembly on the test was much larger than the snippet you provided. I wish a kept a copy of the old test so I could just copy and example problem. Honestly though, that wasn't the worst part of the tests. It was the most dangerous though because many of the questions/instructions relied on previously completed questions/instruction to be correct. So, like if you passed a wrong value to a certain register, then do…

that's awesome! i wish you'd kept a copy too

Re: Compiling to Assembly from Scratch

#43
post #25

Earlier quoted context omitted.

SubX seems like an assembly language itself following a subset of x86 32-bit instructions. Would looking into this help me understand how to translate from assembly to machine code manually? Thanks.

SubX is a weird thing (I built it) that is somewhere between machine code and Assembly language. You have to type in the opcodes directly, which people typically associate with machine code. But it smooths some aspects of programming in machine code. You'll get nice errors if you accidentally write invalid machine code, it won't just go off and run data as code or something like that. I'd be happy to support you if y…

Thanks! I understand better now.

And that cheat sheet PDF is cool, exactly what I was looking for. Any chance you are aware of something similar for x64? Thanks.

Re: Compiling to Assembly from Scratch

#44
Wait 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?

Re: Compiling to Assembly from Scratch

#45

Wait 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 si…

Such 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.

Re: Compiling to Assembly from Scratch

#46
post #43

Earlier quoted context omitted.

SubX is a weird thing (I built it) that is somewhere between machine code and Assembly language. You have to type in the opcodes directly, which people typically associate with machine code. But it smooths some aspects of programming in machine code. You'll get nice errors if you accidentally write invalid machine code, it won't just go off and run data as code or something like that. I'd be happy to support you if y…

Thanks! I understand better now. And that cheat sheet PDF is cool, exactly what I was looking for. Any chance you are aware of something similar for x64? Thanks.

No, sorry. Honestly I spent a long time going to the source of the 3-volume Intel manual. (There's link to them as well in my Readme.) I think that's really what you need to do for machine code, if you're not using Assembly or Assembly-ish that has done that work for you. But then any Assembly language will have its own manual you need to bone up on.. That's mostly why I built SubX: the manual is like 10 pages, and I distilled down the parts of the Intel manual you need to know. But yeah, only for 32-bit. I always found x64 very hacky with the register bits split up between bytes and whatnot. 32-bit is a legitimately nice ergonomic machine.

Re: Compiling to Assembly from Scratch

#47

Wait 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 si…

as 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

Re: Compiling to Assembly from Scratch

#48

Wait 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 si…

it 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.

Re: Compiling to Assembly from Scratch

#49
post #12

God, 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 witho…

I 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.

Re: Compiling to Assembly from Scratch

#50
This 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 :)

Post reply on HN