views:

175

answers:

2

I have a Windows Mobile 6 ARMV4I project where I would like to get the value of the program counter.

The function is declared like this:

extern "C" unsigned __int32 GetPC();

My assembly code looks like this:

GetPC FUNCTION
    EXPORT GetPC
    ldr r0, [r15]   ; load the PC value in to r0
    mov pc, lr      ; return the value of r0
ENDFUNC

But, when I call the GetPC() function, I get the same number every time. So, I'm assuming my assembly isn't doing what I think it's doing. Can anybody point out what I may be doing wrong?

Thanks, PaulH

+5  A: 

PC is same every time, because ldr r0, [r15] has fixed address (PC is always same there). use R14 because it holds return address, that might be what you need. or use inline functions.

Andrey
Assuming he's using Microsoft tools, inline ARM assembler isn't supported.
ctacke
This is my first foray in to assembly, so I'm probably misunderstanding you. But, R15 is the program counter and R0 is the return value according to http://www.pentest.co.uk/documents/exploringwce/exploring_wce_shellcode.html#N10081. Are you saying that site is wrong and it's actually R14? Thanks
PaulH
@ctacke - Yes, I'm using VS2008 and inline `__arm` commands aren't supported.
PaulH
@PaulH every instruction has address. once function is compiled, it's instructions are put into memory and have fixed address. when you do ldr r0, [r15] you will have same result, because this instruction is pinned into memory. you can try macros if they are supported.
Andrey
@PaulH what is your arm assembler compiler?
Andrey
@PaulH: http://msdn.microsoft.com/en-us/library/ms863547(v=MSDN.10).aspx
Andrey
@Andrey - ARMASM.exe v15.00.20720. It comes with Microsoft Visual Studio 2008
PaulH
try: extern inline "C" unsigned __int32 GetPC();
Andrey
+4  A: 

If this is a true function, you should always get the same value in this code since you're just returning the current PC which is inside GetPC.

You probably want:

move r0, lr // put return address in r0
move pc, lr // return
plinth