Undocumented 8086 instructions, explained by the microcode
righto.com
righto.com
I remember this.
Once ... gosh, it's hard to believe how long ago that was now, but once I knew the entire Z80 opcode table off head. I could read the Z80 machine code and disassemble it. High school crowded that stuff out of my head, I went to a special math school, it was very very hard. Except... C9 was RET (and the Z80 is an extension of the Intel 8080). That has burned into me so deep I still remember, across more than 35 years. I will be 30 ;) years old in two weeks.
A000 for example I recognize, but can’t tell you as quickly what it is in decimal as I can with C000.
0xA000 = 0xA × 0x1000 = 10 × 0x1000
and I guess you know 0x1000 = 4096 95 ba 07 01 cd 21 c3 48 65 6c 6c 6f 20 77 6f 72 6c 64 21 0d 0a 24Like, you can look at a string of opcodes from a processor that you haven’t touched for a decade-plus, and still recognize what’s going on.
It’s important to remember that applies in all fields.
That bumpkin that grew up on a farm?
Sure, he might not be able to write an award-winning essay, but he could probably tell you everything you need to know about your local soil chemistry and it’s suitability for various crops just by smelling it.
I immediately recognized the opcodes on it because I knew Z80 and they were in 8080 (I don't remember seeing any ED B0 or similar Z80 extensions). 01, 11, 21, C3 and CD’s all over. I think it was either a boot loader or a BASIC ROM startup code, but not sure.
8080 probably implies Altair BASIC because there was “(C) MICROSOFT” string in the code.
I couldn't afford a printer.
I grew up behind the Iron Curtain, the ZX Spectrum we had was smuggled into the country by my parents in 1985. What printer...? There was no printer to buy! More, we were soldering the data cable when it broke because what today looks like a bog standard 3.5mm mono cable was impossible to replace. It was not available and that was the end of the story.
Also, SALC is still technically undocumented by Intel (AMD documents it, though). It doesn't have a dedicated section in the SDM (would be in Volume 2, Chapter 4), and in the opcode map (Volume 2, Appendix A), there's a blank there. One actually has to go to Volume 3, Chapter 23 "Architecture Compatibility", Section 15 "Undefined Opcodes" (of version 080 from June) to see it mentioned. It's weird. They even call it out as SALC "when not in 64-bit mode" and that it performs "IF (CF=1), AL=FF, ELSE, AL=0", but refuse to officially document it.
The 6502 on the other hand, didn't take such precautions. There are opcodes that cause the internal timing state machine to sort of fall off the end, causing the CPU to lock up and even an interrupt won't rescue you. You need a RESET signal.
> With the advent of the MC6800 (introduced in 1974), a design flaw was discovered by programmers. Due to incomplete opcode decoding, two illegal opcodes, 0x9D and 0xDD, will cause the program counter on the processor to increment endlessly, which locks the processor until reset. Those codes have been unofficially named HCF. During the design process of the MC6802, engineers originally planned to remove this instruction, but kept it as-is for testing purposes. As a result, HCF was officially recognized as a real instruction.
https://en.wikipedia.org/wiki/Halt_and_Catch_Fire_(computing...
The show feels like if you were supposed to take It's Always Sunny seriously, for drama. Meanwhile there just happens to be 25 years of computer history occasionally shoved into the background, that magically is the fault of the same like four people.
https://en.m.wikipedia.org/wiki/Halt_and_Catch_Fire_(computi...
although by the time I got to computing, the HCF didn't actually cause conflagration.
I think I recall a 1960s computer design that would poll a limited set of (magnetic core) memory addresses in its idle loop, which led to overheating in those memory elements. Boot loader for PDP-8? I don't think it was the CDC-6600...
Random thing: chip transistor counts usually count "transistor sites" rather than physical transistors, so the omitted transistors still show up in the transistor counts.
Reminds me of the MEMPTR on Z80: https://gist.github.com/drhelius/8497817
Also, I'm not sure if you've explored 8f/1-7 yet, since it's not mentioned in the article, but I suspect it's just the same as pop r/m16 (8f/0) as it ignores the subopcode bits completely. It's very weird that the push and pop are in completely different places in the opcode map.
Are they? There's a lot of different opcodes for push and pop, but if I'm reading right, for a given address mode, the op code for push and pop always differs by one bit (which bit changes though)
https://www.felixcloutier.com/x86/push https://www.felixcloutier.com/x86/pop
I agree that it's very weird that PUSH rm and POP rm are arranged completely differently. The obvious place to put POP would be in FF/7, especially since that spot is unused. I can't think of any reason why they wouldn't do that.
That's what Andrew Jenner's emulator code does.
https://github.com/reenigne/reenigne/blob/master/8088/xtce/x...
Line 3049.
It's less about the content creators and more about supporting a system / business model that isn't really sustainable and reliant on business practices that distract and in many cases actively harm consumers. Most content creators have Patreon profiles or some similar service for taking donations in a structured and community-driven way, why don't you use an adblocker and donate there?
I use 1Blocker. It’s made of several extensions, only one or two non-essential ones that are not pure content blockers (and so can read the site), and which I have turned off, with still very good results.
Clearly some portion of the HN audience might be unaware, as they are in this thread complaining about ads.
1. Either they block the ad, in which case no revenue anyway.
2. Or they don't block it and it looks like an ad ridden site at first glance, so makes some people kneejerk close it.
Unless you were about to donate a few pennies to the author, I'm not sure "freeloaders" is the audience they were aiming for.
I disagree. The vast majority of the internet doesn’t care, because it’s the internet and this is normal.
The types of readers who will read a blog post and critique the author for things unrelated to the content of the blog (such as the presence of ads) are generally not a great audience to cultivate, and definitely not a great vocal minority to cater to.
There are numerous examples of YouTubers being hesitant to turn on ads in their early days because they think it will drive away potential subscribers and drive down view counts. Then they turn them on eventually, growth continues exactly as before, and their only regret is not turning them on sooner.
Be careful not to mistake the vocal minority’s complaints as a common concern.
>even being able to tell that a website has ads
Wew
Similarly, not having https properly configured is a huge turnoff - it literally takes 5 minutes with LetsEncrypt
One thing I'm thinking about: I grew up writing 6502 assembly on the VIC20 and C64. We hated the 8086 back then, as kids do with hardware. When growing up I saw that we were partly right. The 6502 performed very well compared to the IBM PC on practical tasks. But the 6502 is a dirt simple, while the 8086 is surprisingly complex. Was the PC slow due to 8088 and not 8086?
I can of course just Google it or check the op code table. But always fun to talk about old technology :)
For the 286, do keep in mind that prior to IBM releasing the PC-AT, no one at Intel likely considered that anyone would want to use their newfangled 286 as nothing more than a "fast 8086". It appears that Intel's plan for the 286 was that everyone would also have a 286 protected mode OS to run upon it, and 8086 real mode was included only for the purposes of setting up the minimum necessary protected mode data tables to enable a switch into protected mode. This is one of the reasons why the 286 provided no documented way to leave protected mode once the OS flipped the PE bit in CR0 to 1. And, in 'protected mode' one has to provide protection against executing invalid opcodes for it to be properly a 'protected mode'.
The fact that most 286 system purchasers were running their shiny new 286 as nothing more than a fast 8086 for many years probably caused much more consternation at Intel than the fact that the [12]86's generated exceptions for undocumented 8086 opcodes.
attempting to set the PE bit back to zero has no effect:
> The CPU is put into protected mode by setting the PE bit in MSW using the LMSW or LOADALL instructions. Clearing the PE bit has no effect using either of those instructions, thus it is not possible to switch back to real mode.
The 80_68_'s microcode ROM
I'm curious how Motorola's circuit design and approach differs from Intel's.
This has been a niche programming challenge which was popular before I knew it existed, so I upped the ante by using alpha-numeric only.
The usable opcodes where practically IMUL and XOR with severe limitation on registers and offset. But with them I managed to create a random number generator that magically outputs fragments of codes at the location where the next instruction would be located. This would snowball adding more opcodes/functionality as it unrolls into a complete application.
It felt like the instruction set was so restricting and that the designers of the instruction set deliberately mapped the most critical instruction to make this possible to the opcode values. This has made me wonder what the considerations were to select which binary byte value to match with the instructions. if MUL/XOR were mapped differently, this project most likely would not have existed.
Synchronicity in overdrive:
https://xyzzy.github.io/smile/README.htmlVideo: https://youtube.com/watch?v=LA_DrBwkiJA
Paper (PDF): http://tom7.org/abc/paper.pdf
Paper (TXT): http://tom7.org/abc/paper.txt
Compiler (EXE): http://tom7.org/abc/paper.exe
Editted: What you reference to is a compiler and something completely different.
These are two different projects with different design goals and challenges. Tom's built a compiler around it, I created a bootloader that consists of only MUL and XOR.
I don't understand why I feel that I have to defend myself, I thought hackers love these kind of projects, yet it seems I got cancelled.
A true innovation would be to combine both projects. One that inputs source code plus an image and outputs ASCII art that runs like a program.
Holy hyperbole captain. Apparently not being heaped in praise and getting the usual amount of hyper cynical HN criticism is "being cancelled" now.
That was fixed (either in microcode or hardware) on all later generations. And the 8086/88 did the check in the CORD subroutine of course, which is used by both DIV and AAM.
Multiply/divide is now assisted by the ALU, so the microcode mainly has to set up the registers and do the check for zero divisor / overflow. There is also a final adjustment to the result, because the hardware uses a non-restoring algorithm that may underflow. And for signed division, the operands are converted to unsigned first and the result possibly negated at the end, using the F1 flag to store the sign like on the 8086.
The 286's instruction decoder and microcode ROM are entirely different: 1536 words of 35 bits, with the entry point determined by a separate PLA.
It's a bit confusing because microcode has changed meaning a bit over time. "Classical" microcode, such as the 8086, replaces hard-wired control logic with micro-instructions. The processor steps through the appropriate micro-instructions, which are decoded to generate control signals.
The Pentium Pro introduced a new model, where machine instructions are broken down into independent micro-ops, which are handed off to the core processor engine and processed independently, in parallel. At the end, the micro-ops are "retired" in a sequential order, so your program appears sequential.
Most micro-ops are generated by decoders that convert a machine instruction into a small number of micro-ops. However, complicated machine instructions are converted into micro-ops by microcode. This is similar to classical microcode, except it's not executing micro-instructions but generating micro-ops that then get run by the underlying processor.
https://www.youtube.com/watch?v=dXdoim96v5A
That is the start of the videos where the control logic gets microcoded. Its pretty basic but over the next few videos he comes up with about 10 different OPCODES and programs their microcode (a series of control logic activations). Its pretty amazing to see it all come together and work in the end.
If you want to learn about simple microcode and how a (non-superscalar, which matches the 8086) CPU generally works, this is a brilliant resource, and fun to watch.
Provided you can find a copy, the book "Computer Organization", 2nd ed, by V. Car Hamacher, Zvonko G. Vranesic and Safwat G. Zary, published by McGraw Hill, contains a very understandable chapter of microcode control. Depending on your background, you may want to read some of the prior chapters first before starting on the microcode one, to get some foundational knowledge.
Do note that the 2nd ed was published in 1984, so finding a copy may be difficult. I do not know how (or even if) the microcode control chapter was updated in subsequent editions.
For example, 'ADD AL,CL' can be encoded as (values in octal):
000 310 : 3=reg/reg 1=source is CL 0=dest. is AL
002 301 : 3=reg/reg 0=dest is AL 1=src. is CL
Other assemblers always use one of these consistently, A86 switches between them depending on some bits of the opcode and operands (but each instruction will always be encoded the same when it appears multiple times, there is no steganographic message embedded).Not actually in the AX register but in a tmp reg, right?
MOV CS, AX
0F.