News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

rip relative addressing code

Started by markallyn, February 20, 2018, 07:35:11 AM

Previous topic - Next topic

markallyn

Hello everyone,

I am trying to understand how to do rip-relative addressing in UASM.  The manual for 2.46 uasm shows some very brief code snippets, but they do not give the full possible syntaxes and as such are not really indicative of the usefulness of rip addressing.

If someone could post some examples of rip-relative addressing code it would be very helpful.  Please try to show a range of possible usages.

Many thanks,
Mark Allyn

johnsa

For the most part the whole process is automatic if you're careful.

For example using LEA to obtain the address of a variable is always rip relative, use of ADDR and & too as they translate to LEA.

For me personally when I code that's really all I worry about, I don't directly take the RIP value and apply it.

With some other assemblers I believe the syntax allows for something like:

mov eax,mVariable(rip) to force a rip relative access to the variable.

markallyn

Good morning Johnsa,

Yes, what you write here:
Quote
With some other assemblers I believe the syntax allows for something like:

mov eax,mVariable(rip) to force a rip relative access to the variable.


...seems to be true in other assemblers.  But, it also doesn't work with UASM as far as I can tell.  Are there instructions similar to this one that actually DO ASSEMBLE with UASM?  LEA is very, very useful and does (as a post from Sinsi some time ago illustrated) as you write use RIP addressing, but one can't address the RIP directly. 

Thanks for responding.

Mark

johnsa

In Uasm all the memory references that can be rip relative are automatically rip relative.

If you specifically wanted to use it manually you'd have to do some sort of trick



codestart0:
   jmp codestart1

someVar dd 0

codestart1:
  mov eax,[rip+($-someVar)]



I've not tested this, but just thinking out aloud...

markallyn

Johnsa,

I'll try it and see if it works.  I always learn something new when I try these experiments.  It teaches humility if nothing else.

Supposing it does work, why would one want to do something like this?  Generally, it seems to me that everything of a practical nature one might want to do with rip addressing is done by LEA.  If so, then why do YASM and NASM both provide for this capability along with LEA?

Regards,
Mark

johnsa

Good question :)

I've never found a use for accessing it directly myself, I suppose if I wanted to write some self-modifying code it might be useful..

The only thing I can think with the other NASM or GAS style assemblers is they've always been aimed more at providing a direct or literal translation of opcode/encoding to assembler syntax rather than the MASM style which is slightly more abstracted away from the underlying encoding so they opted for an instruction form that makes it very clear that it's using a RIP+displacement encoding... I don't know if this is the truth but it's the only thing I can think of :)

I'm aiming to do a similar level of abstraction for PLT and GOT on Linux, which apparently have become mandatory.. NASM / GAS require the use of @GOT / @PLT to specify this, which as far as I can tell so-far it should be able to automate this, saving the programmer from this burden and ugly syntax.

habran

Here is one nice example how we can utilise RIP, however, it is dangerous to do such programming:
; Written by: Fibergeek, http://www.codegurus.be/
; Date:       2004-10-03
; Subject:    Testing RIP relative addressing
;
; Updates:
;   2006-10-22
;     Added "public Main", this is needed from now on
;     Updated the command line you need to run
;     Removed the extra demonstration about absolute addressing, it's irrelevant with the newer ML64 versions
;
;   2005-09-12
;     The "END main" was turned into a simple "END"
;
; Compile & Link: ml64 rip.asm /link /subsystem:windows /defaultlib:kernel32.lib /defaultlib:user32.lib /entry:Main

extrn VirtualProtect: PROC
extrn MessageBoxA: PROC
extrn ExitProcess: PROC

.data
testok    db 'RIP based addressing worked, we executed "OR EAX, ECX" instead of "OR EAX, EAX"!', 0
testfail  db 'RIP based addressing didn''t work, we executed "OR EAX, EAX" instead of "OR EAX, ECX"!', 0
testtitle db 'RIP based addressing test by Fibergeek', 0

oldprotect dd ?

.code

public Main

Main:
  ; We first need to make this page writeable
  lea r9, oldprotect        ; R9  = lpflOldProtect
  mov r8d, 40h              ; R8D = flNewProtect (0x40 = PAGE_EXECUTE_READWRITE)
  mov rdx, 1                ; RDX = dwSize (NOTE: we will modify only one byte, but the whole page gets changed :))
                            ;              (this parameter is of type SIZE_T so it's 64-bits wide!)
  lea rcx, InXorInstruction ; RCX = lpAddress
  call VirtualProtect
 
  ; Ensure that the used registers for the test are setup
  mov eax, 0
  mov ecx, -1

  ; This is the test, we will increment C0 with one thus turning it into C1
  ; OR EAX, EAX will become OR EAX, ECX
  ;inc byte ptr [rip + 1] ; modify the next instruction - ML64 doesn't accept RIP as a parameter :((
  ;                         but will convert the address reference using RIP based addressing for us
  ;                         (this is because 64-bit mode doesn't support absolute addressing!?)
  inc InXorInstruction      ; UASM accept here:  inc byte ptr [rip + 1]   ;edited by habran
XorInstruction   DB 00Bh ; 0BC0 = or eax, eax
InXorInstruction DB 0C0h

  ; Store in RAX the correct display text
  ; If EAX is 0 than the test failed!
  or eax, eax
  lea rax, testfail
  jz skip
  lea rax, testok
skip:

  ; Display the result and exit the program returning the result of the MessageBox
  mov r9d, 0         ; R9D = UINT uType
  lea r8,  testtitle ; R8  = LPCTSTR lpCaption
  mov rdx, rax       ; RDX = LPCSTR lpText
  mov rcx, 0         ; RCX = HWND hWnd (0 = HWND_DESKTOP)
  call MessageBoxA
  mov ecx, eax       ; ECX = UINT uExitCode
  call ExitProcess

  ; Just in case :)
  ret
END


Cod-Father