ASM Subroutine C0/91A6 By AnyoneEB Last updated 2004-10-21.1923-0400 Final conclusion: Modulus subroutine. See below for details. Note: $ used to mean ref to memory address (a.k.a. * in C/C++). 0x is used for values. Note: C types used. int = 4 bytes; short = 2 bytes; char = 1 byte C0/91A6: A5 0A LDA $0A C0/91A8: 8D B0 00 STA $00B0 (short*) $7E00B0 = *(short*) $0A C0/91AB: A5 0C LDA $0C C0/91AD: 8D B2 00 STA $00B2 (short*) $7E00B2 = *(short*) $0C $(7E00B0, 4 bytes) = $(0A, 4 bytes) (int*($7E00B0)) = *(int*($0A)) C0/91B0: 64 0A STZ $0A C0/91B2: 64 0C STZ $0C $0A = $0C = 0x0000 (int*($0A)) = (int) 0 C0/91B4: A0 20 00 LDY #$0020 Y = 0x0020 for(short y = 0x20; y != ?; y--) { C0/91B7: 26 06 ROL $06 C0/91B9: 26 08 ROL $08 C0/91BB: 26 0A ROL $0A C0/91BD: 26 0C ROL $0C Rotate left (short) $06, $08, $0A, and $0C C0/91BF: A5 0C LDA $0C A = (short*)$0C C0/91C1: CD B2 00 CMP $00B2 C0/91C4: D0 05 BNE $91CB //if($0C == $00B2) { C0/91C6: A5 0A LDA $0A // A = $0A C0/91C8: CD B0 00 CMP $00B0 Compare: $0A - $00B0, carry set if $00B0 > $0A C0/91CB: 90 0E BCC $91DB // if($0A >= $00B0 || $0C >= $00B2) { //both shorts if((int*)$0A >= (int*)$00B0) { C0/91CD: A5 0A LDA $0A C0/91CF: ED B0 00 SBC $00B0 C0/91D2: 85 0A STA $0A C0/91D4: A5 0C LDA $0C C0/91D6: ED B2 00 SBC $00B2 C0/91D9: 85 0C STA $0C (int*) $0A -= *(int*($00B0)) } C0/91DB: 88 DEY Y-- C0/91DC: D0 D9 BNE $91B7 } C0/91DE: 26 06 ROL $06 C0/91E0: 26 08 ROL $08 rotate left $06 and $08 C0/91E2: 6B RTL return; rewrite: bool c; //carry bit (int*($7E00B0)) = *(int*($0A)); (int*($0A)) = (int) 0; for(short y = 0x0020; y != 0; y--) //one iteration for each bit of an int { //rotate a bit out of (int*)$06... bool t = c; //temp for carry c = *(int*)$06 & 0x80000000; //set carry to highest order bit *(int*)$06 <<= 1; *(int*)$06 |= t; //set lowest order bit to old carry //... into (int*)$0A t = c; //temp for carry c = *(int*)$0A & 0x80000000; //set carry to highest order bit *(int*)$0A <<= 1; *(int*)$0A |= t; //set lowest order bit to old carry, that is, former highest order bit of (int*)$06 //if $0A >= $00B0, decrease it by $00B0, may or may not actually make it less than $00B0 if(*(int*)$0A >= *(int*)$00B0) (int*) $0A -= *(int*($00B0)); } //rotate bit in carry back into $06? bool t = c; //temp for carry c = *(int*)$06 & 0x80000000; //set carry to highest order bit *(int*)$06 <<= 1; *(int*)$06 |= t; //set lowest order bit to old carry, that is highest order bit of old (int*)$0A return; notes: * 0x0020 = # of bits in int * Goes through loop 0x1f times... right? So the rotate at the end is the 0x20th... I think. * Lack of final rotation of (int*)$0A indicates that only (int*)$06 is the return value. * $0A will equal 0 at the end and $00B0 will equal the input value of $0A * Loop is not needed for line decreasing value in $0A since it is always below half the value of $00B0 * Each iteration multiples $0A by two and may or may not add 1. * If x < y then 2x + 1 can at the highest be y - 1 (assuming integers), ex. 99 and 200. (99<<1)+1 = 198+1 = 199. * Loop ensures that $06 will be under $00B0 * Loop ensures that $06 will never have a number that is not an integer multiple of $00B0 substracted from it * Conclusion: subroutine implements modulus operator. Exact result listed below in rewrite #3. rewrite #2: int c09146(int _0A, int _06) { int _00B0 = _0A; _0A = 0; bool c; for(short Y = 0x20; y != 0; y--) { bool t = c; c = _0A & 0x80000000; _0A <<= 1; _0A |= (_06 & 0x80000000 == 0 ? 0 : 1); _06 <<= 1; _06 |= c ? 1 : 0; if(_0A >= _00B0) _0A -= _00B0; } return (_06 << 1) & (c ? 1 : 0); } rewrite #3: *(int*)$00B0 = $0A; *(int*)$06 %= *(int*)$0A; //Important part *(int*)$0A = 0;