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 ☺️
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!
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!
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.
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.
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.
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.
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.
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).
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!
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.
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.
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.
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 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'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).
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
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.
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.
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"
@0:15 Oh look, it's the famous 486X3D CPU :D
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 ☺️
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!
Great deep dive with assembly. I’m still at ‘hello world’ 😂
Oh, I have no idea how to make hello world in assembly 😅
Great Vid , this brings back great memories really enjoyable!
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!
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 :)
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.
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.
Put the fixed BIOS into retroweb.
It's already there ☺️
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 🤣
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 😅
The DF00 ruintine can be eliminated completely. Just replace the call with 9e23.
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.
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.
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.
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.
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!
oh no not a bin file. well done. dir/w/p
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
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.
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.
Incredible!
36:10 Surely that was kilobytes? 🙂
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.
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 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.
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.
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).
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
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.
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.
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"