Hehe, thanks. I really have no experience with it. I tried to learn about the instructions in the area that was interesting, but without the help of my viewers, I wouldn't be able to do this myself!
@@bitsundbolts I've been experimenting with 6502 lately because of some Famicom games and ChatGPT has been super helpful in helping me understand some routines and some basic asm. You just paste the whole thing and it will analyze it for you. It makes mistakes sometimes, so beware.
And you know what? I absolutely love it! It is not that easy to understand and I feel you need to know a lot that is not mentioned anywhere (like port 0x70h, 0x71), but I am willing to learn more and get better! Assembly language allows you to do really amazing low level things!
@@bitsundbolts It's definitely not easy. Plus you have to understand (at least for x86 assemly) what are the differences between ports and memory addresses, memory segments, segment registers, stack, stack pointer etc etc. Later you can explore the 32 bit subset (386 specific) registers like EAX, EBX etc...
I already saw examples of register segmentation. It's quite fascinating. EAX, AX, AH, AL... It's still all new to me, but that's as far as I got. I'll definitely continue to learn. It's so different from the languages I'm used to - and that's what's exciting ☺️
AMD were truly ahead of their time. Heck, this predates even their groundbreaking K5, which introduced the concept of translating x86's CISC instructions to be executed by a RISC backend (which in the K5 was based on AMD's own 88K RISC architecture).
Ok, new challenge: You know for sure that modbin can calculate a new checksum. It does so when saving the file. Can you mod modbin so that instead of showing an error, it just fixes the checksum?
Well, it clearly calculates the checksum - otherwise, modbin wouldn't know that something is wrong with the checksum. It's an interesting idea and definitely a great challenge. I know that I'm not there yet, but I'll try to do that some time! At least to maybe output what checksum was expected!
@bitsundbolts it could be easy, with some luck. I presume the program opens the file, and then calls a function to verify the checksum. If that is the case, the function would return something to indicate failure or success. If this is the case, all you would have to do is replace the call instruction with a jump instruction to the right place.
@@jbinary82 Safer? Yes, for sure. Easier? Not at all. To change a call into a jump, you don't have to change a lot. You only replace a few bytes, and the number of bytes doesn't change. Both are simple opcodes that take an address as parameter. But to print something, that takes a lot. First of all, you have to know where to find the actual checksum. That is a variable somewhere in RAM, and since you don't have the labels from the source, you don't know where it is. Then you want to convert that binary number into something readable, like a representation of the binary value in hex using ascii characters. And then you have to call some sort of print function.
such convoluted code to make it always display 256K... at address 02510 they could have simply changed the "mov cl,al" to a "mov cl,5"... no need to make extra functions or change jumps.
Guess that extra function would make it easy to find and change the value for other variants of the fake cache board. Wonder if the seller even knew the cache chips were fake.
checking for 5 and then overwriting anyways is interesting, yeah 😅 also wondering why al is decreased before shifting 0x10. could also just shift 0x08 by al directly 🤷🏻♂️
based on what I've learned in 6502 assembly, I'd search for the "cache memory" string like you did, but then I would take note of the memory location and then search for that memory location being referenced. That would get you that mov instruction. I could then look at the code at the address of the call immediately after it.
This. Modern reverse engineering tools like IDA or Ghidra make it pretty easy to do. I actually find it rather weird that in this BIOS, the strings are stored just next to their usages in code, modern compilers almost never emit code like that.
@@SianaGearz Probably. But most hand-written assembly I've seen also put constants outside of function bodies. There's nothing wrong with putting it inline, especially when you're not very concerned with speed and/or targeting a CPU that doesn't have a ton of pipelining - and the routine for printing the system summary screen in a 486 BIOS fits both of those descriptions. It's just... weird.
@@kFY514 I found it odd as well, but I'd actually be surprised if it was compiled (well other than an assembler). It was probably written with strings and code mixed in the original assembly file.
The addressing modes supported by x86 assembly are so varied and "baroque" that it could be hard to find the code referencing the string by knowing just the address. In this case it was rather direct, but it does not have to be.
The checksum check is actually quite simple. All that is done is to add up all bytes in the ROM and test if the result is zero. So you basically have to set the last byte of the ROM (or any other unused byte) to 256 - [sum of all the other bytes]. That's all.
The question is: which bytes. I don't think all of them are used to calculate the checksum. Or is it just the last byte that is excluded as it is the checksum.
@@bitsundbolts It really includes all the bytes of the whole ROM. Let's say you've changed a 04 to a 06 somewhere. Then the ROM would add up to 2 instead of 0, making the check fail. So you change the last byte from e.g. C9 to C7 (subtract 2) so the sum of all the bytes equals to zero again. In this example, if you would take the sum of all bytes but the last one, it would add up to 39h, or 57d. If you subtract this from 100h or 256d you'll get 199d or C7h, which is what you need to put as the last byte so the whole ROM adds up to zero again. Sounds more complicated than it is :D
I think this is what I'm doing with that excel sheet. It does exactly that. It records the changes (calculates the difference in bytes recorded) and outputs the new checksum relative to the existing checksum. So, it calculates the checksum based on the DIFF.
Really great job and very interesting. I do low--level bootloaders for embedded ARM based products, which are less complicated (less peripherals to handle), but it is funny that such simple checksums were deemed adequate back then. Really curious on stuff such as the Energy Star logo ... is that stored in the BIOS image as well, and how would this be rendered?
I have a video on my channel in which I show how you can change the BIOS logo. If I recall correctly, the logo is converted to characters and then displayed in text mode. The top lines are all yellow for the EnergyStar logo, and the bottom line is green to show "EPA Pollution Preventer". I don't remember everything, but there are tools that help you convert images to BIOS logos.
The issue you might run into with decode is you need to tell it where to start. IE that text at the top is not instructions, so decoding starting at byte 0 will give 1 set of instructions, but decoding starting with byte 1, will give you a completely different set of instructions. This is because instructions are variable length, so the disassembler may not align with the beginning of an instruction.
A small hint that could've helped avoid some work/uncertainty: strings will often end in a 0 byte, so at 0x20 0x00 at the end of the cache memory was very likely not an instruction and it was definitely starting instruction decoding with an instruction at the 0x00, and it's unsure when a disassembler will happen to fall in line with the instructions, if it ever would. Lots of little patterns like that to figure out over time. Kinda wacky it checks for if it's 5 just to set it to 5. Not even well-coded lies. :p
At around 18:00 the reads and writes are to ports 0x70 and 0x71 and to port 0xE1. I/O ports 0x70 and 0x71 are used to read and write data from/to the CMOS RAM. Writing to port 0x70 causes whatever is put on the databus (in this case the contents of register AL) to be latched in the CMOS RAM address register. The CMOS RAM address selected is 0x3a. Bit 7 is set to disable the NMI circuitry. (this results in the NMI, or non-maskable interrupt being masked). The read from port 0x71 reads whatever value is stored at address 0x3a in the CMOS RAM. The venerable I/O port listing from Ralf Brown's Interrupt list does not document this CMOS RAM location for Award BIOSes, but it does document the next address, 0x3B, for which bit 0 is reported as enabling the external cache (or at least in configuration). I/O ports 0xe1, 0x22 and 0x23 (the ones in the routine directly following the one being examined) are all reported by the same I/O port listing as for reading and writing chipset data. However, my guess is that I/O port 0xe1 somehow deals with setting the cache size for the chipset (so it basically copies over the configuration setting in CMOS RAM over to the chipset). The or al, al right before the retn instruction makes sure the zero flag is set if the contents of al are zero. The conditional jump in the calling code (jne - jump-if-not-equal, aka as jnz - jump-if-not-zero) simply checks the zero flag and branches if it is not set. In other words, if whatever is returned in al by the function at 0xa8a0 is non-zero, it simply skips over the next stream of instructions, to addres 0x2433. Since at 0x2433 cl is loaded with the contents of al and then decremented. Then, ax is loaded with 0x10 (16 decimal) and ax then gets shifted to the left by cl bits. This value is then printed and a 'K' gets added after it. So if the return value (in al) was 1, the number of bits ax gets shifted to the left is zero, if it is 2, it gets shifted left by 1, etc. In other words: the value stored at 0x3a in the CMOS RAM tells us that we have 16*2^cl K of cache RAM. If it's 1, we have 16k; if it's 2 we have 32k, and so on. Ultimately what the hack at 0xDF00 in the v2 BIOS does is call the original routine (albeit at a different address) and if whatever the routine returns is not 5, it gets "corrected" to be 5 and the control is returned to the calling code.
Hi, if you want to to dig deeper into reverse engineering, than I would recommend tools like the free Ghidra, the free version of Binary Ninja or the free version of IDA Pro.
In the meantime, I installed both of those programs :) Unfortunately, Binary Ninja is a bit confusing with all the different windows, but I guess I will get used to it over time.
I'm fairly sure a lot of those kinds of tools don't work for 6502 machine code, though I've never tried it, so I don't know. Though I'm fairly sure IDA does support older instruction sets, not sure about 6502 though
@@nikkiofthevalley Ghidra supports 6502, IDA and Binary Ninja support it only in the paid versions. But the BIOS file was/is for x86, which is supported by all three.
I am pretty sure that the checksum at the very bottom of the bios code is not there as any sort of copy protection but probably as a way to verify that all bytes were written to rom correctly. Its either used as a verification during boot or probably during write when doing a update.
lol I feel your pain. After a few years of watching youtube videos I feel like I finally am starting to understand 6502 assembly language. And assembly is unique to each CPU.
It is true that assembly is unique to each CPU, but it's kind of like with programming languages in general - you get familiar with one or two, and all the others become almost effortless. Not that there aren't any gotchas, though, like the MIPS delay slot (which can be extra confusing considering that _some_ assemblers take care of it, while disassemblers generally don't).
Very interesting how naive the original hack was. To check for matching 0x05 before replacing anything else with 0x05 shows a lack of understanding. A normal override for this would simply always replace whatever was there with 0x05. Replacing 0x05 with 0x05 is fine and would not do anything and thus only require a single line. Technically the hack could have been done without a new function also by exploiting the code that reduced the value from 0x05 to 0x04 before using it to shift. This could have simply loaded 0x04 directly, ignoring everything the call returned. Alternatively using the space for the shift operation as well we could simply load the desired 256 result.
That would have been the quickest and shortest way to get this BIOS always return the value those people wanted to have the BIOS return. It would even call the original function that seems to be important (or maybe it isn't).
It might be a bit of trickery to hide it when (hardware) testing the code? As example: It does check the cache memory on a hardware level but then ignores it completely in the code so with hardware testing it gives the right signals on an electrical level?? Bit like the Volkswagen scandal, the car knew when it was being tested and went into a "compliant" program so it passed the test.
@@samuraidriver4x4 But that's just it, the extra stack level and call could have been caught by testing. The result is also returned in a register so unless you specifically looked for a read from that register after a certain number of instructions upon returning you would never be able to tell. The register is used a lot more later.
You can't "decode" a string to anything useful, it's plain data, not CPU opcodes (operation codes), you need to find the code that make use of that data. You can see that the hex values for those "instructions" are actually the letters in your string (grab an ASCII chart and check). You're actually very lucky you found the reference immediately after the string, this is often not the case.
The modified routine that checks if the value matches 0x05 and then sets it if it doesn't, would it not have been simpler (and very slightly more efficient) just to set the value without checking it since this would save a few clock cycles? I get the way they've done it seems a "better way" but in terms of efficiency it achieves nothing. Anyone else manage to follow this a lot better as you've too watched Ben Eater's various tutorial videos? And if you haven't you 100% should!
@bitsundbolts I learned a LOT from his videos. Especially how computers work with the 6502 project, where he builds incrementally explaining each step in succession starting with basic logic gates. Can't recommend them highly enough.
In the hacked BIOS, what's the point of checking if AL was 0x05 only to set it to 0x05 if it wasn't? The only reason I can see this process at 0xDF00 being useful, is if the returned flags can be used to tell if AL was originally 0x05 (ZF=1) or if it was hacked to 0x05 (ZF=0).
ZF is zero flag, isn't it? I stumbled across this already. That extra code and function doesn't seem to serve any purpose from what I've seen. I guess it's just a way to implement it. And think about it, that code was not meant to be seen by anyone else 😊
There is a really great tool called Compiler Explorer, wich you should try out if you want to learn more about assembly. Also assembly really isnt to complicated to read. There is the mnemonic, which represents the type or operation the instruction performs and then there are the operands, which are either registers or memory locations.
I'll have a look. What I've seen is that not every disassembler can work on BIOS files. Some expect windows executables. I will spend some more time on this topic.
Well, without your help, I wouldn't be able to make this video! It took some time, but I definitely appreciate that disassembled code you provided! Well, it was very useful and now we have an unmodified BIOS. Who knows, maybe there are other boards and BIOSes out there with the exact same code!
There are plenty of comments about the redundant code at 0xDF00, but can we take a second to mention the code that decrements cl before using it to shift al (which was just loaded with 0x0010). If al was loaded with 0x0008 instead the dec would not be required. dec uses 3 clock cycles, where-as the shl uses 8+4-per-bit cycles, so the dec is one cycle quicker I guess _shrug_
Great explanation. I never touched a BIOS but on my to-do list is to mod a BIOS for a motherboard to be Win2k compliant and to accept HDDs larger than 8G. Is there a cache capacity that is right for a certain memory size? I remember that on my 486, having 512K cache, the computer was slower with 4M RAM than with 32M RAM. Not sure if I remember correctly.
Could it be that you meant it was slower with 32MB RAM than with 4MB? It could be that the cacheable memory area was the issue and only half of the memory was cached, but it sounds unlikely with just 32MB. Or the TAG RAM was too small for that big cache size. I wonder how difficult it is to fix the 8G HDD limit on a BIOS like this.
Very Interesting on finding the bypass. But I have to say it was humorous watching your naive understanding of assembly. There is a difference between code and strings, most of what you were trying to decode were strings which would give you undecodable gibberish -- because it is not code! Basically, the code was really had a jump over a string of characters "Cache Memory : " then an instruction to load the beginning of the string into register SI, then a call to a pair of subroutines to output that. Finally a routine to blank register AL and figure out cache size and then the bypass that you found that calls the real routine and then bumps the al to 5 (256K) if the cache is actually 0.
I find the mix of data and code unusual. In modern binaries the data and code live in separate blocks (for multiple reasons) and are not mixed together in this way.
I don't understand why the pirate patched bios checks for 05hex after the original code is called by the new routine. Call the original code to preserve the hardware behavior then load 05h on the register and return. Check the original value to to skip is a utterly moot point.
Who knows. It is odd to have the check there and then overwrite only if it is not equal to 5. Maybe a coding style. Don't update the register if it already has the value you need.
@drewnewby there the code only runs once, it just wastes space with something a single instruction can do. Calling the original function before is understandable as it may be important for initialization, that part is actually fine.
@leonardoliveira There's a difference on vintage bare metal between more code and how fast an operation takes to complete. Less code is not always faster of course.
I was wondering if you had any suggestion from your video (Voodoo VGA Loop Cable Repair) I left a message there too. I am looking to repair vga loose wire on my wacom cintiq 21 UX monitor. And was looking for any suggestions. Thanks
Haha, I hope it is because you like it so much - squeezing out the bad code via a disassembler :D (and not because it is confusing an my explanations are horrible)
@@bitsundbolts Exactly. I've just had to skim it due to lack of time for the time being and leave pondering for later. RE content is fundamentally always welcome, though i suppose it could be a hard sell for some other part of the audience.
@@bitsundbolts What i did notice is that you haven't spotted the end of the string where you inspect "cache memory", the 0 terminator slipped into the decoding of the next instruction in hiew, thus making that decode junk. Classic code-data disambiguation problem. It obviously finds its footing eventually so it hasn't actually interfered with what you were trying to find but given x86 has variable instruction length, it can take a while.
Yeah, it was hard finding the end of the string and the decoded instructions didn't always make sense (e.g. the string turned into instructions). I skipped over the parts that weren't that interesting - and I already knew what I was looking for. However, I still wanted to understand what's happening and why we get 256K displayed in the summary. The video is doing well, so, RE is maybe not such a bad topic from time to time.
Making it show 32M cache was awesome. Next level awesome would be to make it show, instead of 256K or any value, the text "FRAUD". Ultimate level awesome would be to make it display, instead of "DEEP GREEN PC BIOS", "DEEP FRAUD PC BIOS", with the original false 256K cache display.
Hehe, that is easily possible with modbin. You can easily change this message in the original BIOS that always shows 256K L2 Cache. It definitely is a fraudulent BIOS
@@bitsundbolts I'd love to see a follow-up video, or even a short, where you do that. I've read about and seen videos on these fake cache motherboards before, but you went orders of magnitude beyond those 'there were these fraudulent 486 motherboards with fake cache' videos, etc. to digging into the actual BIOS code. I think you're now the world expert on these fake cache boards -- I think only the original perpetrators of the fraud might know more.
Haha, thanks for saying that I'm an expert! I had a lot of help from my viewers who did most of the work - I just made the video. I guess I was lucky to find such a board at the scrapyard! Fully loaded with fake BIOS and fake cache chips!
@@bitsundbolts True - you and those viewers are the collective global experts on these. Though recording, editing and publishing a video isn't trivial, so you all deserve credit. It's seriously impressive, so far beyond and deeper than anything I've ever seen on these. And it really would be awesome to see a capture of the BIOS splash screen with "FRAUD" on it. Wonder where those fraudsters are today....
Glad to hear you enjoyed the video. It definitely takes a lot of effort to put it all in a video, but it is also very rewarding each time a video is ready for upload! Maybe I get to change that BIOS message in one of the upcoming videos when I work on that board again.
It was part of a scam that made customers believe to have cache in the system even though there wasn't. To make sure the trickery isn't easily discovered, fake cache chips were placed on the board. Those cache chips just looked like real cache chips, but there wasn't any silicone die inside. So, just a plastic housing with metal legs to give the illusion cache is installed. There is already a video about this on my channel. This BIOS code helped scamming people.
@@bitsundbolts Although I understood every BIT of what you were doing, I didn't know WHY. A 25 year grudge? Revenge? Thanks for clearing that up, and good job.
Well, it worked. My criticism would be that just because the computer is from ~1995, you didn't have to behave like you were also in 1995. IDA or Ghidra would have been more appropriate tools
I have no experience with those tools as of now. I started to look at other tools to disassemble code. Yes, the newer tools are way more capable and helpful.
If you're referring to BIOS v1.2 and v2.01, then there will be a lot of differences. Both versions differ significantly. I'll try to point this out in another video in the future. Seems like v1.2 is a lot older.
A set of video converters: VGA cable to OSSC (open source scan converter) and then HDMI to USB capture card to get the signal into OBS. The HDMI to USB was difficult to find. I had to test at least 10 different devices to find this one. Even Elgato Camlink 4K doesn't work owith those old and small resolutions.
Haha, I was checking out a PCChips M507 motherboard, with fake cache chips. So fake that they are even poorly soldered. I thought someone had tried to increase the cache and had made a mess, what could I do to fix it? But then I saw that the lines didn't go anywhere, and then reading about this motherboard, I understood what a scam that cache was.
Its looks as though 24CE is writing the text to the screen to me. 24CE inc bx inc = increment bx is the function jump through the function until something (without the function its impossible to know what), so probably write the characters until the : Just a guess though, like you, I know VERY little about ASM 😆 Edit: I swear I don'y know yet (I'm at 8 minutes right now) but I'm guessing [si] is the variable/register/Idontknowassemblyterms that calculates or stores the cache. I guessing this because it gets "and"ed to what I think is the screen write function.....
32 Mb of cache... Seems like you gave it a bit of a modern chip there for a brief moment. Seeing as you theoretically can install Windows 95 in the cache alone if it was supported on some chips.
I've often wondered what would happen if you replaced RAM with cache. Of course now days it's not that big of a deal. RAM is actually faster than CPUs now. They have 10ghz ram now!! it's insane.
@@bitsundbolts The thing that really shocked me is when the memory address in the call command doesn't match the actual memory address. Ohhhhhh intel what the hell did you do? LMAO In 6502 the address is the address is the address. That's the way it should be.
@@awilliams1701 It's a relative call, it doesn't use an absolute memory address but a signed offset. So you tell the CPU not where but how far to jump.
@@kpanic23 I guess in the end the actual assembly would be something like "Call cacheDetect" and "cacheDetect" would be resolved by the compiler, but that seems rather silly to me. I can see some cases like a for loop where that would make sense. If you only need to jump relative with numbers that fit into 8 bits then sure (like a 6502's zero page), but more than that? Might as well just use the actual address at that point.
I'm sure it's possible. For one, you can add your name easily with modbin. You can also replace the BIOS logo (there is already a video on my channel, but an old one).
Is this a modern thing (as i people selling crap ro collectors) or a historical issue meaning my 486 i was running back in they day may never have had 256kb cache?
It's a historical thing. I found this motherboard at the scrapyard - nothing special except for the fake cache chips I made another video about - and the BIOS that always reports 256k of level 2 cache. The chance that you never had L2 cache in your 486 is not zero.
@bitsundbolts oh wow. Hey, thank you so much for this informative content. It's definitely something I'm gonna watch out for when I build my next retro gaming rig!
Very nicely explained! The original patch seems pretty damn stupid, patching in another function to return 5 instead of just replacing the call with a mov al, 5. Unless there is a consequence of not checking the cache size. Even then the compare in the patch is redundant. 😂
I was going to comment the same thing. The entire “patch” they made is entirely unnecessary. Comparing to 5 and then replacing al with 5 if not is the mark of someone who has programmed a lot of assembly.
Amd Ryzen 9 3900X has 4 x 16MB of L3 cache - 16MB per CCX, 32MB per CCD, 64MB in total, NOT 32MB in total. 32MB of L3: R7 3700X, R7 5700, R7 7700X and R7 9700X
They were a bit wasteful with their code! If you are going to always change AL to 0x05 then why check it's 0x05 after the return from the original code at all? No point checking if AL is 0x05 and skipping changing it if it is, that makes more code, not less. They should have just called the original routine then set AL to 0x05 before returning to the calling routine.
Assembly language of x86/AMD64 is a disaster. One of the messiest out there. Over the years I got to know it pretty well and I wouldn't recommend it for someone just starting to learn asm. I wouldn't recommend any CISC for that purpose. RISC architerctures like MIPS, AArch64 (64 bit ARM; 32 bit is a little bit messy too), RISCV, etc., are much better starting point. 8-bit microcontrollers are good for learning too.
Thanks for this information. I started an online course that I can hopefully finish soon. I will keep this in mind and probably have a look at cleaner assembly before it gets frustrating.
@pvc988 Same, go with CISC, suffer as we did decades ago. Assembly is a product of it's time regarding x86. I'm sure RISCV is cleaner, as OP mentioned, but I'm not sure how that's helpful in the context of this channel's focus.
I have come to really love Z80 assembly. It was binary compatible with the 8080, but the intel mnemonics are horrible. The language for the Z80 is much better. I believe it was specifically designed to be easy to learn.
wow you know something sucks when I'm calling it out in a language I know nothing about. first it compares then it returns if if it's fine. Otherwise it sets it equal, then it returns. Why doesn't it just set it equal and return? lol completely redundant code.
oh and if you're overriding the number why are you calling 9e23 in the first place? sigh..... Seriously all the fake function needs is "mov al, 005" and "retn"
For someone claiming to not know x86 assembly you did great :-)
Hehe, thanks. I really have no experience with it. I tried to learn about the instructions in the area that was interesting, but without the help of my viewers, I wouldn't be able to do this myself!
@@bitsundbolts I've been experimenting with 6502 lately because of some Famicom games and ChatGPT has been super helpful in helping me understand some routines and some basic asm. You just paste the whole thing and it will analyze it for you. It makes mistakes sometimes, so beware.
Great job. Nice to see you tip your toes in Assembly language.
And you know what? I absolutely love it! It is not that easy to understand and I feel you need to know a lot that is not mentioned anywhere (like port 0x70h, 0x71), but I am willing to learn more and get better! Assembly language allows you to do really amazing low level things!
@@bitsundbolts It's definitely not easy. Plus you have to understand (at least for x86 assemly) what are the differences between ports and memory addresses, memory segments, segment registers, stack, stack pointer etc etc. Later you can explore the 32 bit subset (386 specific) registers like EAX, EBX etc...
I already saw examples of register segmentation. It's quite fascinating. EAX, AX, AH, AL... It's still all new to me, but that's as far as I got. I'll definitely continue to learn. It's so different from the languages I'm used to - and that's what's exciting ☺️
@0:15 Oh look, it's the famous 486X3D CPU :D
AMD were truly ahead of their time. Heck, this predates even their groundbreaking K5, which introduced the concept of translating x86's CISC instructions to be executed by a RISC backend (which in the K5 was based on AMD's own 88K RISC architecture).
Im actually surprised with how clean the modified function was done
GREAT job at fixing the bios though 👍
really? I'm wondering why it even tests for 5 before overwriting it with 5 anyways. could just overwrite it 😂
@@RoterFruchtZwergyes that's kind of weird
Very nice logical fix from someone who claims not to know any assembly. Give yourself a pat on the back mate, really enjoyed watching this one.
Thanks! Happy to hear you enjoyed my first steps in assembly language 😅
Ok, new challenge:
You know for sure that modbin can calculate a new checksum. It does so when saving the file.
Can you mod modbin so that instead of showing an error, it just fixes the checksum?
Well, it clearly calculates the checksum - otherwise, modbin wouldn't know that something is wrong with the checksum.
It's an interesting idea and definitely a great challenge. I know that I'm not there yet, but I'll try to do that some time! At least to maybe output what checksum was expected!
@bitsundbolts it could be easy, with some luck.
I presume the program opens the file, and then calls a function to verify the checksum. If that is the case, the function would return something to indicate failure or success.
If this is the case, all you would have to do is replace the call instruction with a jump instruction to the right place.
These checksums are usually a form of crc, so should be easy to recalculate with python @bitsundbolts
It would be probably much easier (and safer) to just print the expected checksum. Then you could modify it with the hex editor.
@@jbinary82 Safer? Yes, for sure.
Easier? Not at all.
To change a call into a jump, you don't have to change a lot. You only replace a few bytes, and the number of bytes doesn't change. Both are simple opcodes that take an address as parameter.
But to print something, that takes a lot. First of all, you have to know where to find the actual checksum. That is a variable somewhere in RAM, and since you don't have the labels from the source, you don't know where it is.
Then you want to convert that binary number into something readable, like a representation of the binary value in hex using ascii characters. And then you have to call some sort of print function.
such convoluted code to make it always display 256K... at address 02510 they could have simply changed the "mov cl,al" to a "mov cl,5"... no need to make extra functions or change jumps.
That's certainly the quickest way to always show 256k L2 cache. I wish the author of that code would come forward and explain it and him/herself 🤣
@@bitsundboltsI think the author wanted to be at least a little bit obfuscated than straight out lie in front of you ;)
Or even that the function at 0xDF00 bothers to A) call the original routine, B) compare the return value. it could just put 5 into al unconditionally.
Guess that extra function would make it easy to find and change the value for other variants of the fake cache board.
Wonder if the seller even knew the cache chips were fake.
checking for 5 and then overwriting anyways is interesting, yeah 😅 also wondering why al is decreased before shifting 0x10. could also just shift 0x08 by al directly 🤷🏻♂️
Daumen hoch! Nicht schlecht Herr Specht würde ich sagen.
Great job. Now you can claim to know some x86 assembly. 😊 Also explained really well.
Thanks! Glad to hear that it somehow made sense what I say in this video :)
Great Vid , this brings back great memories really enjoyable!
based on what I've learned in 6502 assembly, I'd search for the "cache memory" string like you did, but then I would take note of the memory location and then search for that memory location being referenced. That would get you that mov instruction. I could then look at the code at the address of the call immediately after it.
This. Modern reverse engineering tools like IDA or Ghidra make it pretty easy to do. I actually find it rather weird that in this BIOS, the strings are stored just next to their usages in code, modern compilers almost never emit code like that.
@@kFY514 the BIOS code isn't compiled from a higher level language, it was written in assembler to begin with.
@@SianaGearz Probably. But most hand-written assembly I've seen also put constants outside of function bodies. There's nothing wrong with putting it inline, especially when you're not very concerned with speed and/or targeting a CPU that doesn't have a ton of pipelining - and the routine for printing the system summary screen in a 486 BIOS fits both of those descriptions. It's just... weird.
@@kFY514 I found it odd as well, but I'd actually be surprised if it was compiled (well other than an assembler). It was probably written with strings and code mixed in the original assembly file.
The addressing modes supported by x86 assembly are so varied and "baroque" that it could be hard to find the code referencing the string by knowing just the address. In this case it was rather direct, but it does not have to be.
The checksum check is actually quite simple. All that is done is to add up all bytes in the ROM and test if the result is zero. So you basically have to set the last byte of the ROM (or any other unused byte) to 256 - [sum of all the other bytes]. That's all.
The question is: which bytes. I don't think all of them are used to calculate the checksum. Or is it just the last byte that is excluded as it is the checksum.
@@bitsundbolts It really includes all the bytes of the whole ROM. Let's say you've changed a 04 to a 06 somewhere. Then the ROM would add up to 2 instead of 0, making the check fail. So you change the last byte from e.g. C9 to C7 (subtract 2) so the sum of all the bytes equals to zero again.
In this example, if you would take the sum of all bytes but the last one, it would add up to 39h, or 57d. If you subtract this from 100h or 256d you'll get 199d or C7h, which is what you need to put as the last byte so the whole ROM adds up to zero again.
Sounds more complicated than it is :D
I think this is what I'm doing with that excel sheet. It does exactly that. It records the changes (calculates the difference in bytes recorded) and outputs the new checksum relative to the existing checksum. So, it calculates the checksum based on the DIFF.
Потрясающая работа! Amazing Work!
Put the fixed BIOS into retroweb.
It's already there ☺️
Really great job and very interesting. I do low--level bootloaders for embedded ARM based products, which are less complicated (less peripherals to handle), but it is funny that such simple checksums were deemed adequate back then. Really curious on stuff such as the Energy Star logo ... is that stored in the BIOS image as well, and how would this be rendered?
I have a video on my channel in which I show how you can change the BIOS logo. If I recall correctly, the logo is converted to characters and then displayed in text mode. The top lines are all yellow for the EnergyStar logo, and the bottom line is green to show "EPA Pollution Preventer". I don't remember everything, but there are tools that help you convert images to BIOS logos.
The issue you might run into with decode is you need to tell it where to start. IE that text at the top is not instructions, so decoding starting at byte 0 will give 1 set of instructions, but decoding starting with byte 1, will give you a completely different set of instructions. This is because instructions are variable length, so the disassembler may not align with the beginning of an instruction.
Yes, the tool I'm using here decodes strings into instructions as well. Luckily, I could follow the section that was important for reversing the code.
Thanks for sharing your knowledge
The DF00 ruintine can be eliminated completely. Just replace the call with 9e23.
A small hint that could've helped avoid some work/uncertainty: strings will often end in a 0 byte, so at 0x20 0x00 at the end of the cache memory was very likely not an instruction and it was definitely starting instruction decoding with an instruction at the 0x00, and it's unsure when a disassembler will happen to fall in line with the instructions, if it ever would. Lots of little patterns like that to figure out over time.
Kinda wacky it checks for if it's 5 just to set it to 5. Not even well-coded lies. :p
At around 18:00 the reads and writes are to ports 0x70 and 0x71 and to port 0xE1. I/O ports 0x70 and 0x71 are used to read and write data from/to the CMOS RAM. Writing to port 0x70 causes whatever is put on the databus (in this case the contents of register AL) to be latched in the CMOS RAM address register. The CMOS RAM address selected is 0x3a. Bit 7 is set to disable the NMI circuitry. (this results in the NMI, or non-maskable interrupt being masked). The read from port 0x71 reads whatever value is stored at address 0x3a in the CMOS RAM. The venerable I/O port listing from Ralf Brown's Interrupt list does not document this CMOS RAM location for Award BIOSes, but it does document the next address, 0x3B, for which bit 0 is reported as enabling the external cache (or at least in configuration).
I/O ports 0xe1, 0x22 and 0x23 (the ones in the routine directly following the one being examined) are all reported by the same I/O port listing as for reading and writing chipset data. However, my guess is that I/O port 0xe1 somehow deals with setting the cache size for the chipset (so it basically copies over the configuration setting in CMOS RAM over to the chipset).
The or al, al right before the retn instruction makes sure the zero flag is set if the contents of al are zero. The conditional jump in the calling code (jne - jump-if-not-equal, aka as jnz - jump-if-not-zero) simply checks the zero flag and branches if it is not set. In other words, if whatever is returned in al by the function at 0xa8a0 is non-zero, it simply skips over the next stream of instructions, to addres 0x2433.
Since at 0x2433 cl is loaded with the contents of al and then decremented. Then, ax is loaded with 0x10 (16 decimal) and ax then gets shifted to the left by cl bits. This value is then printed and a 'K' gets added after it. So if the return value (in al) was 1, the number of bits ax gets shifted to the left is zero, if it is 2, it gets shifted left by 1, etc. In other words: the value stored at 0x3a in the CMOS RAM tells us that we have 16*2^cl K of cache RAM. If it's 1, we have 16k; if it's 2 we have 32k, and so on.
Ultimately what the hack at 0xDF00 in the v2 BIOS does is call the original routine (albeit at a different address) and if whatever the routine returns is not 5, it gets "corrected" to be 5 and the control is returned to the calling code.
Thanks for this very detailed explanation! Very insightful!
That MODBIN tool is clearly able to fix the checksum. If only I had time, I could crack it to do just that.
Hi, if you want to to dig deeper into reverse engineering, than I would recommend tools like the free Ghidra, the free version of Binary Ninja or the free version of IDA Pro.
In the meantime, I installed both of those programs :) Unfortunately, Binary Ninja is a bit confusing with all the different windows, but I guess I will get used to it over time.
I'm fairly sure a lot of those kinds of tools don't work for 6502 machine code, though I've never tried it, so I don't know. Though I'm fairly sure IDA does support older instruction sets, not sure about 6502 though
@@nikkiofthevalley Ghidra supports 6502, IDA and Binary Ninja support it only in the paid versions.
But the BIOS file was/is for x86, which is supported by all three.
@@SuperVirus1978 Oh, I thought the BIOS was for 6502 for some reason, I'm stupid haha
I am pretty sure that the checksum at the very bottom of the bios code is not there as any sort of copy protection but probably as a way to verify that all bytes were written to rom correctly. Its either used as a verification during boot or probably during write when doing a update.
Great deep dive with assembly. I’m still at ‘hello world’ 😂
Oh, I have no idea how to make hello world in assembly 😅
lol I feel your pain. After a few years of watching youtube videos I feel like I finally am starting to understand 6502 assembly language. And assembly is unique to each CPU.
It is very challenging!
It is true that assembly is unique to each CPU, but it's kind of like with programming languages in general - you get familiar with one or two, and all the others become almost effortless.
Not that there aren't any gotchas, though, like the MIPS delay slot (which can be extra confusing considering that _some_ assemblers take care of it, while disassemblers generally don't).
@@kFY514 true. In fact I noticed a number of things while watching that I wouldn't have if I didn't know 6502 as much as I do.
Very interesting how naive the original hack was.
To check for matching 0x05 before replacing anything else with 0x05 shows a lack of understanding.
A normal override for this would simply always replace whatever was there with 0x05. Replacing 0x05 with 0x05 is fine and would not do anything and thus only require a single line.
Technically the hack could have been done without a new function also by exploiting the code that reduced the value from 0x05 to 0x04 before using it to shift. This could have simply loaded 0x04 directly, ignoring everything the call returned. Alternatively using the space for the shift operation as well we could simply load the desired 256 result.
That would have been the quickest and shortest way to get this BIOS always return the value those people wanted to have the BIOS return. It would even call the original function that seems to be important (or maybe it isn't).
It might be a bit of trickery to hide it when (hardware) testing the code?
As example: It does check the cache memory on a hardware level but then ignores it completely in the code so with hardware testing it gives the right signals on an electrical level??
Bit like the Volkswagen scandal, the car knew when it was being tested and went into a "compliant" program so it passed the test.
@@samuraidriver4x4 But that's just it, the extra stack level and call could have been caught by testing. The result is also returned in a register so unless you specifically looked for a read from that register after a certain number of instructions upon returning you would never be able to tell. The register is used a lot more later.
You can't "decode" a string to anything useful, it's plain data, not CPU opcodes (operation codes), you need to find the code that make use of that data. You can see that the hex values for those "instructions" are actually the letters in your string (grab an ASCII chart and check). You're actually very lucky you found the reference immediately after the string, this is often not the case.
Yes, that was lucky that the file made any sense at all in Hiew. I only realize now that it could have been much harder to reverse the code.
Amazing job
Thank you!
definitely i'll have to watch it again! :)
There is quite a bit of material in there. It's not easy to follow assembly language.
@BitsUndBolts
Well done good sir! Now just install 512k of cache and 64MB of RAM and call that board good!
The modified routine that checks if the value matches 0x05 and then sets it if it doesn't, would it not have been simpler (and very slightly more efficient) just to set the value without checking it since this would save a few clock cycles?
I get the way they've done it seems a "better way" but in terms of efficiency it achieves nothing.
Anyone else manage to follow this a lot better as you've too watched Ben Eater's various tutorial videos? And if you haven't you 100% should!
I'll check Ben Eater's tutorials. Thanks for the hint.
@bitsundbolts I learned a LOT from his videos.
Especially how computers work with the 6502 project, where he builds incrementally explaining each step in succession starting with basic logic gates. Can't recommend them highly enough.
In the hacked BIOS, what's the point of checking if AL was 0x05 only to set it to 0x05 if it wasn't?
The only reason I can see this process at 0xDF00 being useful, is if the returned flags can be used to tell if AL was originally 0x05 (ZF=1) or if it was hacked to 0x05 (ZF=0).
ZF is zero flag, isn't it? I stumbled across this already. That extra code and function doesn't seem to serve any purpose from what I've seen. I guess it's just a way to implement it. And think about it, that code was not meant to be seen by anyone else 😊
Also the zero flag is immediately overwritten by 'or al,al' at the calling site, so it makes no sense (or nonsense).
There is a really great tool called Compiler Explorer, wich you should try out if you want to learn more about assembly.
Also assembly really isnt to complicated to read. There is the mnemonic, which represents the type or operation the instruction performs and then there are the operands, which are either registers or memory locations.
I'll have a look. What I've seen is that not every disassembler can work on BIOS files. Some expect windows executables. I will spend some more time on this topic.
Incredible!
Good job man :)
Thanks 👍
Well, without your help, I wouldn't be able to make this video! It took some time, but I definitely appreciate that disassembled code you provided! Well, it was very useful and now we have an unmodified BIOS.
Who knows, maybe there are other boards and BIOSes out there with the exact same code!
Very interesting!
There are plenty of comments about the redundant code at 0xDF00, but can we take a second to mention the code that decrements cl before using it to shift al (which was just loaded with 0x0010). If al was loaded with 0x0008 instead the dec would not be required.
dec uses 3 clock cycles, where-as the shl uses 8+4-per-bit cycles, so the dec is one cycle quicker I guess _shrug_
Great explanation. I never touched a BIOS but on my to-do list is to mod a BIOS for a motherboard to be Win2k compliant and to accept HDDs larger than 8G.
Is there a cache capacity that is right for a certain memory size? I remember that on my 486, having 512K cache, the computer was slower with 4M RAM than with 32M RAM. Not sure if I remember correctly.
Could it be that you meant it was slower with 32MB RAM than with 4MB? It could be that the cacheable memory area was the issue and only half of the memory was cached, but it sounds unlikely with just 32MB. Or the TAG RAM was too small for that big cache size. I wonder how difficult it is to fix the 8G HDD limit on a BIOS like this.
@@bitsundbolts Probably easier to get a xt-ide bios chip and add it in :D
Very Interesting on finding the bypass. But I have to say it was humorous watching your naive understanding of assembly. There is a difference between code and strings, most of what you were trying to decode were strings which would give you undecodable gibberish -- because it is not code!
Basically, the code was really had a jump over a string of characters "Cache Memory : " then an instruction to load the beginning of the string into register SI, then a call to a pair of subroutines to output that. Finally a routine to blank register AL and figure out cache size and then the bypass that you found that calls the real routine and then bumps the al to 5 (256K) if the cache is actually 0.
Oh well, I'm not denying that I am a bloody beginner when it comes to assembly language 😅
I find the mix of data and code unusual. In modern binaries the data and code live in separate blocks (for multiple reasons) and are not mixed together in this way.
I don't understand why the pirate patched bios checks for 05hex after the original code is called by the new routine. Call the original code to preserve the hardware behavior then load 05h on the register and return. Check the original value to to skip is a utterly moot point.
Who knows. It is odd to have the check there and then overwrite only if it is not equal to 5. Maybe a coding style. Don't update the register if it already has the value you need.
Likely because it's a quicker operation.
@drewnewby there the code only runs once, it just wastes space with something a single instruction can do. Calling the original function before is understandable as it may be important for initialization, that part is actually fine.
@leonardoliveira There's a difference on
vintage bare metal between more code and how fast an operation takes to complete. Less code is not always faster of course.
once you quit I'm like......wait you didn't fix the bios for the checksum. One of many reasons why I wouldn't mess around with a bios.
Well done for not knowing!
I was wondering if you had any suggestion from your video (Voodoo VGA Loop Cable
Repair) I left a message there too. I am looking to repair vga loose wire on my wacom cintiq 21 UX monitor. And was looking for any suggestions. Thanks
I saw your comment and replied to it there.
I'll need another watch of this or two :D
Haha, I hope it is because you like it so much - squeezing out the bad code via a disassembler :D (and not because it is confusing an my explanations are horrible)
@@bitsundbolts Exactly. I've just had to skim it due to lack of time for the time being and leave pondering for later. RE content is fundamentally always welcome, though i suppose it could be a hard sell for some other part of the audience.
@@bitsundbolts What i did notice is that you haven't spotted the end of the string where you inspect "cache memory", the 0 terminator slipped into the decoding of the next instruction in hiew, thus making that decode junk. Classic code-data disambiguation problem. It obviously finds its footing eventually so it hasn't actually interfered with what you were trying to find but given x86 has variable instruction length, it can take a while.
Yeah, it was hard finding the end of the string and the decoded instructions didn't always make sense (e.g. the string turned into instructions). I skipped over the parts that weren't that interesting - and I already knew what I was looking for. However, I still wanted to understand what's happening and why we get 256K displayed in the summary.
The video is doing well, so, RE is maybe not such a bad topic from time to time.
Making it show 32M cache was awesome. Next level awesome would be to make it show, instead of 256K or any value, the text "FRAUD". Ultimate level awesome would be to make it display, instead of "DEEP GREEN PC BIOS", "DEEP FRAUD PC BIOS", with the original false 256K cache display.
Hehe, that is easily possible with modbin. You can easily change this message in the original BIOS that always shows 256K L2 Cache.
It definitely is a fraudulent BIOS
@@bitsundbolts I'd love to see a follow-up video, or even a short, where you do that. I've read about and seen videos on these fake cache motherboards before, but you went orders of magnitude beyond those 'there were these fraudulent 486 motherboards with fake cache' videos, etc. to digging into the actual BIOS code. I think you're now the world expert on these fake cache boards -- I think only the original perpetrators of the fraud might know more.
Haha, thanks for saying that I'm an expert! I had a lot of help from my viewers who did most of the work - I just made the video. I guess I was lucky to find such a board at the scrapyard! Fully loaded with fake BIOS and fake cache chips!
@@bitsundbolts True - you and those viewers are the collective global experts on these. Though recording, editing and publishing a video isn't trivial, so you all deserve credit. It's seriously impressive, so far beyond and deeper than anything I've ever seen on these. And it really would be awesome to see a capture of the BIOS splash screen with "FRAUD" on it. Wonder where those fraudsters are today....
Glad to hear you enjoyed the video. It definitely takes a lot of effort to put it all in a video, but it is also very rewarding each time a video is ready for upload!
Maybe I get to change that BIOS message in one of the upcoming videos when I work on that board again.
awesome
Is it just someones joke? And does it affect any software for real, or just a POST gimmik?
It was part of a scam that made customers believe to have cache in the system even though there wasn't. To make sure the trickery isn't easily discovered, fake cache chips were placed on the board. Those cache chips just looked like real cache chips, but there wasn't any silicone die inside. So, just a plastic housing with metal legs to give the illusion cache is installed. There is already a video about this on my channel. This BIOS code helped scamming people.
@@bitsundbolts Although I understood every BIT of what you were doing, I didn't know WHY.
A 25 year grudge? Revenge?
Thanks for clearing that up, and good job.
Well, I shared the BIOS with the community: The Retro Web.
Now, anyone who has this board can use the latest BIOS.
@@bitsundbolts Just saw your first vid about fake cache and see clearly the reason for revenge :-)
Well, it worked.
My criticism would be that just because the computer is from ~1995, you didn't have to behave like you were also in 1995.
IDA or Ghidra would have been more appropriate tools
I have no experience with those tools as of now. I started to look at other tools to disassemble code. Yes, the newer tools are way more capable and helpful.
If you want help with that checksum, assuming its crc should be pretty easy to fix the checksum
I'm curious what the maximum value is that you could fake for the cache, without crashing or whatever.
You should use a diff program to compare the two bios.
If you're referring to BIOS v1.2 and v2.01, then there will be a lot of differences. Both versions differ significantly. I'll try to point this out in another video in the future. Seems like v1.2 is a lot older.
What do you use to capture the screen of the 486 pc?
A set of video converters: VGA cable to OSSC (open source scan converter) and then HDMI to USB capture card to get the signal into OBS.
The HDMI to USB was difficult to find. I had to test at least 10 different devices to find this one. Even Elgato Camlink 4K doesn't work owith those old and small resolutions.
oh no not a bin file. well done. dir/w/p
Haha, I was checking out a PCChips M507 motherboard, with fake cache chips. So fake that they are even poorly soldered. I thought someone had tried to increase the cache and had made a mess, what could I do to fix it? But then I saw that the lines didn't go anywhere, and then reading about this motherboard, I understood what a scam that cache was.
Speedsys shows Y2K bug in BIOS, why not fix this and upload it as version 2.1 or v3?
wait......bits UND bolts? I've thought this whole time it was bits and bolts. lol
Haha. Yeah - it is UND - the German word for 'and'.
@@bitsundbolts I seriously only just noticed today.
Its looks as though 24CE is writing the text to the screen to me.
24CE inc bx
inc = increment
bx is the function
jump through the function until something (without the function its impossible to know what), so probably write the characters until the :
Just a guess though, like you, I know VERY little about ASM 😆
Edit: I swear I don'y know yet (I'm at 8 minutes right now) but I'm guessing [si] is the variable/register/Idontknowassemblyterms that calculates or stores the cache. I guessing this because it gets "and"ed to what I think is the screen write function.....
32 Mb of cache... Seems like you gave it a bit of a modern chip there for a brief moment.
Seeing as you theoretically can install Windows 95 in the cache alone if it was supported on some chips.
Hehe, yes - Windows 95 would indeed fit in 32 MB of cache. Someone should try something like this on a modern CPU ☺️.
I had a dream once that my BIOS was made by Apogee
try Ghidra to reverse engineer - you can even decompile it into pseudo code which will help you understand whats going on
I've often wondered what would happen if you replaced RAM with cache. Of course now days it's not that big of a deal. RAM is actually faster than CPUs now. They have 10ghz ram now!! it's insane.
Isn't there some trickery somewhere? Like double data rate and other ways to just market it at high MHz, but in reality, it's not clocked that high.
@bitundbolts Very much so, it's nowhere near as fast as modern on-die cache.
@@bitsundbolts It functions as if it's that fast. It's actually faster than any CPU can handle currently.
can you not edit the code directly in the disassembly mode?
Yes, you can. I will do that later in the video. But you're right, no need to jump to the hex editor for editing.
@@bitsundbolts The thing that really shocked me is when the memory address in the call command doesn't match the actual memory address. Ohhhhhh intel what the hell did you do? LMAO In 6502 the address is the address is the address. That's the way it should be.
@@awilliams1701 It's a relative call, it doesn't use an absolute memory address but a signed offset. So you tell the CPU not where but how far to jump.
@@kpanic23 I guess in the end the actual assembly would be something like "Call cacheDetect" and "cacheDetect" would be resolved by the compiler, but that seems rather silly to me. I can see some cases like a for loop where that would make sense. If you only need to jump relative with numbers that fit into 8 bits then sure (like a 6502's zero page), but more than that? Might as well just use the actual address at that point.
I wonder if we could change the name of the bios to be a personalized name?
I'm sure it's possible. For one, you can add your name easily with modbin. You can also replace the BIOS logo (there is already a video on my channel, but an old one).
the lefthand address was 24ce yes
36:10 Surely that was kilobytes? 🙂
Is this a modern thing (as i people selling crap ro collectors) or a historical issue meaning my 486 i was running back in they day may never have had 256kb cache?
It's a historical thing. I found this motherboard at the scrapyard - nothing special except for the fake cache chips I made another video about - and the BIOS that always reports 256k of level 2 cache. The chance that you never had L2 cache in your 486 is not zero.
@bitsundbolts oh wow. Hey, thank you so much for this informative content. It's definitely something I'm gonna watch out for when I build my next retro gaming rig!
DEC is "decrement"
Very nicely explained! The original patch seems pretty damn stupid, patching in another function to return 5 instead of just replacing the call with a mov al, 5. Unless there is a consequence of not checking the cache size. Even then the compare in the patch is redundant. 😂
Maybe those people were paid by how many lines of code they wrote.
@@bitsundbolts 😂
I was going to comment the same thing. The entire “patch” they made is entirely unnecessary. Comparing to 5 and then replacing al with 5 if not is the mark of someone who has programmed a lot of assembly.
why am I watching this, some guy getting scammed in 1995
Have you seen recent Ryzen scams? They also look real, but no Ryzen chips under the heat spreader.
32Mb of cache!? That's L3 a Ryzen 3900X) 🤣
Haha, yes! I think I could even go to 256MB! 0x0F
Amd Ryzen 9 3900X has 4 x 16MB of L3 cache - 16MB per CCX, 32MB per CCD, 64MB in total, NOT 32MB in total.
32MB of L3: R7 3700X, R7 5700, R7 7700X and R7 9700X
They were a bit wasteful with their code! If you are going to always change AL to 0x05 then why check it's 0x05 after the return from the original code at all? No point checking if AL is 0x05 and skipping changing it if it is, that makes more code, not less. They should have just called the original routine then set AL to 0x05 before returning to the calling routine.
Yes, that would have been shorter. I have no idea why they did it that way.
Assembly language of x86/AMD64 is a disaster. One of the messiest out there. Over the years I got to know it pretty well and I wouldn't recommend it for someone just starting to learn asm. I wouldn't recommend any CISC for that purpose. RISC architerctures like MIPS, AArch64 (64 bit ARM; 32 bit is a little bit messy too), RISCV, etc., are much better starting point. 8-bit microcontrollers are good for learning too.
Thanks for this information. I started an online course that I can hopefully finish soon. I will keep this in mind and probably have a look at cleaner assembly before it gets frustrating.
@@bitsundbolts I mean, don't take it too seriously. If you're comfortable with CISC go for it. x86 isn't going away anytime soon.
@pvc988 Same, go with CISC, suffer as we did decades ago. Assembly is a product of it's time regarding x86. I'm sure RISCV is cleaner, as OP mentioned, but I'm not sure how that's helpful in the context of this channel's focus.
I mean as far as classic x86 code goes it's not TOO terrible. It was written like this, thus it can also be read like this.
I have come to really love Z80 assembly. It was binary compatible with the 8080, but the intel mnemonics are horrible.
The language for the Z80 is much better. I believe it was specifically designed to be easy to learn.
wow you know something sucks when I'm calling it out in a language I know nothing about. first it compares then it returns if if it's fine. Otherwise it sets it equal, then it returns. Why doesn't it just set it equal and return? lol completely redundant code.
oh and if you're overriding the number why are you calling 9e23 in the first place? sigh..... Seriously all the fake function needs is "mov al, 005" and "retn"
@@awilliams1701 The original procedure may actually do some initialization first, before returning the size.
@@k4be. well let's say that call is required to boot the system. You can still eliminate the comparison. That's being erased by the mov command.