Solar Winds (DOS, 2013) annoyingly doesn't use C-strings in the text embedded into the executable. It seems to use the PC BIOS convention of ending strings by a $.
Sadly Ghidra doesn't seem to natively support this
Solar Winds (DOS, 2013) annoyingly doesn't use C-strings in the text embedded into the executable. It seems to use the PC BIOS convention of ending strings by a $.
Sadly Ghidra doesn't seem to natively support this
I wonder if anyone has made an extension for 16bit DOS reversing. Seems there's a lot of low-hanging-fruit involving automatically analyzing interrupts
I think this code is why the game froze on my packard bell back when I was a kid:
It's setting up the timer and then going into an infinite loop, expecting an interrupt to kick it out of loop eventually.
Something about the packard bell's PIT means that sometimes that wouldn't happen, and the cutscene would just hang forever
ugh. this was definitely written in assembly. Compilers like consistent registers for calling conventions, not randomly deciding to use BX for the single argument
@cr1901 maybe I'm mixing it up
@foone Huh, I thought '$' was specifically a DOS convention (and PC-BIOS requires you to know the length ahead of time).
I thought it was a 1993 game.
@Tathar huh. that was a major thinko, considering I checked before posting. fixed, thanks!
well I'm in a new function and I know what the value of DS is, but I have zero idea how to tell Ghidra that.
oh here we go: ctrl+r, Set Register Values
@foone these loops look weird - wouldn't the interrupt just return to the same place when done and the loop would keep running? How would these loops ever stop?
@lethal_guitar They seem to be waiting for AX to change: I think they set up an interrupt that doesn't properly save/restore registers, so AX ends up changing
they must have had a macro or compiler for strings. A lot of the filenames are double-terminatored:
BH_MU8.DAT\0$
@foone or is this just Ghidra misinterpreting the Assembly?
@lethal_guitar
so the disassembly sets AX and CX to 0, then loops on waiting for AX to turn to non-zero, then it does it again waiting for it to turn to zero, then it loops again incrementing CX while waiting for AX to turn non-zero.
So with an interrupt handler that toggles AX, this lets them calibrate how many CPU cycles (roughly) equals the set PIT frequency
@lethal_guitar yeah. so much hand-written assembly does shit like that, in my experience. just things that feel COMPLETELY WRONG because you can't realistically connect that kind of code to anything written by a compiler
@foone I guess when you're programming in Assembly it's more convenient to use registers instead of setting up variables in memory. But still feels wrong for the interrupt to not save/restore all registers.
@foone interesting!!
maybe I need to switch back to Ida Pro. Ghidra makes a lot of questionable or just plain bad assumptions when dealing with 16bit code
like I've got this code:
MOV byte ptr [0x4678],0x1
and I know DS is 0x1019. I have told Ghidra as much. but if I click on 4678, it tries to look up 0000:4678, which is the wrong address
yeah this code has a lot of NOPs in it for something a compiler would write.
x86-16 doesn't have delay slots, so... that's definitely a human writing this
@aidenfoxivey I tried a while back but at the time it wasn't very good at 16bit x86 at all. maybe it's improved since then
@foone Foone have you tried Binja for this?
although I wouldn't be surprised if they're using some macros or existing libraries for basic program stuff. I've found two different ways they set interrupts.
They've got their own function that writes the IVT directly, and then sometimes they call INT 21h,AH=9
@foone byte/segment/bank alignment?
@luisfcorreia 16-bit x86 doesn't care about alignment, so nope
okay yeah they definitely are using some library.
They register a interrupt handler for interrupt 10: That's an FPU error. this program doesn't use the floating point unit!
ahh. and printer errors.
yeah, I doubt there's very many printer errors in this video game
I'm sorry, what?
This is the whole function.
First, we save DS.
Then we set AX to 1BF9
Then we set DS to AX
then we set AX to DS (?!)
then we restore the old value of DS
So... the only result is setting AX to 1BF9?
and now I found some strings terminated with \x01.
that's THREE terminators so far
@foone yeah, the lack of fat pointer support for 16-bit segmented addressing is frustrating. If memory serves it's not something that can be fixed in the SLEIGH definition, it needs a bunch of changes to the Java model.
Still, people are actively contributing fixes for DOS stuff, eventually Ghidra will support Earth's worst address space.
076萌SNS is a social network, courtesy of 076. It runs on GNU social, version 2.0.2-beta0, available under the GNU Affero General Public License.
All 076萌SNS content and data are available under the Creative Commons Attribution 3.0 license.