News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Pointer arithmetic in x64

Started by Yuri, February 09, 2012, 05:11:13 AM

Previous topic - Next topic

Yuri

Am I right in my feeling that such things should be avoided?

sub rax,addr Thing
add rax,addr Thing
cmp rax,addr Thing

I mean, the immediate value operands of the instructions above can at most be 32-bit, according to docs, so the results may be wrong. Perhaps it is negligible for an EXE because it is loaded at a low address and its labels won't have addresses longer than 32 bits, but what about DLLs? Theoretically they can sit anywhere in the virtual address space. Right?

So what if the code above is in a DLL and Thing is a label within that DLL, then, to be 100% on the safe side, should I do this:

lea rdx,[Thing]
sub rax,rdx
add rax,rdx
cmp rax,rdx


Maybe this is a dumb question either because I misunderstand some basic concepts or because the answer is obvious, but this x64 transition still puzzles me at times.

donkey

Hi Yuri,

GoAsm uses RIP relative addressing which is always a 32 displacement from the current instruction pointer so it is position independent. That is regardless of where it actually resides in memory the immediate displacement will never be more than 32 bits (signed). This is the root cause of the segment override issue in GoAsm X64 and why you have to use byte code in order to get access to the TIB (GS MOV does not assemble in a useful manner).
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

Yuri

Hmm... I don't seem to have understood everything you said, Edgar. My problem is not about addressing but calculating and comparing addresses. The CMP instruction cannot use a 64-bit immediate value, so I thought I shouldn't do the comparison this way:

cmp rax,addr Thing

because the address would be truncated to its lower half, which would produce the wrong result of the comparison if the DLL happened to have been loaded somewhere beyond the first 4GB.

However, this

lea rdx,[Thing]

must calculate and put in rdx the real 64-bit address of Thing, if I am not missing something.

donkey

Oh I see what you mean Yuri, you want to use instructions that only allow absolute addressing. In that case yes, you have to calculate its address and use a register with LEA if there is a chance it will be in a location beyond the 31 bit displacement.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

dedndave

i am curious - would this work ?
        mov     rdx,offset Thing
        cmp     rax,rdx

Yuri

Actually it's the same because GoAsm replaces mov rax,addr Thing with lea rax,[Thing]. The lea version is shorter since it uses the 32-bit RIP-relative displacement, while mov would use the 64-bit absolute address. This is mentioned in the GoAsm manual. The result must be the same, I think.

BogdanOntanu

Quote from: Yuri on February 09, 2012, 02:53:05 PM
Actually it's the same because GoAsm replaces mov rax,addr Thing with lea rax,[Thing]. The lea version is shorter since it uses the 32-bit RIP-relative displacement, while mov would use the 64-bit absolute address. This is mentioned in the GoAsm manual. The result must be the same, I think.

Nope, you are much safer using the MOV version when you want to calculate pointer differences.

LEA is not capable to load an 64bits immediate. It might work for cases when the offset of the symbol is in RIPĀ +/- 2G range BUT LEA can not really load 64 bits offsets.

The only "standard" instruction that can do this in 64 bits is MOV GPR, 64bits_immediate or MOV RAX, moffset64.

Ambition is a lame excuse for the ones not brave enough to be lazy.
http://www.oby.ro

Yuri

Yes, I see your point, Bogdan. Fortunately in my current case the addresses used are in the same DLL as the code that uses them, and the DLL is of course much smaller than 4GB, so there must be no difference. But generally speaking I think this replacement had better be turned off then. Unnecessary extra bytes are much less trouble than inability to do things.