0

currently working on reverse engineering some MIPS assembly and I am a bit stuck

004052c0 <subroutine_fnc>:
  4052c0:   27bdfff8    addiu   sp,sp,-8
  4052c4:   afbe0004    sw  s8,4(sp)
  4052c8:   03a0f025    move    s8,sp
  4052cc:   afc40008    sw  a0,8(s8)
  4052d0:   8fc20008    lw  v0,8(s8)
  4052d4:   00000000    nop
  4052d8:   2842005b    slti    v0,v0,91
  4052dc:   10400006    beqz    v0,4052f8 <subroutine_fnc+0x38>
  4052e0:   00000000    nop
  4052e4:   8fc20008    lw  v0,8(s8)
  4052e8:   00000000    nop
  4052ec:   28420041    slti    v0,v0,65
  4052f0:   10400004    beqz    v0,405304 <subroutine_fnc+0x44>
  4052f4:   00000000    nop
    else
  4052f8:   8fc20008    lw  v0,8(s8)
  4052fc:   1000000c    b   405330 <subroutine_fnc+0x70>
  405300:   00000000    nop
  405304:   3c020041    lui v0,0x41
  405308:   8c426190    lw  v0,24976(v0)
  40530c:   00000000    nop
  405310:   24430001    addiu   v1,v0,1
  405314:   3c020041    lui v0,0x41
  405318:   ac436190    sw  v1,24976(v0)
  40531c:   8fc20008    lw  v0,8(s8)
  405320:   00000000    nop
  405324:   24420020    addiu   v0,v0,32
  405328:   afc20008    sw  v0,8(s8)
  40532c:   8fc20008    lw  v0,8(s8)
  405330:   03c0e825    move    sp,s8
  405334:   8fbe0004    lw  s8,4(sp)
  405338:   27bd0008    addiu   sp,sp,8
  40533c:   03e00008    jr  ra
  405340:   00000000    nop

I think I have been able to disassemble most of it but I am really stuck on halfway through where the else statement. I mainly don't really understand the instructions lw v0,24976(v0) and lui v0,0x41 too well. Any help would be greately appreciated.

int subroutine_fnc(char a) {
    int b = (a<91) ? 1 : 0;
 
    if(b==0){
        return a;
    }else{
        b = (a<65) ? 1 : 0;
        if(b != 0){
            return a;
        }else{
            b = 0x41 << 16;
            //int v1 = b+1;
            // ???
            a+=32;
        }
    }
    return a;
}
Shaxey
  • 13
  • 4
  • `lui reg, %hi(foo)` / `lw reg, %lo(foo) (reg)` is how a MIPS assembler expands `lw reg, foo`, generating a 32-bit absolute address between LUI and the immediate part of `lw`. It's some global or static variable being incremented by a compiler too silly to remember that it could reuse the same `lui` result. (But this is obviously a debug build so it's not trying to be efficient.) – Peter Cordes May 23 '22 at 03:30
  • Near duplicate of [MIPS Assembly - lui $t0, 4097?](https://stackoverflow.com/a/56896673) / [What do %lo and %hi in compiler-generated asm mean, and why doesn't it work on MARS?](https://stackoverflow.com/q/32810716) – Peter Cordes May 23 '22 at 03:36
  • I sort of understand what it does, but what I'm mainly having trouble with is actually translating into C code. – Shaxey May 23 '22 at 03:39
  • I thought that was obvious once you know its loading from and then storing back to the same global (or `static`) var, after incrementing the load result. – Peter Cordes May 23 '22 at 03:40
  • I'm just having trouble making sense of the code. `lw v0,24976(v0)` is called before `sw v1,24976(v0)`, does this mean I am missing a while loop somewhere? – Shaxey May 23 '22 at 03:44
  • The block starting with `lui/lw` and ending with `lui/sw` is just doing `some_global++` like I was hinting at before. I haven't looked at the surrounding code, but that on its own doesn't imply any looping. Most loops would use a local variable as the loop counter, so it's unlikely to be that. – Peter Cordes May 23 '22 at 03:54
  • Makes bit more sense. Now though looking through the code I can't find where this global variable would be initialized. In the main function it is only referenced here `lui v0,0x41`, `lw v0,24976(v0)` ... `jr ra` at the very end of the code. – Shaxey May 23 '22 at 04:23
  • Global / static variables are statically initialized by data in the `.data` or `.bss` section, not by code. That's part of the point of static storage. In the code you're showing, the only reference to it is the increment, which doesn't come right before a `jr ra`, not sure what you're talking about. Unless you mean a different function loads it as a return value. And BTW, there are no loops in this function; all the branches are forwards. – Peter Cordes May 23 '22 at 04:37
  • it'll be more readable if you change `b = (a<65) ? 1 : 0;` → `b = (a<'A') ? 1 : 0;`, `b = 0x41 << 16;` → `b = 'A' << 16;`, `a<91` → `(a<='Z')` – phuclv May 23 '22 at 09:03
  • I am really failing to actually understand the global variable incrementation here. Namely `lui v0,0x41` and `lw v0,24976(v0)` followed by the `addiu`. Am I loading the global variable with `lw` here and incrementing and then storing it at with `sw v1,24976(v0)` again? – Shaxey May 23 '22 at 10:37
  • The `lui` and the `24976` offset produce the address for the variable. Yes, the `lw` loads the variable, the `addiu` obviously increments it and the `sw` writes it back. – Jester May 23 '22 at 11:39
  • One more question to the end code after `addiu v0,v0,32`. I am not sure what value I am actually returning at the end. Basically I am having a hard time just understanding the syntax of the last 7 lines. – Shaxey May 23 '22 at 11:57
  • Your C code is correct for that, it's returning `a+32`. The rest of the lines are just cleaning up, restoring `sp` and `s8` and returning. – Jester May 23 '22 at 12:03

0 Answers0