'x86 Assembly Question - Can anyone determine what is happening below?
I downloaded a modification for a 20+ year old game I play, which is written in assembly code. It adds a fog effect, and then varies the grip levels based on that. However, the fog level is chosen seemingly at random.
Is it easy to see that happening below with trained eyes? I ran it through a disassembler, so not sure if it is actually displaying properly...
It is easy to spot the incrementing 0x33, 0x34, 0x35 etc so I have a feeling that is significant.
0x0000000000000000: DD 35 00 00 00 00 fnsave dword ptr [0]
0x0000000000000006: 80 3D 00 00 00 00 B8 cmp byte ptr [0], 0xb8
0x000000000000000d: 75 24 jne 0x33
0x000000000000000f: 80 3D A8 11 55 00 02 cmp byte ptr [0x5511a8], 2
0x0000000000000016: 0F 85 E6 00 00 00 jne 0x102
0x000000000000001c: 80 3D 00 00 00 00 00 cmp byte ptr [0], 0
0x0000000000000023: 75 30 jne 0x55
0x0000000000000025: 50 push eax
0x0000000000000026: A1 04 B5 6C 00 mov eax, dword ptr [0x6cb504]
0x000000000000002b: A3 00 00 00 00 mov dword ptr [0], eax
0x0000000000000030: 58 pop eax
0x0000000000000031: EB 22 jmp 0x55
0x0000000000000033: 80 3D B0 11 55 00 02 cmp byte ptr [0x5511b0], 2
0x000000000000003a: 0F 85 C2 00 00 00 jne 0x102
0x0000000000000040: 80 3D 00 00 00 00 00 cmp byte ptr [0], 0
0x0000000000000047: 75 0C jne 0x55
0x0000000000000049: 50 push eax
0x000000000000004a: A1 0C B5 6C 00 mov eax, dword ptr [0x6cb50c]
0x000000000000004f: A3 00 00 00 00 mov dword ptr [0], eax
0x0000000000000054: 58 pop eax
0x0000000000000055: 80 3D 00 00 00 00 33 cmp byte ptr [0], 0x33
0x000000000000005c: 75 11 jne 0x6f
0x000000000000005e: D9 05 00 00 00 00 fld dword ptr [0]
0x0000000000000064: D9 1D 00 00 00 00 fstp dword ptr [0]
0x000000000000006a: E9 30 00 00 00 jmp 0x9f
0x000000000000006f: 80 3D 00 00 00 00 34 cmp byte ptr [0], 0x34
0x0000000000000076: 75 11 jne 0x89
0x0000000000000078: D9 05 00 00 00 00 fld dword ptr [0]
0x000000000000007e: D9 1D 00 00 00 00 fstp dword ptr [0]
0x0000000000000084: E9 30 00 00 00 jmp 0xb9
0x0000000000000089: 80 3D 00 00 00 00 35 cmp byte ptr [0], 0x35
0x0000000000000090: 75 11 jne 0xa3
0x0000000000000092: D9 05 00 00 00 00 fld dword ptr [0]
0x0000000000000098: D9 1D 00 00 00 00 fstp dword ptr [0]
0x000000000000009e: E9 30 00 00 00 jmp 0xd3
0x00000000000000a3: 80 3D 00 00 00 00 36 cmp byte ptr [0], 0x36
0x00000000000000aa: 75 11 jne 0xbd
0x00000000000000ac: D9 05 00 00 00 00 fld dword ptr [0]
0x00000000000000b2: D9 1D 00 00 00 00 fstp dword ptr [0]
0x00000000000000b8: E9 30 00 00 00 jmp 0xed
0x00000000000000bd: 80 3D 00 00 00 00 37 cmp byte ptr [0], 0x37
0x00000000000000c4: 75 11 jne 0xd7
0x00000000000000c6: D9 05 00 00 00 00 fld dword ptr [0]
0x00000000000000cc: D9 1D 00 00 00 00 fstp dword ptr [0]
0x00000000000000d2: E9 30 00 00 00 jmp 0x107
0x00000000000000d7: 80 3D 00 00 00 00 38 cmp byte ptr [0], 0x38
0x00000000000000de: 75 11 jne 0xf1
0x00000000000000e0: D9 05 00 00 00 00 fld dword ptr [0]
0x00000000000000e6: D9 1D 00 00 00 00 fstp dword ptr [0]
0x00000000000000ec: E9 30 00 00 00 jmp 0x121
0x00000000000000f1: D9 05 00 00 00 00 fld dword ptr [0]
0x00000000000000f7: D9 1D 00 00 00 00 fstp dword ptr [0]
0x00000000000000fd: E9 1F 00 00 00 jmp 0x121
0x0000000000000102: E8 00 00 00 00 call 0x107
0x0000000000000107: D9 05 00 00 00 00 fld dword ptr [0]
0x000000000000010d: D8 25 00 00 00 00 fsub dword ptr [0]
0x0000000000000113: D8 C9 fmul st(1)
0x0000000000000115: D8 05 00 00 00 00 fadd dword ptr [0]
0x000000000000011b: D9 1D 00 00 00 00 fstp dword ptr [0]
0x0000000000000121: 50 push eax
0x0000000000000122: B8 01 00 00 00 mov eax, 1
0x0000000000000127: A3 00 00 00 00 mov dword ptr [0], eax
0x000000000000012c: B8 BE 00 00 00 mov eax, 0xbe
0x0000000000000131: A3 00 00 00 00 mov dword ptr [0], eax
0x0000000000000136: A3 00 00 00 00 mov dword ptr [0], eax
0x000000000000013b: A3 00 00 00 00 mov dword ptr [0], eax
0x0000000000000140: 58 pop eax
0x0000000000000141: E8 00 00 00 00 call 0x146
0x0000000000000146: 83 3D 00 00 00 00 00 cmp dword ptr [0], 0
0x000000000000014d: 75 20 jne 0x16f
0x000000000000014f: 50 push eax
0x0000000000000150: A1 00 00 00 00 mov eax, dword ptr [0]
0x0000000000000155: A3 00 00 00 00 mov dword ptr [0], eax
0x000000000000015a: A1 00 00 00 00 mov eax, dword ptr [0]
0x000000000000015f: A3 00 00 00 00 mov dword ptr [0], eax
0x0000000000000164: A1 00 00 00 00 mov eax, dword ptr [0]
0x0000000000000169: A3 00 00 00 00 mov dword ptr [0], eax
0x000000000000016e: 58 pop eax
0x000000000000016f: D9 05 00 00 00 00 fld dword ptr [0]
0x0000000000000175: D8 35 00 00 00 00 fdiv dword ptr [0]
0x000000000000017b: D8 0D 00 00 00 00 fmul dword ptr [0]
0x0000000000000181: D9 E0 fchs
0x0000000000000183: D8 05 00 00 00 00 fadd dword ptr [0]
0x0000000000000189: D9 1D 00 00 00 00 fstp dword ptr [0]
0x000000000000018f: D9 05 00 00 00 00 fld dword ptr [0]
0x0000000000000195: D8 35 00 00 00 00 fdiv dword ptr [0]
0x000000000000019b: D8 0D 00 00 00 00 fmul dword ptr [0]
0x00000000000001a1: D9 E0 fchs
0x00000000000001a3: D8 05 00 00 00 00 fadd dword ptr [0]
0x00000000000001a9: D9 1D 00 00 00 00 fstp dword ptr [0]
0x00000000000001af: D9 EE fldz
0x00000000000001b1: D8 1D 00 00 00 00 fcomp dword ptr [0]
0x00000000000001b7: 9B wait
0x00000000000001b8: DF E0 fnstsw ax
0x00000000000001ba: 9E sahf
0x00000000000001bb: 74 1E je 0x1db
0x00000000000001bd: D9 05 00 00 00 00 fld dword ptr [0]
0x00000000000001c3: D8 35 00 00 00 00 fdiv dword ptr [0]
0x00000000000001c9: D8 0D 00 00 00 00 fmul dword ptr [0]
0x00000000000001cf: D8 05 00 00 00 00 fadd dword ptr [0]
0x00000000000001d5: D9 1D 00 00 00 00 fstp dword ptr [0]
0x00000000000001db: DD 25 00 00 00 00 frstor dword ptr [0]
0x00000000000001e1: E9 00 00 00 00 jmp 0x1e6
Solution 1:[1]
Using absolute address 0
is very weird, presumably there's some kind of relocation to fixup those addresses. But your disassembly doesn't show it. If it's in a standard object-file format, you could use objdump -dr -Mintel foo.o
to include relocation metadata.
But anyway, it uses fnsave
to dump the x87 FPU state.
Probably the later addresses have different relocation fixup metadata, even though they're all [0]
in the code you dumped. The start of the fsave area gets the FPUControlWord
, and it makes no sense to fld
/ fstp
4 bytes from that location.
Almost certainly fld dword ptr [0]
/ fstp dword ptr [0]
is copying a float
value between 2 other locations, not loading / storing the FPU control and status words in place, as a 4-byte single-precision float
. (Possibly munging the data if it represents a NaN.) So we must conclude that each [0]
addressing mode could actually be any address, either within the fsave area or not. (The floats in the fsave area will be in 80-bit x87 format, not 32-bit (dword) single precision, so the fld dword
is unlikely to be operating on them.)
The cmp
with 0x33 .. 0x38 probably are looking at a byte of the x87 status word, maybe to figure out which slot in the save-area is the current top-of-stack? No, the status-word bits are not at the bottom of a byte. But the compare-result (C2, C1, C0) are at the bottom of the high byte of the status word (http://www.ray.masmcode.com/tutorial/fpuchap1.htm), and the exception-status bits in the bottom of the low byte.
So it's possible this chain of compare/branch is looking for something in the fsave area. Or more likely it's just checking for one of a few possible values for some byte of the game's data. Notice how on not-equal it jumps to the next cmp/jne. So this is an if
/else
chain, or one way of implementing a switch
/case 0x33:
/ case 0x34:
/ ... statement.
The fnsave
/ frstor
around the whole thing might be a red herring, it might not be poking around in that data at all. Instead it might just be saving/restoring the FPU state so it can use x87 instructions itself without messing up the main program. I initially thought it was reading the save-area because of the [0]
address, but it seems clear that relocations might point that address at other parts of the program's data, not just this patch's own private storage.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Peter Cordes |