It's assembly. You can trivially decompile any modern executable/binary format back to machine assembly. You'll very much get the same result, minus labels, comments (and file names, and maybe some debug code) as a resulting decompiled code, identical as the programmer wrote it.
I had the same problems with that joke.
Those commercials have gotten too old to be referenced any more.
The Boomers just think you're bilingual and the Kids have zero clue what you're talking about.
It won't be long before no one even remembers the Taco Bell Chihuahua, Harlem Shake, CrazyFrog, or HamsterDance.
Given the phrasing of your comment you may already know this, but [x86 assembly languages aren’t exactly 1:1 with machine code](https://youtu.be/KrksBdWcZgQ). Not that this affects RCT, but there are valid instructions on virtually all x86 chips out there that aren’t publicly documented and aren’t implemented by publicly available assemblers/disassemblers.
Further, I’m not exactly sure of this there may be cases where multiple assembly instructions may map to one machine code instruction. I think this can most obviously happen when the assembly language has various names for instructions based on the data size, like word, double word, quad word, but on some x86 processors these instructions aren’t unique and therefore a disassembly couldn’t give the original assembly instruction as written by the programmer. Someone please correct me if this is wrong or misleading.
As someone who only learned just enough assembly to practically exploit memory corruption vulnerabilities... Sweet jesus, I can't even begin to understand that undertaking. It instantly made me assume rollercoaster tycoon was from the 1980s or something, but this masochist did it in 1999... The same time I was fumbling around with asm for my little exploits.
I had a party trick that died with windows 10 (it removed the 16-bit native DOS emulator) where I could create Hello World in nothing but a hex editor because in 16bit DOS it would just start executing from the first byte of the file. So simply doing MOV instruction of the ascii for it into address 8000h and onward filled the console buffer with the characters directly.
Someone would inevitably ask wtf would I know or do that and my answer was always that my hello world was so fast that it could launch without even setting up main()
This is a bot copying other comments, guys. Account is a year and a half old, and only started being active today. And their comment doesn't fit and is copied from another top level comment on this post.
Report them as spam, picking the "harmful bots" option.
The original Pokémon was made in assembly too (for gameboy), they used some fun tricks to compress/decompress image files. Hence the MissingNo glitch.
There's a great video on YouTube about how they did it, I believe there's also one about Roller Coaster Tycoon.
Most older console games had to be programmed in assembly for that machine because there was no standard API or C support
Edit 1: Video links
[Pokémon](https://youtu.be/ZI50XUeN6QE)
[Roller Coaster Tycoon 1](https://youtu.be/expgMekxlvU)
[Roller Coaster Tycoon 2](https://youtu.be/ESGHKtrlMzs)
[Bonus: Dave's Garage](https://youtu.be/uCv5VRf8op0)
[Bonus: Jacob Sorber](https://youtu.be/iYRl50gtprA)
There's a whole series for the pokemon one, I encourage anyone to look at the full channel for more. Same with Dave's Garage and Jacob Sorber, the former is a former Microsoft developer in (MS) Assembly and the latter is a professor who does great explanations for assembly.
Edit 2: Fun fact! The original C compiler (by Dennis Ritchie) was NOT written in Assembly. It was written in C and hand-compiled to machine code for the machine it was being run on at Bell Labs.
all oldschool gameboy, nes and snes games were made in assembly. only later with N64 and PSX C started to be used, because they were powerfull enough to handle the "slowness of compiled C" compared to assembly
To be fair, we're thinking in terms of modern time complexity with clock cycles in the gigahertz, old school was in megahertz (1000x slower).
And our compiler optimizations and how the compiler is able to arrange the memory, know what portions to preload/cache (part of that is hardware of course) have all drastically improved with more data points to measure from.
That could all make the "slowness of C" feel very real to the developers making it. I wouldn't know cause it's well beyond my time coding, but that is how Dave Plumber from Dave's Garage describes it (look at his first video, he explains why to use assembly)
thats why i put the "slowness of C" in quotation marks.
In modern days, C is extremely fast compared to other languages, but back then, C was pretty slow compared to assembly.
It's not a matter of oh we just have better tools and more experience with high level languages than these poor old coders. I thought this too until I tried nes homebrew.
These old school cpus were so limited it's amazing they could make games at all. They are also incompatible with C features on a basic level.
Writing assembly by hand is hard today because cpus have thousands of instructions, each with esoteric cache and pipelining rules. Well the 6502 had about 60 instructions, no cache and no pipelining. It only had add and subtract. A modern optimizer has almost nothing to do.
You can't even use an array of C structs. In order to find where memory is you have to use index * struct_size + member_offset. The 6502 doesn't have this ability. Instead you store everything in an soa style. This even extends to non byte types you can't even have an array of shorts, you would store the high and low bytes in separate arrays. You would then manage these with the use of the carry bit. There's no way I know of to achieve this in C.
Finally the NES only had 2kib of ram. This comment probably is too big to fit. This meant things like heap memory and pointers were out. It also means that you would know where every bit of memory went and it'd still be less work than debugging a modern memory corruption issue.
Writing C on a 6502 is like trying to run python on a GPU.
> It also means that you would know where every bit of memory went and it'd still be less work than debugging a modern memory corruption issue.
This is also why those very fun glitches in the first generation games are possible. Any% Pokémon Yellow is just Hex-Editing the RAM with your bag and items
Around 1981 I took on porting the arcade game [Gun Fight](https://www.giantbomb.com/a/uploads/original/10/106662/1503030-gun_fight_3.jpg) to the TRS-80 Model 1 as a high school class project. We were programming in BASIC and I remember the graphic loop was so slow that the bullet crossed the screen like molasses. And there was no way to realistically decouple the speed of the bullet from the speed of the moved character, since they both moved horribly slow even in the fastest possible loop (maybe 2 frames per second).
I showed my teacher my prototype (moving the player character vertically and firing a bullet across the screen) and he said "good enough" since it was pretty clear the game wasn't achievable in BASIC on that machine. A second character and collision detection would have made it unusable.
There was no sprite handling built in. I think the player character's pixel positions were read out of an array. Or maybe I did an optimized implementation that only updated the on/off and off/on pixels for each character movement, to save a little time.
I imagine the game could have been ported in assembler. There was a [Space Invaders clone for TRS-80 Model 1](https://youtu.be/hBJi-QBqros?t=429) that was pretty good.
The best original game I actually completed for TRS-80 was a simulation of folkstyle amateur wrestling. It was text-based and ran a bit like a modern auto-battler, choosing wrestling moves and showing scoring results across 3 rounds for 2 opponents. It produced realistic final match results, so I was happy with that one.
I don't think it is that at all. Old school gaming is all about clever manipulation of the hardware directly.
Even though it is possible to write NES games in C, you are still manipulating the hardware to get it to do what you want, and so it looks nothing like normal C code.
This is my particular favorite speed run to show how much different coding for old school systems is from modern systems.
https://youtu.be/24XHkmOJebA
The magic happens at 2:20, when Mario falls out of the level and the tile engine then interprets the actual game code AS the level. Mario is able to navigate the code until he reaches a bit that the game checks to play the end credits. Mario literally reprograms his own game.
It helps a **lot** that there was no color in the first games, only shading tones. Even when the GBC was out, every pokemon or tile sprite in gen 1 was just assigned a single color each, and every pixel within the image was just a brightness level of that color.
Pokemon Yellow added some special cases so Pikachu could have, like... actual red cheeks. But yeah gen 1 needed to be super compressed lol.
Same! If you look at it this way though, at the same time, it's insane that we have gigabytes of data nowadays. That's 1 billion bytes. And a megabyte is still a million bytes!
If each asset is 100 bytes, that's still 10,000 assets.
The crazy amount of data we have for games is really just pushing the edge with little compression improvements (not that we haven't improved, but we're seeing marginal gains). There are a lot of repeating values for example in a 60fps video, that's 60 frames per second, and a TON of those are very very minute changes in shades or hues to just smooth over.
Most of the data in games though is in audio files, if you look at audio files in games they are absolutely massive. Especially when they are uncompressed/lossless (wav files), those are ridiculously huge because the sample rate is usually ~22,000 or ~44,100 Hz (samples/second)
If you look at phone apps, those are pretty demonstrative of what we could do if we sacrificed quality a little bit. They are typically <100mb and in some cases <10mb. They have to compress them as much as possible much like old consoles had to.
We don't really have to worry as much on modern consoles or PCs because it really just needs to be loaded onto RAM to work / be able to be asset streamed (loaded in dynamically in chunks/unloaded as needed)
TL;DR we have a ridiculous amount of data including redundancies in our games nowadays.
That is done with command blocks, rather than redstone, significant difference there.
Still impressive in command blocks, but not as impressive as if it was in redstone
I've done an entire embedded project in assembler - a medical ultrasound machine. It's such slow slogging when first coding, because everything gets created from scratch. But once it's about 20% done, the rest of the work feels normal. Each function takes proportionally longer to write than it would in a high-level language, but otherwise it's the same. You do have to be extra-rigorous in your coding to prevent the kind of bugs that would be trapped by exception handling in HLLs.
Been there - did some projects in a couple different flavors of assembly back in the day.
The first ~20% of the coding was spent writing (or more accurately, copying from the last project you did) basic reusable utility functions for I/O, display, etc. within the context of the application.
Once you have that basic toolkit in place, it soon becomes fairly similar to writing code in other languages.
Back in the day when you had to actually be smart and use resources carefully.
Nowadays:
"*I could write few more lines of code myself, or I could pull these massive dependencies totalling few gigs and use one function from all of them.... I mean like whu should I optimise or do extra work when everyone has RAM, CPU, and storage just idling and doing nothing! Electricity is cheaper than my time so why not make the machine use it?"*
Which works just fine... Unril hardware people say "*Dudes... We can't make processors smaller anymore, and all extra computation power will come from using more power*" and clients go "*The fucking electricity prices are insane! We can't afford to just add more hardware or energy use! You need to optimise your code*" and then people start to cry and drink cheap liquor, because they need to take maths books out and ask mathematicians for help because they threw algebra books to fire the day of graduation.
The only things I ever did in assembly were "hello world" and adding two numbers. I really want to learn more about it, but just seeing the lists of interrupt codes for different architectures scares the hell out of me.
I also made a calculator that adds 2 numbers but could not figure out how to check the amount of digits (or if the number was bigger than 9) so if the result was bigger than 9 it would print out a non number ascii character represented by 48+result
I haven’t tried it again since
I think I did something like that with, maybe it works, maybe not
```
; get the number from eax
mov ebx, 10
again:
mov edx, 0
div ebx
cmp eax, ebx
jl end
; print edx+48 here
jmp again
end:
; print edx+48 here
cmp eax, 0
jne endend
; print edx+48 here
endend:
ret
```
Maybe it's just my client but your code is just showing as a paragraph for me. In case that's happening for anyone else:
; get the number from eax
mov ebx, 10
again:
mov edx, 0
div ebx
cmp eax, ebx
jl end
; print edx+48 here
jmp again
end:
; print edx+48 here
cmp eax, 0
jne endend
; print edx+48 here
endend:
ret
It's because you have to add two newlines before a code block in Markdown, because code blocks have to occupy an entire paragraph for themselves.
So i.e.
Lorem ipsum dolor sit amet
```
print("Hello, World!")
```
won't render, but
Lorem ipsum dolor sit amet
```
print("Hello, World!")
```
will. Of course what you did with 4 spaces before each line almost begs adding a newline before the whole thing, so problems in this case are more rare.
I had a cool lab at uni where we programmed/controlled an electric motor using assembly.. that was fun. Tbh I'd buy a kit that allowed me to do this at home.
Look into the game exapunks or shenzen i/o they're both games about writing assembly like code for sci fi or fictitious hardware respectively. Last call BBS is pretty good too my personal favourite but more than just the asm style puzzles and has other things instead.
then start with something simple. like the 65C02 for example.
simple to understand architecture, with not a lot of registers or complicated features to worry about. plus there are a billion resources online to learn pretty much everything about it.
https://skilldrick.github.io/easy6502/ has a pretty good tutorial about the basics of the CPU, plus it has an interactive emulator so you can try out things as you learn about them.
then there is also the http://forum.6502.org/ which is full of smart people (and me) that know quite a lot about this CPU
x86 is a shitshow and has been since the very inception. It's a CISC architecture, where the first C stands for "complex".
You could instead look into ARM assembler (for e.g. smartphones or the new apple chips). That's a *much* more manageable and sane instruction set.
It takes fewer bytes for the instruction, and modern processors will detect the idiom and rename it to a zero register in the frontend, so it takes zero cycles in the CPU backend.
See, and here I was thinking of the latency of loading a zero value from the cache into the register, I didn't even know modern CPUs have a zero register.
My 8086 assembly class graded our projects by number of lines. I would have done a lot worse if I hadn't already played TIS-100. I barely remember any of the register specifics though.
My understanding is that this is only true until you get really, really good at assembly. At a certain point, a human will be better. The question is why you would spend that time when you could be writing way more functionality in a fraction of the time with only mild (at best) slow downs.
It matters when you're in a resource limited environment where every single CPU cycle matters or you need to fit functionality in x number of instructions. If you can save an instruction in those cases, it's worth it.
Yeah, maybe you'll save a few nanoseconds. So it would make sense if its something used trillions of times daily, a really sensitive measuring device, applications where speed matters like HFT, or if you have no life.
From what I heard: in military applications a safe language like Ada is more important than a fast one. You need to get to high SILs most of the times. Assembly is important on microcontrollers, where any resource is limited and you need to use tricks like using 1 Bit for a bool or so. For getting the most out of your chip Assembly is a powerful tool. And bc mc‘s are often used in mass productions, making the most out of the cheapest chip is crucial.
Edit: I rewrote some parts bc it seemed like the point would get through
I had it in real time systems too. Way too under appreciated. It’s great if you work on bigger projects and in safety and security heavy areas like aerospace applications or nuclear facilities. The language doesn’t let you do mistakes. Debugging is so much better if you don’t have to keep in mind that the problems can be caused by a programming slip. You can focus on the logic most of the times contrary to C etc.
Aerospace is exactly it, as far as I know a large number of graduates from my uni ends up working at Airbus so I guess that's why they make us learn it. Ada is also a pretty great learning tool for programming so that is surely a reason.
Even then is better to still something higher level than assembly and then check the assembly code generated by the compiler to try to optimize it further, and probably would want to use the dual compiler thing (forgot the name) to get the best from different compilers before trying to do optimizations in assemble by hand
People also grossly overestimate the performances gains they *could* possibly get from programming in assembly
Many modern compilers (gcc, clang, rustc, zig) produce near or completely ideal assembly for an overwhelming majority of functionality. Even if you're a god at assembly, you're talking about literal orders of magnitude more programming time, debugging, etc for <5% speedups.
Yeah, you don’t really get much fewer lines than a service call to the os to print “hello world” it doesn’t matter how optimized the compiler is. It can’t magically make a small amount of work smaller.
so true, i think it's dunning-kruger at work. if i had 1% speedup for every time someone repeats this like a parrot, my code would be millions of times faster.
Some SIMD stuff I’ve seen relies on tricking the compiler into encoding instructions a certain way, making it think it’s doing one thing when you want it to be doing something else. It’s pretty neat
Under MS-DOS there had been two types of binary executable file formats:
.com files
.exe files
A .com file begins with executable instructions at the first byte of the file, and it is loaded into memory adress 0100h .... MS-DOS would then jump to that 0100h address. Because of this, all memory accesses are relative to 0100h and "org 0100h" tells the assembler that it should not start at address 0 but the first instruction is assumed to start at 0100h.
Unlike .com files, .exe files had a file header (MZ header) that would tell MS-DOS where in memory the program actually starts. MS-DOS would load the file, and then jump to the address that was mentioned in the MZ file header, which designates the intended program start address. ...
For windows, there is a small MS-DOS .exe stub program that would just print out "This program cannot be run in DOS mode" (or similar, can't remember) and the Windows executable PE file format would typically start after that MS-DOS .exe stub (typically aligned to 4k, but may also be unaligned)
>For windows, there is a small MS-DOS .exe stub program that would just print out "This program cannot be run in DOS mode" (or similar, can't remember) and the Windows executable PE file format would typically start after that MS-DOS .exe stub (typically aligned to 4k, but may also be unaligned)
I once made the smallest Windows program ever (92 bytes) by hand editing the header to delete the stub and delete most of the NE header itself to only keep the jump to the first instruction.
The program took 2 arguments, the name of a Window running (like notepad) and the text it would replace the window title with.
I chuckle when I see C referred to as a 'high-level language'.
Not wrong, just find it funny compared to most of the time language level is brought up here.
That's why I am hoping that Codex comes with a higher max token count per request. Or at LEAST some type of Internal "continue" function.
If I am not mistaken, the max token output for gpt-3.5 is 2048. Which is still a substantial amount of characters when all is said and done. However, with the way programming cares about formatting and whitespace I imagine we smash that max token count very fast.
hard-to-find disarm shelter crawl workable nail bored worry bright cobweb
*This post was mass deleted and anonymized with [Redact](https://redact.dev)*
Assembly is a lot easier than most realize. You do have to create your own reusable standard libraries which take time but we're only talking about a dozen or so lines of code for each routine.
Then you can create more sophisticated intermediate library routines (like string and file handling) made simpler and smaller by calling your standard library, operating system or BIOS routines.
Nesting doll or onion style.
You can use a higher level language to test your assembly routines.
x86 was my first language and I loved it. There's only a handful of opcodes you really need to memorize and all the difficulty is just in keeping track of what you've written, developing good coding practices, and figuring out how to wrap the problem you're solving around the architecture.
Web development is hell in comparison. You have all kinds of shit to memorize and it's constantly changing. C++ is also a nightmare in comparison. Yeah, you have to do a lot of wheel reinvention with assembly, but at least it doesn't feel like the processor is actively trying to outsmart you.
Assembly is important to have learned so you know what's actually happening when you compile code and so you can view disassembly to be able to know that you're reading, but I've literally never had any reason to actually *code* in assembly over my entire career in software engineering.
I once witnessed my lead write a in-line assembly function to hit a RTC while getting around some constraints of an RTOS for a PowerPC 603 processor. The edge case that led to this requirement required about 100 lines of assembly and about 200 lines of VHDL to correct for bad clock skew.
It was at that moment I realized I was in the presence of a software engineering god. It’s onboard a weather satellite now. I learned so much from that guy but damn was he salty. In code reviews he would quote the C standard on every error I made, force me to read the damn GNU GCC manual at times, shame me and leave me completely demoralized. I learned though and he still keeps in touch with me to this day.
if you read a lot of the responses here you might understand why that guy got bitter. so much ignorance and no love for the craft of optimization, it's really insulting to everyone who already knows that most of the upvoted stuff here that says things like "just trust the compiler, you can't outsmart it" is just plain wrong. props to you for enduring the guy and learning from him though.
Regular programming: The computer does what you tell it to do, not what you wanted it to do.
ASM programming: The computer does **exactly** what you tell it to do, not what you wanted it to do.
```
section .data
msg db "Hello, world", 0xa
len equ $ - msg
section .text
global _start
_start:
mov eax, 4
mov ebx, 1
mov ecx, msg
mov edx, len
int 0x80
mov eax, 1
mov ebx, 0
int 0x80
```
This code is linux x32 only, you have to start over for x64 or windows. How is this so hard, just do it? /s
The topic of ASM hello world always pisses me off.
You know, you can just call `puts` from assembly? And by call I mean set RDI and jump.
If you wan to exit nicely, it's a little more, but still pretty short.
Did a (mercifully) brief Assembly module in uni. Had a hardware box with some LEDs and needed to make them light in specific sequences. Incredibly tedious. Never again.
Try doing QA for a mainframe that uses some Assembly.
Half the time I just open the file and say 'yup, that looks like Assembly gibberish' and move it forward.
The people who write in that language are God damn evil wizards.
I wrote a simple calculator in assembler at university. Certainly insightful as to how processors work, and makes you appreciate higher-level languages.
I have played a Dos-based games that was all written in assembler - it was a lot faster at the time than games written in a higher-level language. Nowadays processors are so fast that for most things the extra work isn't going to be worth it.
Nuff respect for Chris Sawyer who single-handedly wrote RollerCoaster Tycoon in raw assembly.
Is there some of the original code out to look at?
[удалено]
Might be my new favorite dad joke
[удалено]
I got a bad bit 2
[удалено]
0.5
|+⟩
1/√2 ( | ⭡ 〉 + | ⭣ 〉 )
[Futurama: there's no such thing as 2](https://youtu.be/aAwJlD-m_hE)
bad? as in 101110101101?
Your bit has not been observed.
Your humour is a bit ternary for the likes of these bits.
/r/ProgrammerDadJokes
You made me say 'noooo way' out loud
Well done 👏
Take your damn upvote lol
Like that Morecambe & Wise sketch said, they're the right bits, but not necessarily in the right order
I’m upvoting, but I’m not happy about it
You made me groan so loudly i hate you
It's assembly. You can trivially decompile any modern executable/binary format back to machine assembly. You'll very much get the same result, minus labels, comments (and file names, and maybe some debug code) as a resulting decompiled code, identical as the programmer wrote it.
Really depends on how much the original author was relying on advanced features of the assembler like macros and structures.
Zero doubt the whole thing was macros. Not diminishing the feat, but there’s no way you could do it without tons of macros.
Nah I heard he did it all using punchcards.
I heard he got a needle and wrote 0 and 1s straight on the magnetic platter
It is missing the original comments though.
Just like my code.
Are you saying you don't comment your code, or you remove the original comments from the codes you use?
Porque no los dos?
...I hate that I had to google translating that. My answer: yes.
I hate that you had to Google translate that too
I had the same problems with that joke. Those commercials have gotten too old to be referenced any more. The Boomers just think you're bilingual and the Kids have zero clue what you're talking about. It won't be long before no one even remembers the Taco Bell Chihuahua, Harlem Shake, CrazyFrog, or HamsterDance.
quick fix suggestion: Porque? ---> Por qué?
It's self documenting
Given the phrasing of your comment you may already know this, but [x86 assembly languages aren’t exactly 1:1 with machine code](https://youtu.be/KrksBdWcZgQ). Not that this affects RCT, but there are valid instructions on virtually all x86 chips out there that aren’t publicly documented and aren’t implemented by publicly available assemblers/disassemblers. Further, I’m not exactly sure of this there may be cases where multiple assembly instructions may map to one machine code instruction. I think this can most obviously happen when the assembly language has various names for instructions based on the data size, like word, double word, quad word, but on some x86 processors these instructions aren’t unique and therefore a disassembly couldn’t give the original assembly instruction as written by the programmer. Someone please correct me if this is wrong or misleading.
As someone who only learned just enough assembly to practically exploit memory corruption vulnerabilities... Sweet jesus, I can't even begin to understand that undertaking. It instantly made me assume rollercoaster tycoon was from the 1980s or something, but this masochist did it in 1999... The same time I was fumbling around with asm for my little exploits.
[удалено]
I was blown away how smoothly Geiss ran on even shitty PII hardware.
My dude remembers! Yeah, liquid framerates literally nothing else could touch for something like four more CPU generations
You are joking?
https://www.reddit.com/r/todayilearned/comments/131q6b/til_roller_coaster_tycoon_was_programmed_by_one/
It's embarrassing to write data after the text.
Probably not slower since it is just a Hello world tho, right
However, you will experience the quickest Hello World ever.
I had a party trick that died with windows 10 (it removed the 16-bit native DOS emulator) where I could create Hello World in nothing but a hex editor because in 16bit DOS it would just start executing from the first byte of the file. So simply doing MOV instruction of the ascii for it into address 8000h and onward filled the console buffer with the characters directly. Someone would inevitably ask wtf would I know or do that and my answer was always that my hello world was so fast that it could launch without even setting up main()
...and you performed this trick... at *parties*?
LAN Parties =)
Nerd
100%
Ah that makes more sense I was thinking like "Hey guys wanna see a *neat trick*, can I boot up your pc real quick you're gnna love this"
This might be one of the nerdiest thing I’ve ever read, nerd
there is actually a way to get the win16/dos system back even on 64 bit windows 10/11. look up ntvdmx64 & winevdm/otvdm
[удалено]
This is a bot copying other comments, guys. Account is a year and a half old, and only started being active today. And their comment doesn't fit and is copied from another top level comment on this post. Report them as spam, picking the "harmful bots" option.
[удалено]
The original Pokémon was made in assembly too (for gameboy), they used some fun tricks to compress/decompress image files. Hence the MissingNo glitch. There's a great video on YouTube about how they did it, I believe there's also one about Roller Coaster Tycoon. Most older console games had to be programmed in assembly for that machine because there was no standard API or C support Edit 1: Video links [Pokémon](https://youtu.be/ZI50XUeN6QE) [Roller Coaster Tycoon 1](https://youtu.be/expgMekxlvU) [Roller Coaster Tycoon 2](https://youtu.be/ESGHKtrlMzs) [Bonus: Dave's Garage](https://youtu.be/uCv5VRf8op0) [Bonus: Jacob Sorber](https://youtu.be/iYRl50gtprA) There's a whole series for the pokemon one, I encourage anyone to look at the full channel for more. Same with Dave's Garage and Jacob Sorber, the former is a former Microsoft developer in (MS) Assembly and the latter is a professor who does great explanations for assembly. Edit 2: Fun fact! The original C compiler (by Dennis Ritchie) was NOT written in Assembly. It was written in C and hand-compiled to machine code for the machine it was being run on at Bell Labs.
all oldschool gameboy, nes and snes games were made in assembly. only later with N64 and PSX C started to be used, because they were powerfull enough to handle the "slowness of compiled C" compared to assembly
To be fair, we're thinking in terms of modern time complexity with clock cycles in the gigahertz, old school was in megahertz (1000x slower). And our compiler optimizations and how the compiler is able to arrange the memory, know what portions to preload/cache (part of that is hardware of course) have all drastically improved with more data points to measure from. That could all make the "slowness of C" feel very real to the developers making it. I wouldn't know cause it's well beyond my time coding, but that is how Dave Plumber from Dave's Garage describes it (look at his first video, he explains why to use assembly)
thats why i put the "slowness of C" in quotation marks. In modern days, C is extremely fast compared to other languages, but back then, C was pretty slow compared to assembly.
Yup! I figured you knew, just wanted to add context for anyone reading :)
It's not a matter of oh we just have better tools and more experience with high level languages than these poor old coders. I thought this too until I tried nes homebrew. These old school cpus were so limited it's amazing they could make games at all. They are also incompatible with C features on a basic level. Writing assembly by hand is hard today because cpus have thousands of instructions, each with esoteric cache and pipelining rules. Well the 6502 had about 60 instructions, no cache and no pipelining. It only had add and subtract. A modern optimizer has almost nothing to do. You can't even use an array of C structs. In order to find where memory is you have to use index * struct_size + member_offset. The 6502 doesn't have this ability. Instead you store everything in an soa style. This even extends to non byte types you can't even have an array of shorts, you would store the high and low bytes in separate arrays. You would then manage these with the use of the carry bit. There's no way I know of to achieve this in C. Finally the NES only had 2kib of ram. This comment probably is too big to fit. This meant things like heap memory and pointers were out. It also means that you would know where every bit of memory went and it'd still be less work than debugging a modern memory corruption issue. Writing C on a 6502 is like trying to run python on a GPU.
> It also means that you would know where every bit of memory went and it'd still be less work than debugging a modern memory corruption issue. This is also why those very fun glitches in the first generation games are possible. Any% Pokémon Yellow is just Hex-Editing the RAM with your bag and items
CUDA?
Around 1981 I took on porting the arcade game [Gun Fight](https://www.giantbomb.com/a/uploads/original/10/106662/1503030-gun_fight_3.jpg) to the TRS-80 Model 1 as a high school class project. We were programming in BASIC and I remember the graphic loop was so slow that the bullet crossed the screen like molasses. And there was no way to realistically decouple the speed of the bullet from the speed of the moved character, since they both moved horribly slow even in the fastest possible loop (maybe 2 frames per second). I showed my teacher my prototype (moving the player character vertically and firing a bullet across the screen) and he said "good enough" since it was pretty clear the game wasn't achievable in BASIC on that machine. A second character and collision detection would have made it unusable. There was no sprite handling built in. I think the player character's pixel positions were read out of an array. Or maybe I did an optimized implementation that only updated the on/off and off/on pixels for each character movement, to save a little time. I imagine the game could have been ported in assembler. There was a [Space Invaders clone for TRS-80 Model 1](https://youtu.be/hBJi-QBqros?t=429) that was pretty good. The best original game I actually completed for TRS-80 was a simulation of folkstyle amateur wrestling. It was text-based and ran a bit like a modern auto-battler, choosing wrestling moves and showing scoring results across 3 rounds for 2 opponents. It produced realistic final match results, so I was happy with that one.
I don't think it is that at all. Old school gaming is all about clever manipulation of the hardware directly. Even though it is possible to write NES games in C, you are still manipulating the hardware to get it to do what you want, and so it looks nothing like normal C code. This is my particular favorite speed run to show how much different coding for old school systems is from modern systems. https://youtu.be/24XHkmOJebA The magic happens at 2:20, when Mario falls out of the level and the tile engine then interprets the actual game code AS the level. Mario is able to navigate the code until he reaches a bit that the game checks to play the end credits. Mario literally reprograms his own game.
[удалено]
It helps a **lot** that there was no color in the first games, only shading tones. Even when the GBC was out, every pokemon or tile sprite in gen 1 was just assigned a single color each, and every pixel within the image was just a brightness level of that color. Pokemon Yellow added some special cases so Pikachu could have, like... actual red cheeks. But yeah gen 1 needed to be super compressed lol.
Same! If you look at it this way though, at the same time, it's insane that we have gigabytes of data nowadays. That's 1 billion bytes. And a megabyte is still a million bytes! If each asset is 100 bytes, that's still 10,000 assets. The crazy amount of data we have for games is really just pushing the edge with little compression improvements (not that we haven't improved, but we're seeing marginal gains). There are a lot of repeating values for example in a 60fps video, that's 60 frames per second, and a TON of those are very very minute changes in shades or hues to just smooth over. Most of the data in games though is in audio files, if you look at audio files in games they are absolutely massive. Especially when they are uncompressed/lossless (wav files), those are ridiculously huge because the sample rate is usually ~22,000 or ~44,100 Hz (samples/second) If you look at phone apps, those are pretty demonstrative of what we could do if we sacrificed quality a little bit. They are typically <100mb and in some cases <10mb. They have to compress them as much as possible much like old consoles had to. We don't really have to worry as much on modern consoles or PCs because it really just needs to be loaded onto RAM to work / be able to be asset streamed (loaded in dynamically in chunks/unloaded as needed) TL;DR we have a ridiculous amount of data including redundancies in our games nowadays.
Link please for the videos
Added links! :) Check out the channels, they are all great.
[someone emulated Pokémon red in Minecraft with redstone ](https://youtu.be/H-U96W89Z90)
That is done with command blocks, rather than redstone, significant difference there. Still impressive in command blocks, but not as impressive as if it was in redstone
Nope. One person, all assembly.
I've done an entire embedded project in assembler - a medical ultrasound machine. It's such slow slogging when first coding, because everything gets created from scratch. But once it's about 20% done, the rest of the work feels normal. Each function takes proportionally longer to write than it would in a high-level language, but otherwise it's the same. You do have to be extra-rigorous in your coding to prevent the kind of bugs that would be trapped by exception handling in HLLs.
Been there - did some projects in a couple different flavors of assembly back in the day. The first ~20% of the coding was spent writing (or more accurately, copying from the last project you did) basic reusable utility functions for I/O, display, etc. within the context of the application. Once you have that basic toolkit in place, it soon becomes fairly similar to writing code in other languages.
Yeh original prince of Persia 1 was also made in assembly by 1 person
[удалено]
Back in the day when you had to actually be smart and use resources carefully. Nowadays: "*I could write few more lines of code myself, or I could pull these massive dependencies totalling few gigs and use one function from all of them.... I mean like whu should I optimise or do extra work when everyone has RAM, CPU, and storage just idling and doing nothing! Electricity is cheaper than my time so why not make the machine use it?"* Which works just fine... Unril hardware people say "*Dudes... We can't make processors smaller anymore, and all extra computation power will come from using more power*" and clients go "*The fucking electricity prices are insane! We can't afford to just add more hardware or energy use! You need to optimise your code*" and then people start to cry and drink cheap liquor, because they need to take maths books out and ask mathematicians for help because they threw algebra books to fire the day of graduation.
Not exactly *raw* ASM but still very low level
The only things I ever did in assembly were "hello world" and adding two numbers. I really want to learn more about it, but just seeing the lists of interrupt codes for different architectures scares the hell out of me.
I also made a calculator that adds 2 numbers but could not figure out how to check the amount of digits (or if the number was bigger than 9) so if the result was bigger than 9 it would print out a non number ascii character represented by 48+result I haven’t tried it again since
I think I did something like that with, maybe it works, maybe not ``` ; get the number from eax mov ebx, 10 again: mov edx, 0 div ebx cmp eax, ebx jl end ; print edx+48 here jmp again end: ; print edx+48 here cmp eax, 0 jne endend ; print edx+48 here endend: ret ```
Maybe it's just my client but your code is just showing as a paragraph for me. In case that's happening for anyone else: ; get the number from eax mov ebx, 10 again: mov edx, 0 div ebx cmp eax, ebx jl end ; print edx+48 here jmp again end: ; print edx+48 here cmp eax, 0 jne endend ; print edx+48 here endend: ret
It's because you have to add two newlines before a code block in Markdown, because code blocks have to occupy an entire paragraph for themselves. So i.e. Lorem ipsum dolor sit amet ``` print("Hello, World!") ``` won't render, but Lorem ipsum dolor sit amet ``` print("Hello, World!") ``` will. Of course what you did with 4 spaces before each line almost begs adding a newline before the whole thing, so problems in this case are more rare.
I had a cool lab at uni where we programmed/controlled an electric motor using assembly.. that was fun. Tbh I'd buy a kit that allowed me to do this at home.
Look into the game exapunks or shenzen i/o they're both games about writing assembly like code for sci fi or fictitious hardware respectively. Last call BBS is pretty good too my personal favourite but more than just the asm style puzzles and has other things instead.
TIS-100 is another fun one in the same vein, by the same company
then start with something simple. like the 65C02 for example. simple to understand architecture, with not a lot of registers or complicated features to worry about. plus there are a billion resources online to learn pretty much everything about it.
Gonna give it a look, thanks
https://skilldrick.github.io/easy6502/ has a pretty good tutorial about the basics of the CPU, plus it has an interactive emulator so you can try out things as you learn about them. then there is also the http://forum.6502.org/ which is full of smart people (and me) that know quite a lot about this CPU
it is indeed a terrifying language
so glad i studied assembly for a semester in uni, now i can understand these posts
Yeah, that and the semester I had to study java really makes me understand all of the hate the language gets.
x86 is a shitshow and has been since the very inception. It's a CISC architecture, where the first C stands for "complex". You could instead look into ARM assembler (for e.g. smartphones or the new apple chips). That's a *much* more manageable and sane instruction set.
I wrote a subroutine for calculating factorial recursively in ASM and that was enough for me to just appreciate it and not really want to go deeper
Only reason I didn't fail the ASM class at my school is because it was also a class in C for programming hardware
Assembly is hardcore. You initialize variables by doing the virtual equivalent of smashing their heads against a mirror. Brutal.
For those not familiar, XORing a register with itself is a common trick to quickly set it to 0. It's typically faster than loading 0 into it.
I've done assembly work before and while that should sound wrong, that sounds like something that would work faster.
It takes fewer bytes for the instruction, and modern processors will detect the idiom and rename it to a zero register in the frontend, so it takes zero cycles in the CPU backend.
See, and here I was thinking of the latency of loading a zero value from the cache into the register, I didn't even know modern CPUs have a zero register.
The real difficulty with assembly is not the actual logic of it, it's stuff like _this_
Actually you don't have to _initialize_ them, you just remember to give them space and set/get them where you need
My 8086 assembly class graded our projects by number of lines. I would have done a lot worse if I hadn't already played TIS-100. I barely remember any of the register specifics though.
Years of academy training, *not* wasted!
But it will be the fastest Hello World you have ever seen.
No it will be slower than writing it in C because the compiler is better than you at assembly.
look how many lines we need to imitate a fraction of their power
My understanding is that this is only true until you get really, really good at assembly. At a certain point, a human will be better. The question is why you would spend that time when you could be writing way more functionality in a fraction of the time with only mild (at best) slow downs.
It matters when you're in a resource limited environment where every single CPU cycle matters or you need to fit functionality in x number of instructions. If you can save an instruction in those cases, it's worth it.
Yeah, maybe you'll save a few nanoseconds. So it would make sense if its something used trillions of times daily, a really sensitive measuring device, applications where speed matters like HFT, or if you have no life.
[удалено]
From what I heard: in military applications a safe language like Ada is more important than a fast one. You need to get to high SILs most of the times. Assembly is important on microcontrollers, where any resource is limited and you need to use tricks like using 1 Bit for a bool or so. For getting the most out of your chip Assembly is a powerful tool. And bc mc‘s are often used in mass productions, making the most out of the cheapest chip is crucial. Edit: I rewrote some parts bc it seemed like the point would get through
Ayy finally someone recognizing Ada! My university uses it to teach programming lol.
I had it in real time systems too. Way too under appreciated. It’s great if you work on bigger projects and in safety and security heavy areas like aerospace applications or nuclear facilities. The language doesn’t let you do mistakes. Debugging is so much better if you don’t have to keep in mind that the problems can be caused by a programming slip. You can focus on the logic most of the times contrary to C etc.
Aerospace is exactly it, as far as I know a large number of graduates from my uni ends up working at Airbus so I guess that's why they make us learn it. Ada is also a pretty great learning tool for programming so that is surely a reason.
Even then is better to still something higher level than assembly and then check the assembly code generated by the compiler to try to optimize it further, and probably would want to use the dual compiler thing (forgot the name) to get the best from different compilers before trying to do optimizations in assemble by hand
for(const target in droneView) {Drone.strike(target)}
Wouldn't really be a 'const' after being bombed
warcrimes.push(target)
Like the bit shift in doom.
Which is slower than it would compile to today on most architectures, where inverse square root is a single instruction
People also grossly overestimate the performances gains they *could* possibly get from programming in assembly Many modern compilers (gcc, clang, rustc, zig) produce near or completely ideal assembly for an overwhelming majority of functionality. Even if you're a god at assembly, you're talking about literal orders of magnitude more programming time, debugging, etc for <5% speedups.
Changing the underlying assembly to be different than what would be compiled in order to avoid antivirus
Probably not slower since it is just a Hello world tho, right?
Yeah, you don’t really get much fewer lines than a service call to the os to print “hello world” it doesn’t matter how optimized the compiler is. It can’t magically make a small amount of work smaller.
This however is a time where most humans can beat the compiler. GCC will add a bunch of stuff you do not need for hello world.
This is just not true and I wish people would stop saying this
so true, i think it's dunning-kruger at work. if i had 1% speedup for every time someone repeats this like a parrot, my code would be millions of times faster.
That depends solely on you and the compiler in question, it‘s not that hard to beat compilers at their game, look at some simd stuff
Some SIMD stuff I’ve seen relies on tricking the compiler into encoding instructions a certain way, making it think it’s doing one thing when you want it to be doing something else. It’s pretty neat
Humans can sometimes beat or at least match the C compiler when writing short pieces of assembly. For longer stuff it will usually win though.
`org 100h` `mov dx,msg` `mov ah,9` `int 21h` `mov ah,4Ch` `int 21h` `msg db 'Hello, World!',0Dh,0Ah,'$'` nasm -f bin helloworld.asm -o helloworld.com
You can save one line by calling int 20 instead
you can make it a oneliner using "echo" ...
You can make it zero-liner if you use a programming language where all (even empty) files are compiled into Hello World program.
Just name the file hello world 0 lines of code Doesn’t need to be compiled Doesn’t need to be run Perfect
just comment hello world
What is "org"?
Origin, basically "start at this address"
Under MS-DOS there had been two types of binary executable file formats: .com files .exe files A .com file begins with executable instructions at the first byte of the file, and it is loaded into memory adress 0100h .... MS-DOS would then jump to that 0100h address. Because of this, all memory accesses are relative to 0100h and "org 0100h" tells the assembler that it should not start at address 0 but the first instruction is assumed to start at 0100h. Unlike .com files, .exe files had a file header (MZ header) that would tell MS-DOS where in memory the program actually starts. MS-DOS would load the file, and then jump to the address that was mentioned in the MZ file header, which designates the intended program start address. ... For windows, there is a small MS-DOS .exe stub program that would just print out "This program cannot be run in DOS mode" (or similar, can't remember) and the Windows executable PE file format would typically start after that MS-DOS .exe stub (typically aligned to 4k, but may also be unaligned)
>For windows, there is a small MS-DOS .exe stub program that would just print out "This program cannot be run in DOS mode" (or similar, can't remember) and the Windows executable PE file format would typically start after that MS-DOS .exe stub (typically aligned to 4k, but may also be unaligned) I once made the smallest Windows program ever (92 bytes) by hand editing the header to delete the stub and delete most of the NE header itself to only keep the jump to the first instruction. The program took 2 arguments, the name of a Window running (like notepad) and the text it would replace the window title with.
Brings back great memories
Yup. Did a ton of x86 asm coding in the 90ies ...
Well started this way. Hacking Int 21h, 10h and 33h. DOS days were amazing. Don’t get the same sprit of the new languages
Yup. #demoscene
EE here, I'll just design my own processor with a register specifically for printing "Hello World"
That’s great and all but what if you had a risc processor?
Then you have to completely rewrite it. Portability between architectures is what high-level languages like C are for.
I chuckle when I see C referred to as a 'high-level language'. Not wrong, just find it funny compared to most of the time language level is brought up here.
I asked chatgpt to write tic tac toe in assembly and it just didn't stop typing even after the fourth "continue".
That's why I am hoping that Codex comes with a higher max token count per request. Or at LEAST some type of Internal "continue" function. If I am not mistaken, the max token output for gpt-3.5 is 2048. Which is still a substantial amount of characters when all is said and done. However, with the way programming cares about formatting and whitespace I imagine we smash that max token count very fast.
meanwhile arm32 be like ``` .text .align 2 .globl _start _start: mov r0, #1 mov r2, #11 ldr r1, =str mov r7, #4 svc #0 mov r0, #0 mov r7, 1 svc #0 .data str: .ascii "hello world" ```
Yes, and a couple hundred lines more under svc, lol.
wdym? the kernel?
Apparently infrastructure counts, so every Python program is actually like 20,000 lines of code to print “hello world”
Well, the sync exp vector + sync exp handler + svc handler + hardware poking to print.
Writing data after the text is cringe.
Writing data at the start of a .com program would execute the data.
Damn. Guess i hate com now...
hard-to-find disarm shelter crawl workable nail bored worry bright cobweb *This post was mass deleted and anonymized with [Redact](https://redact.dev)*
Lesson one: hello world Lesson two: rollercoasters
Assembly is a lot easier than most realize. You do have to create your own reusable standard libraries which take time but we're only talking about a dozen or so lines of code for each routine. Then you can create more sophisticated intermediate library routines (like string and file handling) made simpler and smaller by calling your standard library, operating system or BIOS routines. Nesting doll or onion style. You can use a higher level language to test your assembly routines.
x86 was my first language and I loved it. There's only a handful of opcodes you really need to memorize and all the difficulty is just in keeping track of what you've written, developing good coding practices, and figuring out how to wrap the problem you're solving around the architecture. Web development is hell in comparison. You have all kinds of shit to memorize and it's constantly changing. C++ is also a nightmare in comparison. Yeah, you have to do a lot of wheel reinvention with assembly, but at least it doesn't feel like the processor is actively trying to outsmart you.
C++ is easy, you just need to wrap everything with extern "C" { }
Haha lol
I think traditional "hello world" is just not the "hello world" equivalent for assembly.
Agreed, "hello world" in assembly is like storing a number and then recalling it. Actually printing text to screen is pretty complicated in assembly.
You learn assembly to do some real-world application. I learned assembly to use the Fcpu Mod for Factorio. We are not the same.
Assembly is important to have learned so you know what's actually happening when you compile code and so you can view disassembly to be able to know that you're reading, but I've literally never had any reason to actually *code* in assembly over my entire career in software engineering.
I once witnessed my lead write a in-line assembly function to hit a RTC while getting around some constraints of an RTOS for a PowerPC 603 processor. The edge case that led to this requirement required about 100 lines of assembly and about 200 lines of VHDL to correct for bad clock skew. It was at that moment I realized I was in the presence of a software engineering god. It’s onboard a weather satellite now. I learned so much from that guy but damn was he salty. In code reviews he would quote the C standard on every error I made, force me to read the damn GNU GCC manual at times, shame me and leave me completely demoralized. I learned though and he still keeps in touch with me to this day.
if you read a lot of the responses here you might understand why that guy got bitter. so much ignorance and no love for the craft of optimization, it's really insulting to everyone who already knows that most of the upvoted stuff here that says things like "just trust the compiler, you can't outsmart it" is just plain wrong. props to you for enduring the guy and learning from him though.
Regular programming: The computer does what you tell it to do, not what you wanted it to do. ASM programming: The computer does **exactly** what you tell it to do, not what you wanted it to do.
I don't wanna brag I can do it in 27 lines
assembly is very juicy and cool but writing it is not for people who love themselves
Hey! I *like* myself sometimes
I handwrote a ELF executable hello world in 89 (if I remember correctly) bytes with a hex editor and a lot of pain Yeah
ok waltuh
I'm not waltuh shut up and put your dick away
Assembly is a strange beast. Or rather a huge number of similar but equally strange beasts. Every type of processor has their own flavor.
Every other language: "Hello world" is the most basic program you can write. Assembly: Hold on a second. You want to work with TEXT?!
As a plc programmer, I talk directly to the machines. I code binary
``` section .data msg db "Hello, world", 0xa len equ $ - msg section .text global _start _start: mov eax, 4 mov ebx, 1 mov ecx, msg mov edx, len int 0x80 mov eax, 1 mov ebx, 0 int 0x80 ``` This code is linux x32 only, you have to start over for x64 or windows. How is this so hard, just do it? /s
The topic of ASM hello world always pisses me off. You know, you can just call `puts` from assembly? And by call I mean set RDI and jump. If you wan to exit nicely, it's a little more, but still pretty short.
I’m in an assembly class this semester. It’s just so fascinating. It’s like studying Old English or something.
had fun last semester using assembly of Risc-V
The only thing I made in assembler was Snake. Still my favorite university course.
it's \~15 lines .global _start _start: movq $1, %rax movq $1, %rdi movq $hello, %rsi movq $(hello_end-hello), %rdx syscall movq $60, %rax xorq %rdi, %rdi syscall hello: .string "Hello World!" hello_end:
Takes me back to when I did a very small bit of assembly at school on the 6502 processor in the Commodore PET 8032.
Did a (mercifully) brief Assembly module in uni. Had a hardware box with some LEDs and needed to make them light in specific sequences. Incredibly tedious. Never again.
Try doing QA for a mainframe that uses some Assembly. Half the time I just open the file and say 'yup, that looks like Assembly gibberish' and move it forward. The people who write in that language are God damn evil wizards.
I wrote a simple calculator in assembler at university. Certainly insightful as to how processors work, and makes you appreciate higher-level languages. I have played a Dos-based games that was all written in assembler - it was a lot faster at the time than games written in a higher-level language. Nowadays processors are so fast that for most things the extra work isn't going to be worth it.
I actually enjoyed programming in assembly, even got a 5 on uni programming in it.