Assembler: xor [pointer], offset addr1 xor offset addr2

Started by raleeper, June 28, 2011, 11:49:17 PM

Previous topic - Next topic

raleeper

Rejected, A2026: constant expected.

But  xor [pointer], 33 xor 44  assembles without problem, so offset addr1 and offset addr2 must not be recognized as constants.  Adding parentheses is no help.

What dumb mistake am I making?

Thanks.

xandaz

   I don't think u can use memory to memory.... Try. I don't really understand what you're trying to do.
   you want to xor [pointer], offset addr1+offset addr2? Why do you want to use the offsets? you should use xor after pointer as in a real ASM opcode and then + operator which tells the assembler you want to xor both offsets.
   Bye and later

xandaz

    sorry ... i tried bu it didnt work. try this.

mov eax,offset addr1
xor eax,offset addr2
xor [pointer],eax

jj2007

Tested with ML and JWasm:

include \masm32\include\masm32rt.inc
.data?
buffer db 100 dup(?)
.code
start:
mov esi, offset buffer
xor dword ptr [esi], 123
xor dword ptr [esi], offset buffer
inkey "OK"
exit
end start

raleeper

Quote from: xandaz on June 29, 2011, 12:13:42 AM
  I don't think u can use memory to memory.... Try. I don't really understand what you're trying to do.
  you want to xor [pointer], offset addr1+offset addr2? Why do you want to use the offsets? you should use xor after pointer as in a real ASM opcode and then + operator which tells the assembler you want to xor both offsets.
  Bye and later

I'm sorry.  I should have provided more context, and a more precise question.

The actual code I want to use is

xor DWORD PTR [kyptp], OFFSET kyptbl xor OFFSET kyptb2

kyptbl and kyptb2 are translation tables.

kyptp is a pointer initialized to kyptbl.  The xor instruction is meant to flip the pointer between the two tables, so that mov ebx, [kyptp] loads whichever table the user has selected by his last flip.

Since my initial post I tried some equates:

= 00000578         KKK1   =   OFFSET kyptbl
= 00000587         KKK2   =   OFFSET kyptb2
            KKKK   =   KKK1 xor KKK2
g:\lfw\lfw.asm(37) : error A2026: constant expected

Why is "KKK1 xor KKK2" not a constant?

Thanks.

mov eax,offset addr1
xor eax,offset addr2
xor [pointer],eax

Yes, I know I can do it that way,  and I will if necessary, but that's 3 lines of code and changes eax.

dedndave

it seems to me that this ought to work...
        xor DWORD PTR kyptp, OFFSET kyptbl xor OFFSET kyptb2
if not, try an EQUate...
AddrMask EQU OFFSET kyptbl xor OFFSET kyptb2
;
;
        xor DWORD PTR kyptp, AddrMask


the error that is reported describes a problem where the assembler does not know the address of the 2 items
it tries to resolve them in the first pass and cannot, as the addresses have not yet been assigned

i always get upset when i see this error, because it could just put a 0 in there and resolve it on the second pass

another way to go is to put some 32-bit value in there, then modify the operand at program init
a little exercise in self-modifying code   :P

dedndave

;program init code (executed once)

        push    eax
        push    esp
        push    eax
        INVOKE  VirtualProtect,offset Oprand-4,sizeof Oprand,PAGE_EXECUTE_READWRITE,esp
        mov     edx,offset Oprand-4
        mov     eax,offset kyptbl
        xor     eax,offset kyptb2
        mov     [edx],eax
        push    sizeof Oprand
        push    edx
        CALL    VirtualProtect
        pop     eax

;execution code

        xor     kyptp,80000000h   ;too large for signed byte form
Oprand  LABEL   DWORD


the init code may need to appear "below" the execution code in the source file
(otherwise, the assembler may not recognize the label "Oprand")
if so, just make it a PROC and call it
;program init code (executed once)

        call    Oinit

;execution code

        xor     kyptp,80000000h   ;too large for signed byte form
Oprand  LABEL   DWORD
;
;
;
Oinit   PROC

        push    eax
        push    esp
        push    eax
        INVOKE  VirtualProtect,offset Oprand-4,sizeof Oprand,PAGE_EXECUTE_READWRITE,esp
        mov     edx,offset Oprand-4
        mov     eax,offset kyptbl
        xor     eax,offset kyptb2
        mov     [edx],eax
        push    sizeof Oprand
        push    edx
        CALL    VirtualProtect
        pop     eax
        ret

Oinit   ENDP

jj2007

Quote from: raleeper on June 29, 2011, 12:40:34 AM
Why is "KKK1 xor KKK2" not a constant?

Because they are variable...
If you see xor eax, 00401000 in Olly, then 00401000 looks pretty much like an integer constant. However, it has been put there at runtime by the PE loader. Try to use your code as a dll, and you will see the "constant" change...

dedndave

i don't think offsets are always relocatable, Jochen
i think it's a pass 1/pass 2 assembler issue
i may be wrong (again) - lol
either way, the code i posted should fly

raleeper

OK, it looks as if I am stuck with using, instead of:

xor dword ptr [kyptp], offset kyptbl xor offset kyptb2

which in my humble opinion is elegant, efficient and ought to work, another approach.  In my initialize code, just before invoke winmain, I have:

mov eax, offset kyptbl
xor eax, offset kyptb2
mov dword ptr [kyxor], eax


and to flip the pointer:

mov  eax, [kyxor]
xor  [kyptp], eax


And this works as intended [so far - crossed fingers emoticon?].

Thanks to all who responded.
javascript:void(0);

qWord

what is the purpose of combining two pointers using XOR? What result do you expect to get?
FPU in a trice: SmplMath
It's that simple!

dedndave

you can still use the single instruction during execution
i guess you missed my previous post
here's a little update on it....
;program init code (executed once)

        call    Oinit

;execution code

        xor     kyptp,80000000h   ;too large for signed byte form
Oprand  LABEL   DWORD
;
;
;
Oinit   PROC

        push    edi
        push    eax
        mov     edi,offset Oprand-4
        push    esp
        push    eax
        INVOKE  VirtualProtect,edi,sizeof Oprand,PAGE_EXECUTE_READWRITE,esp
        mov     eax,offset kyptbl
        xor     eax,offset kyptb2
        mov     [edi],eax
        push    sizeof Oprand
        push    edi
        CALL    VirtualProtect
        pop     eax
        pop     edi
        ret

Oinit   ENDP


as for it being elegant, maybe not so much - lol
        xor     kyptp,immediate
this is not pretty, no matter how you do it   :P
the CPU has to interogate the value first (i.e. load the kyptp value into a temp register)
then XOR the immediate onto it
then store it
i think it's a 9-byte instruction   :red

raleeper

dedndave:

I have filed your code for later study on how to do self-modifying code.  It's more complicated than I want to get into now.

Thanks!

dedndave

ok - i made it look complicated by stack usage   :bg
here is a more generalized form that may be used for any dword value in the code section
ModDw   PROTO   :DWORD,:DWORD

;---------------------------------------------------------------------------------------

ModDw   PROC    uses edi dwAddress:DWORD,dwValue:DWORD

;Modify a DWORD in the code section
;DednDave 6-2011
;
;Call With: dwAddress = address of DWORD to modify
;           dwValue   = new DWORD value
;
;  Returns: EAX = status:
;                 non-zero = the DWORD was successfully modified
;                 zero     = error, the DWORD was not modified
;           EDX = original DWORD value

        LOCAL   dwFlag1:DWORD
        LOCAL   dwFlag2:DWORD

;save the original value on the stack

        mov     edi,dwAddress
        push dword ptr [edi]

;enable code section write

        INVOKE  VirtualProtect,edi,sizeof DWORD,PAGE_EXECUTE_READWRITE,ADDR dwFlag1
        or      eax,eax
        jz      ModDw0

;modify the value

        push    dwValue
        pop dword ptr [edi]

;restore the original protect flag

        INVOKE  VirtualProtect,edi,sizeof DWORD,dwFlag1,ADDR dwFlag2
        or      eax,1

ModDw0: pop     edx
        ret

ModDw   ENDP

;---------------------------------------------------------------------------------------


to use it...
;program init code (executed once)

        mov     eax,offset kyptbl
        xor     eax,offset kyptb2
        INVOKE  ModDw,offset Oprand-4,eax
        or      eax,eax
        jz      modification_failed

;execution code

        xor     kyptp,80000000h   ;too large for signed byte form
Oprand  LABEL   DWORD

xandaz

    Oh yeah.... it seems jj is right. they're variable. however it seems strange. If it assigns different offset as an EXE and as a DLL it does an then they're not variable anymore right? It would give errors on jump and call instructions also. Am i right. NO!!! laterz