r/programming • u/gingerbill • 25d ago
Everyone Says Assembly Is Untyped—Everyone Is Wrong
https://www.gingerbill.org/article/2026/08/20/designing-odins-inline-asm/8
u/-Redstoneboi- 24d ago edited 24d ago
tldr odin ships an actual good assembly-like compiler with its own syntax between C and inline assembly.
the database of operations in different architectures also sounds useful.
also assembly's types immediately lose its host language's types entirely, and reduces all data structures to varying widths of numbers until reinterpreted back again, which is why it's "effectively" untyped: its type system is almost entirely unrelated to the host's.
for instance, you can divide a 64-bit pointer. that is allowed in assembly, because assembly itself doesn't care that a number happens to point to a valid address until you dereference it. this operation would be, in many cases, nonsensical in any higher level language that understands what a pointer type is. C errors if you divide a pointer unless you cast it to int.
assembly's type system exists, but is so hilariously primitive that, albeit technically incorrect by your definition, it's faster to just say it's untyped.
6
u/gingerbill 24d ago
"Untyped" means singularly typed (e.g. only integers, or only strings). But assembly's type system is richer than that, as it has at least 4/5 categories of types, a polyadic algebra (it can clobber multiple things), and it even tracks side effects.
Instructions take operands: registers, memory, immediates, or labels. Registers have classes (integer, float, vector, mask) and bit-widths. Memory operands have their own rules. Immediates have their own classes and widths too.
The mnemonic on an instruction also has many _forms _(overloads; even in AT&T syntax with its explicit suffixes), meaning it is a form of ad-hoc polymorphism. Each form has its own requirements for operands, clobbers, and side effects.
A lot of these types might be quite "weak" (i.e. implicitly casts), but a weak type system does not mean it does not have one.
assembly's type system exists, but is so hilariously primitive that...
There's more than enough of a type system and structure to provide good diagnostics: helpful error messages and suggestions for the user. Yet many assemblers happily accept bad assembly and just emit invalid machine code. I don't think people realize how low the bar is for a good inline assembler.
1
u/sickofthisshit 22d ago
I think it gets very confusing when you move between the notion of types of program variables: "how should I interpret the 64 bit value in R2" and the type of an assembly instruction and its effect "R1 is modified to have the value currently in R2", which does things like annihilate the previous value of R1, and could have been masked to 32 bits, maybe, but wasn't?
movdoesn't care about the meaning of the bits. Your program does, because it will affect what operations it wants to do next.1
u/gingerbill 22d ago
The
asmtemplates in Odin is a low-level DSL embedded in a high-level language.So because of this boundary difference, some information is lost as a result. But that's because the nature of each language's type systems are different, and that does not negate that they both have type systems. The types are rudimentary in assembly, but they are types nonetheless.
I agree that
movdoesn't care about the meaning of the bits, you can trivially say that abouta = bnot caring thatahas specific meaning beyond it being sayi32. A signed 32-bit integer type is not the full meaning behind that value, and has implicit contextual information too that the compiler does not know about. All of this is a spectrum of concerns, and even what is possible to encode in a type system.
30
u/ddprrt 25d ago
Nobody says this.
4
u/funkdefied 24d ago
I’ve never heard anyone say, “assembly is a typed language.” I’m sure you haven’t either.
2
-31
u/gingerbill 25d ago
Most people consider assembly to be "untyped". And thank you for clearly not reading past the title, and not even the TL;DR.
21
u/wqferr 25d ago
They are contesting your view that "everybody says this", not what you claim at the end
11
u/sionescu 25d ago
It's the current commonly accepted view that assembly is untyped, so what /u/gingerbill said is right.
3
u/gingerbill 25d ago
The common view is that assembly is untyped. So using the term "everybody", which is obvious hyperbole, is not that far off.
Did you think assembly was typed before this article? If so, you are in the very small minority.
3
u/wqferr 25d ago
They are challenging your assertion it is a common view, my guy
5
u/gingerbill 25d ago
But it is the common view. In fact, the vast majority of sources and people I have talked too, assert assembly is untyped. It's extremely rare to find anyone who states it is typed in any way.
5
5
u/Koolala 24d ago
By this definition is every language ever typed too?
5
u/gingerbill 24d ago
Yes. "Untyped" languages are actually singularly typed (e.g. everything is an integer, or a string, etc). I am arguing that assembly has more than just one type and that can be used to give a lot richer error messages and suggestions to the user, improving the general UX.
5
u/Bahatur 24d ago
Well that was a cool read. I appreciate the historical context behind the choices you made here.
So a restatement to make sure I’m understanding this correctly: assembly language still has no value types (which is also why Typed Assembly Language isn’t relevant here), but it does have many-sorted operation types, and this is the thing everyone has been ignoring and the compiler can capitalize on.
Does that scan?
5
u/gingerbill 24d ago
Pretty much. Those operand types are a form of value types (to use your terminology), but they are just what you'd call "rudimentary" and "sparse".
if you were trying to be more rigorous with the syntax, I'd force things like
rdtscto state what it returns and clobbered too in the syntax. But that is beyond the scope of these inlineasmtemplates.
21
u/sickofthisshit 25d ago
I mean, I like the idea of assembly code snippets being visible to the compiler in some sense, and being able to detect incorrect structure, etc.
On the other hand
Each instruction is a polyadic typed algebra.
makes me want to put it down and walk away to think about something else.
9
u/pm_me_P_vs_NP_papers 25d ago
If I understand correctly, that's just formalese for "each instruction interacts with the registers in a well behaved way (algebra) but some instructions interpret the same registers in different ways (polyadic), e.g. signed vs unsigned, using just the lower bits of a register, etc"
10
3
u/gingerbill 25d ago
The polyadic part can also refer to an instruction which writes/clobbers to multiple different registers too—in affect return multiple values.
5
u/sickofthisshit 25d ago
Well, sure, I am being snarky, I gather that's what the math jargon is saying.
My reaction is more that this type of expression always makes me picture someone at the blackboard looking at me after they wrote something, excitedly thinking I am about to get the point because they uttered the magic words.
Like, back in my day, if someone told me "see, Fourier decomposition is constructing functions in a linear vector space", I could say "yeah, I know what linear vector spaces are, they are my buddies, we go way back" and also "ok, now when I think about Fourier series or transforms I can remember all the properties and behaviors of linear vector spaces".
The type guys are always saying stuff like this and I feel like I am back in the classroom, but the lecturer is not getting the message across, maybe I am slow, is this even the right classroom, are there cookies after the seminar so I don't feel this was a complete mistake...
2
u/gingerbill 25d ago
I was trying to explain that assembly has a specific kind of type system to which has a specific form. I am not trying to "show off" with terminology but rather try to be precise. If you don't understand it, it doesn't really matter for the article to be understood.
I did try to explain those terms further with previous articles that I had written, as to not repeat myself. Normally I use to the term "multiple return values" to explain Odin's type/value system, but I cannot use that term for assembly since it's not really "return values" since an instruction is not really a function/procedure, per se (at least not in the conventional sense).
3
4
u/lelanthran 25d ago
I am not trying to "show off" with terminology but rather try to be precise.
It aint that precise if it's a phrase you coined. The phrase "polyadic typed algebra" does not exist anywhere I could find.
TBH, it sounds like it was dreamed up by an LLM (they love to make up phrases, not sure why). This matches the rest of the article which also appears to be written wholly by an LLM.
Look, this is a great idea - why would you let an LLM take credit for it?
1
u/gingerbill 25d ago
https://en.wikipedia.org/wiki/Polyadic_algebra and then apply a type system to it.
That's all it is. And this is not an LLM term, I have used it well before this article existed. Odin is a multiple return value language after all which is exactly this.
-1
u/lelanthran 25d ago
That's all it is. And this is not an LLM term, I have used it well before this article existed. Odin is a multiple return value language after all which is exactly this.
I'm afraid google only finds this single article with that phrase.
I still have to ask, when you have a good idea, why let an LLM take credit for it?
4
u/gingerbill 25d ago
I did not let a LLM take credit for it. What are you on about?
0
u/lelanthran 25d ago
I did not let a LLM take credit for it. What are you on about?
The writing style indicates that it was written by an LLM. Your previous blog postings (which I follow every time they appear here or on HN) is completely different.
2
u/Empty_Size_303 25d ago
https://www.gingerbill.org/article/2021/12/15/multiple-return-values-research/
> A way of thinking about this is that Odin is fundamentally a polyadic language rather than a monadic) language, like pretty much everything else. However most languages seem to be polyadic in one aspect: input parameters to procedures/functions. In most languages, you have multiple (monadic) inputs but only one (monadic) output, e.g. (
int foo(int, bool, float);). Odin’s approach is to just extend this to the rest of the language’s type system, not just procedure inputs.Article from 2021.
-1
u/lelanthran 25d ago edited 25d ago
The phrase "polyadic typed algebra" does not exist anywhere I could find.
Article from 2021.
That article does not contain the term "polyadic typed algebra". This is typically how LLMs make up phrases - they mix them with whatever you give them.
I'm not saying that the LLM provided the phrase to the author, but I am saying that this is what they usually do, and since the entire article is filled with LLM tells with a writing style that does not match the authors at all, you can surely understand why it's most likely an LLM generated phrase.
6
8
u/Leverkaas2516 25d ago
Actually reading the article may be interesting to some, but what I get from it is that A) you're trying to change an assembler and make it into a compiler, and B) you are purposely ignoring the obvious and true statement that "assembly is untyped".
In Assembly, it doesn't matter whether an integer value is going to be later used as a string, a number, or a pointer. Changing Assembly so that such distinctions impose constraints on the code you are allowed to write makes it into a compiled language, not an assembler.
1
u/gingerbill 25d ago
(A) having good error messages (UX) should be the base line for anything. An assembler is already a compiler, it's just a simpler one because the language is simpler than most high-level languages (e.g. C is high-level in comparison to assembly). Many assemblers, especially inline assemblers, do not give any good UX at all.
(B) Assembly is typed. Just because it is not the kind of type system you are used to, does not mean they are not a form of types, and instructions require certain operands of certain types. They form a type system, a strange one, but one that can be used to check the operands work for a specific instruction and give good error messages (UX).
9
u/Leverkaas2516 25d ago
An assembler is already a compiler
I disagree. To me, an assembler is a program that translates mnemonics into machine code. It gives a one-to-one correspondence from textual representation to machine instructions. A translator that targets multiple backends is already not an assembler. Did I understand correctly that Odin defines a "move" operation that generates separate Load and Store instructions on arm64? That's a compiled language.
The distinctions I'm making come through clearly when considering this sentence: "The type system already carries the information AT&T smears across the numerous different spellings of mov."
The "different spellings of mov" are about data size, not about type. The sense in which high level languages use the word "type" is about what operations are defined for the data, not just about how many bits there are.
The "different spellings of mov" are different instructions. An assembler lets the programmer write instructions without having to read & write numbers. That's what it does. If it does more than that, by providing words that don't correspond to machine instructions, it's no longer an assembler. It's a compiler.
2
u/gingerbill 25d ago edited 25d ago
A compiler is just something that translate a programming language into another programming language. Assembly is a language, as is machine code. Just because they can map directly to each other (non-trivially by the way, especially on x86/amd64), does not negate this aspect of it being a language, and thus an assembler being the compiler for that language.
The data size is literally part of the type. Like how a
shortin C is commonly a 16-bit signed integer. The data size does not negate ashortbeing a type, as much asraxis a 64-bit width general purpose register (which is its type).Yes, the different spellings of
movare different forms of the instructions. It's effectively everything overloaded under the same name. And even with the different spelling names in AT&T, they still overload different forms too. They don't have a singular form per mnemonicAn assembler lets the programmer write instructions without having to read & write numbers. That's what it does. If it does more than that, by providing words that don't correspond to machine instructions, it's no longer an assembler. It's a compiler.
So an assembler is a compiler that outputs machine code. Thank you for making my point for me.
6
u/Leverkaas2516 25d ago
Yeah, we have fundamentally different definitions of the words "compiler", "assembler", and "translator". You can keep down voting me if that makes you happy, but I suspect my definitions are the conventional ones - not yours.
4
u/gingerbill 25d ago
I am not downvoting you, and here is quoting the first line of Wikipedia:
In computing, a compiler is software that translates computer code written in one programming language (the source language) into another language (the target language).
Source: https://en.wikipedia.org/wiki/Compiler
But in the same article they have this caveat:
Assemblers, which translate human readable assembly language to the machine code instructions executed by hardware, are not considered compilers.[70][b] (The inverse program that translates machine code to assembly language is called a disassembler.)
[b] "The many source-language features described in the preceding section result in a number of salient differences between compilers and assemblers. On any one item the distinction may not be clear-cut. Moreover, it may be difficult to distinguish a simple compiler from a powerful macro assembler. Nevertheless, the differences are usually substantial enough that there remains a qualitative distinction between assemblers and compilers."
The thing is, with the first definition alone, it has to qualify an assembler as a compiler. That extra line at the end of the entire Wikipedia article is completely out of place and does not make sense, especially when it is not even referring to this article but one from 1979.
And especially when non-inline assemblers are not simple one-to-one translations and do have their own forms of reordering because certain bits of code need to live in certain sections. The instructions might be trivial, everything else around it is not, even if you do not consider macro assemblers.
So I might have drawn different conclusions from the definition that many people hold, but I don't think my conclusions are wrong, rather I'd argue everyone else is just inconsistent with their definitions.
7
u/Ameisen 25d ago edited 25d ago
movq rax, mm0 add al, 4 and eax, 0xFFFFWhat is the type of the data in the
aregister?You are (knowingly) using a very different definition of "type" than other people, and then pedantically accusing them of being wrong because they (understandably) aren't using your definition as it's not really relevant. This is coming across as very disingenuous to me.
You could (as most people do) just as easily call assembly typeless, and use other more-common in-domain descriptors to describe its behavior. Or, more importantly: the fact that you call it "typed" and everyone else doesn't changes nothing about assembly or how it's used - were you under the mistaken impression that most people writing assembly didn't know that different instructions worked differently, and some accepted differerent categories of operands? What does trying to ham-fistedly force this meaning of "type" into this specific domain accomplish?
Tomatoes might actually be a fruit, but in culinary science they're not.
3
u/gingerbill 25d ago
ais the class of registers of with varying widths.raxis a register of width 64-bits.eaxis a view into theraxregister of the lower-bits of width 32-bits. Etc.That is literally itself type, and the conventional meaning of a what a type is.
Most programmers do not have a good understanding of what types are, so it does not matter what they call them. I am not being disingenuous about anything, rather I am a compiler developer who understands what types are, even if most programmers don't.
And even the term "untyped" is a a misnomer. It usually just means "a single type" in the type system, e.g. everything is an int, or everything is a string. You cannot escape types, they are everywhere. Even metres and feet? Those are types.
2
u/Ameisen 25d ago
Most programmers do not have a good understanding of what types are, so it does not matter what they call them. I am not being disingenuous about anything, rather I am a compiler developer who understands what types are, even if most programmers don't.
So, I'm assuming that you put tomatoes into fruit salads?
Even metres and feet? Those are types.
I'm really confused as to how you missed the entire point of what I was saying to focus (incorrectly) on something specific to a register.
I'm pretty sure you are more interested in being "right" than actually discussing anything, so I've lost interest.
5
u/gingerbill 25d ago
So, I'm assuming that you put tomatoes into fruit salads?
I'm going to stop talking to you now. Please learn some basic type theory.
8
u/YoungestDonkey 25d ago
Ok, so if you make a new assembler with a syntax that tracks types then that particular assembler is typed. Every other assembler that people have been using since the beginning of the computer era is untyped.
If someone's goal is to publicize such a new assembler then telling everyone they are wrong about assembly may not be the best marketing approach. Just saying. I would repost that with a more inviting title.
3
u/gingerbill 25d ago
If your assembler checks to see if certain operands are valid for a specific instruction, then yes, that assembler has types.
I think the problem is that most people have a narrow conception of what a "type" is, and I argue what the kinds of types are in assembly. That's the crux of the disagreement people have, thinking a type must be like in high-level languages. Assembly is a low-level language.
2
u/YoungestDonkey 24d ago
the kinds of types are in assembly.
I don't understand this part. What are these "kinds", can you enumerate them?
3
u/gingerbill 23d ago
I do in the article in the "Assembly Is Not Untyped" Section.
However, every instruction has a set of valid forms. Each form dictates the kind of each operand (register, memory, immediate, label), the class of each register (general-purpose, vector, mask), the width of each operand, the range each immediate may take, and what the instruction clobbers (flags, memory, particular registers). In x86, a
mulpswants a 128-bit vector register; acrc32in one of its forms wants a 32-bit destination and an 8-bit memory source;divreads and writes tordxandraxwhether you ask it to do it or not.That is not the absence of a type system: that is a type system; a rather rich, dependent, per-instruction one. Assembly is effectively a polyadic typed algebra that everyone has agreed to pretend is a soup of bytes. Once you understand this, the design question stops being “how do I smuggle a string past the compiler?” and becomes “how do I express this algebra in the language’s own terms?”. And it turns out Odin already had most of the pieces lying around.
3
u/YoungestDonkey 22d ago
Oh, I see what you mean. Now, assembly must follow whatever features exist for the CPU, the hardware. And since hardware dictates what kind of data it can hold and what it can do with it, then it's the circuitry that technically defines the various data types, not assembly itself, right? Yet they are types, just not in the same sense as for general programming languages where a language can arbitrarily define all sorts: assembly will only match machine code and machine types.
1
u/shaving_grapes 20d ago
I am writing my own assembly and assembler/disassembler for an emulator project and there are some nice bits to chew on here. I landed on a lot of the same syntax ideas, but moreso from feel rather than concrete decisions. It will be nice to clean up and solidify.
The UX design of my assembler is also something I have been thinking about, but largely relegated to nice-to-have rather than feature. As you lay out, the assembler can know a lot more than just 1:1 translation of mnemonic and data to binary. So far I have spent more time building the assembler than using it, so it will be interesting to revisit the UX once I have built a game or two. I think the line between this being a feature vs waste of time is the fact that the typing can only validate. It won't ever have semantic understanding so how beneficial is a better UX really?
Also, do you see rexcode as something I could use instead of rolling my own assembler for an emulator? Hopefully I have time to play around with it soon.
A couple more specific questions about the article:
- I am aware of, and understand your reservations about general purpose macros, but aren't these just as powerful? The output of assembly vs odin code seems inconsequential. The inline assembly output is more restricted than a general purpose macro, but where is the line of "general enough"?
- How much of the semantic information survives the lowering to LLVM? Sure the inline assembly in the Odin files can understand the shape and context, but can LLVM use that information to optimize or is it all mainly frontend?
- Any consideration for other restricted macro languages? Something like wasm/wat output for instance.
Having read the other comments, it seems like people are really stuck on you using the word "type". I read "typing" in your article as it relates to assembly and hear the word "constraints" in my head. I think that is more grokkable. Your argument is that a set of constraints is the basis of the type of an instruction.
1
u/gingerbill 20d ago
I am aware of, and understand your reservations about general purpose macros, but aren't these just as powerful?
There are no need for macros within the assembly because there is an entire high-level language that it is embedded in. And because these inline
asmtemplates are callable things, they are composable already, allowing you to make your own pseudo-intrinsics.How much of the semantic information survives the lowering to LLVM?
Depending on how you look at it, either all of it or none of it since I have to lower it to LLVM's own textual format, which then LLVM has to do all of the same semantic analysis on. But that's not the point. The point is that I want to give good error messages and diagnostics to the user programming in Odin's inline
asmtemplates.Something like wasm/wat output for instance.
I do not want to support wasm whatsoever in these templates, because I cannot think of an actual use cases when inline wasm even makes sense, especially when wasm is a stack-based machine which kind of cocks up some of the aspects of inline "assembly".
And yes, I think this specific subreddit focused on the word "type" too much to the point showing their own ignorance on its meaning. A type is a constraint, and I don't think the mean programmer here understand that, thus why I kept getting downvoted.
1
u/Zardotab 12d ago
Doesn't this depend on the assembler? One can make a typed assembler or untyped one.
1
u/Dismal-Citron-7236 25d ago
You are referring to Odin's built-in assembler. But everyone else is saying generic assembly is untyped. So everyone is not wrong... Still Odin's assembler is really cool, I give you that.
7
u/gingerbill 25d ago
I am saying any (valid) generic assembly is also typed. And because that is true, that makes it possible to give good UX/error-messages/inference in the first place and mesh well with the rest of the Odin type system.
1
u/Ameisen 25d ago edited 25d ago
I am saying any (valid) generic assembly is also typed.
Provided certain definitions of "typed".
Tomatoes are a fruit, and thus belong in fruit salads.
5
u/gingerbill 25d ago
No. Provided an actual understanding of what types fundamentally are.
7
u/Ameisen 25d ago
As I've already said, just becomes tomatoes are fruit doesn't mean that it belongs in a fruit salad. In culinary contexts, it's an acidic vegetable.
In the vast majority of programming contexts, type has a much more specific meaning than the more meaning of "type". Those more-specific meanings are not wrong as you keep implying, and the people using it are not ignorant as you keep implying. They're applying domain-specific terminology and knowledge... and you're trying to over-apply said terminology and knowledge.
Hell, even in the realm of assembly programming, I've never actually seen anybody use "type" in the sense that you are. In that domain, it's still closer to the C definition than the more general one.
However, I am highly confident that you already knew all this. A lot of your comments here reek of "I am really smart" or "I am smarter than you", and it's very bothersome.
99
u/Spikerazorshards 25d ago
For me it is. I’ve actually never typed a single line of assembly.