PHO - Pokémon Hackers Online

PHO - Pokémon Hackers Online (http://pokemonhackersonline.com/index.php)
-   Archive (http://pokemonhackersonline.com/forumdisplay.php?f=180)
-   -   Transferring SNES ASM knowledge to THUMB ASM (http://pokemonhackersonline.com/showthread.php?t=15158)

TheGag96 17th August 2014 08:42 PM

Transferring SNES ASM knowledge to THUMB ASM
 
Hi, so I'm diving into the world of Pokemon ASM hacking, and I'm having some trouble. Years ago I had gained some basic proficiency in SNES assembly from hacking Super Mario World. I thought that making the switch to THUMB would be pretty simple, but unfortunately, it's far more confusing than I originally imagined.

For example, I'm trying to get this code to assemble with the compiler that HackMew uses in his ASM tutorial (thumb.bat):

Code:

.text
.align 2
.thumb
.thumb_func

.org 0x08011D72
hijack:
        push {r0-r1,lr}
        bl #.FREESPACE


.align 2
.org .FREESPACE
main:
        mov r0,#0x79AF
        ldr r1, .TEST_PALETTE
        strh r0, [r1]
        pop {r0-r1,pc}

        .hword 0x2080
        .hword 0x0280
        .hword 0x4906

        mov r15, r14       
       
.FREESPACE
        .word 0x0871A260
.TEST_PALETTE:
        .word 0x05000224

However, any of you could easily see precisely why this won't compile. I'm not sure when to use "mov" and when to use "ldr" (one for values and the other for loading values at registers, respectively?). Also, I don't really know how to create compiler variables, like I'm pitifully attempting to do with FREESPACE. My usual ";"-style comments don't seem to fare well with the compiler either, and I don't know what the alternative would be.

If any of you actually know 65c816 ASM, what I'm essentially trying to do is this:

Code:

header
lorom

%FREESPACE = $0871A260        ;freespace variable remembered by compiler

org $08011D72        ;overwrite data here
hijack:
        PHA                ;i think this was to push the A register, just using for example purposes
        JSL main        ;jump long to my code but remember where to return to
       
org $FREESPACE
main:
        LDA #$79AF        ;load value 0x79AF into register A
        STA $05000224        ;store register A at address 0x05000224
        PLA                                ;pop A
       
        .hword #$2080        ;bytes found in debugger that are the original bits of code
        .hword #$0280        ;at 0x08011D72
        .hword #4906
       
        RTL                        ;return long all the way back to where we hijacked

Note the use of the opcode "JSL" and "RTL". These two are the long versions of the opcodes "JSR" and "RTS" which jump but remember where to go back to. There are also opcodes to JMP and JML to simply jump short or jump long to a place and ROM and never go back.

What I'm wondering is, what are the equivalents for this in THUMB? I understand that r14 (or lr) is used to return from jumping somewhere, but I'm still not sure how to actually JUMP to a location I want in the first place. I tried using "bl" but the compiler keeps telling me that it's out of range; why would this be the case if it's a LONG jump??

If anyone could push me in the right direction and help me clear these things up, I would be eternally grateful. Thanks a ton.

DoesntKnowHowToPlay 18th August 2014 01:30 AM

I don't have experience with 65c816 ASM, so I don't know how much help I'll be able to provide, but:

Quote:

Also, I don't really know how to create compiler variables, like I'm pitifully attempting to do with FREESPACE. My usual ";"-style comments don't seem to fare well with the compiler either, and I don't know what the alternative would be.
Hashtags (#) work to denote comments, although only at the start of a line. As for defining compiler variables, I'm not sure if you can; maybe someone else knows?

Quote:

However, any of you could easily see precisely why this won't compile. I'm not sure when to use "mov" and when to use "ldr" (one for values and the other for loading values at registers, respectively?).
"mov" is used to move the value of one register into another, or to place an immediate byte value in one register. "ldr" is used to load a word (4 bytes) from a pointer stored in a register into another (possibly the same) register, or to load a word stored in ROM. A few examples:

Code:

mov r0, #0x64
mov r1, #0x77

#r0 = 64, r1 = 77

mov r0, r1

#r0 = 77, r1 = 77

ldr r0, .ArbitraryValue
ldr r1, .ArbitraryPointer
b Next

.align 2
.ArbitraryValue: .word 0x12345678
.ArbitraryPointer: .word 0x08000010

#r0 = 0x12345678, r1 = 0x08000010

Next:
ldr r0, [r1, #0x0]
ldr r2, [r1, #0x4]
ldrh r3, [r1, #0x0]
ldrb r4, [r1, #0x0]

#r0 = 0xAD09E484
#r1 = 0x08000010
#r2 = 0x988B2411
#r3 = 0x0000E484
#r4 = 0x00000084

Quote:

I understand that r14 (or lr) is used to return from jumping somewhere, but I'm still not sure how to actually JUMP to a location I want in the first place. I tried using "bl" but the compiler keeps telling me that it's out of range; why would this be the case if it's a LONG jump??
"bl" is indeed branch long but it actually does have distance restrictions, and you are likely to hit those if you insert code in FR free space and call functions the game uses. The typical way to get around that for what you're doing is to use the opcode "bx", like so (offsets are fabricated but the hook must be 4-aligned):

Code:

.org 0x12344
ldr r1, .FunctionAddr
bx r1

.FunctionAddr: .word 0x08C80001


.org 0xC80000
#meaningful code that does useful stuff
ldr r2, .ReturnAddr
bx r2

.align 2
.ReturnAddr: .word 0x0801234d

Another option is to repoint some tables and insert the routine closer to where you're hooking in; in my experience the first 3 or so megabytes are bl-safe.

cosarara 7th September 2014 04:34 PM

You should pick up the official ARM manual (it also explains thumb). It's usually found as arm_arm.pdf IIRC [1]. Gbatek [2] and the arm7tdmi manual [3] are nice to have as well.
Comment syntax, macros, etc. are all particular to the assembler you are using, in this case GAS (the GNU Assembler) compiled for arm [4].
// actually works for comments, but you should use /* */ or # at the beginning of the line [5].
BL is encoded in 2 instructions and still can only do so much, because a GBA memory address can take up to 8 bytes.
While we are at it, BL is the call you can return from with a bx lr, and is unconditional. B doesn't return, and can be conditional, and bx takes a register value and uses the last bit to set the mode between arm and thumb.

PS:
[1] https://www.scss.tcd.ie/~waldroj/3d1/arm_arm.pdf
[2] http://problemkaputt.de/gbatek.htm
[3] http://infocenter.arm.com/help/topic...c/DDI0210B.pdf
[4] https://sourceware.org/binutils/docs/as/
[5] https://sourceware.org/binutils/docs....html#Comments
http://www.coranac.com/tonc/text/asm.htm
http://www.coranac.com/files/gba/re-ejected-gasref.pdf


All times are GMT. The time now is 04:54 PM.

Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
User Alert System provided by Advanced User Tagging (Lite) - vBulletin Mods & Addons Copyright © 2018 DragonByte Technologies Ltd.
Pokémon characters and images belong to Pokémon USA, Inc. and Nintendo.
Pokémon Hackers Online (PHO) is in no way affiliated with or endorsed by Nintendo LLC, Creatures, GAMEFREAK inc,
The Pokémon Company, Pokémon USA, Inc., The Pokémon Company International, or Wizards of the Coast.
All forum/site content (unless noted otherwise) and site designs are © 2006-2013 Pokémon Hackers Online (PHO).

Green Charizard Christos TreeckoLv100