flat assembler
Message board for the users of flat assembler.

Index > Main > long mode jmp [ gs : 16 ] ; but NOT rip relative?

Author
Thread Post new topic Reply to topic
lazer1



Joined: 24 Jan 2006
Posts: 185
lazer1 19 Mar 2007, 20:33
with fasm, in long mode the instruction:

Code:
    jmp  [ gs : 16 ]  ; (A)
    


is rip relative,

so to do a non rip relative jmp I have to do:

Code:
   mov  rax, 0
   jmp  [ gs : rax + 16 ]  ;  (B)
    


however that incurs an extra register rax
and there may be none available Sad

(A) and (B) are totally different jumps,
ie jumps to totally different addresses as
(A) is rip-relative addressing and (B) is
absolute addressing,

the question here is :

can I do the same jump as (B)
but without requiring a dummy zero register rax?

Surprised
Post 19 Mar 2007, 20:33
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8367
Location: Kraków, Poland
Tomasz Grysztar 19 Mar 2007, 21:06
lazer1 wrote:
(A) and (B) are totally different jumps,
ie jumps to totally different addresses as
(A) is rip-relative addressing and (B) is
absolute addressing,

As long as your ORG reflects correctly the address at which the code is loaded, they both jump to the same address, that is stored in memory cell at GS:16h - however you also have to specify the size of this address and whether it is near or far jump, what cannot be deduced from your sample.
Post 19 Mar 2007, 21:06
View user's profile Send private message Visit poster's website Reply with quote
lazer1



Joined: 24 Jan 2006
Posts: 185
lazer1 19 Mar 2007, 21:54
Tomasz Grysztar wrote:
lazer1 wrote:
(A) and (B) are totally different jumps,
ie jumps to totally different addresses as
(A) is rip-relative addressing and (B) is
absolute addressing,

As long as your ORG reflects correctly the address at which the code is loaded, they both jump to the same address, that is stored in memory cell at GS:16h - however you also have to specify the size of this address and whether it is near or far jump, what cannot be deduced from your sample.


ok, I had been in fact using it as eg "jmp [ gs : xyz.abc ]"

where I had:

Code:
   struc xyz
          {
          .x     dq   0
          .y     dq   0
          .abc  dq   0
          }
   virtual at 0
   xyz  xyz
   end virtual
   ....
   mov rax, 0
   jmp  [ gs : rax + xyz.abc ]
  
    


so fasm was getting the size indirectly from the struc,

you say I should use ORG, there is a problem,

I cannot use ORG because I have relocated the
code. the address stored at absolute address "[ gs : rax + xyz.abc ]"
is the place I want to jmp to.

so
Code:
     mov rax,0
     jmp [ gs : rax + xyz.abc ]
    


is what I want to do, however I need *all* registers, *none* are
free,

rip-relative doesnt help as I want to jump to an absolute address
which isnt known at compile time and there are no free registers
available

also the code is not allowed to store the address in the body of the
code as the code needs to be recursively reentrant,


in the original code the ORG is correct, but the code
is then relocated to somewhere
completely different. The rip relative addressing
still functions correctly as that is relocation invariant.

gs contains a relocated pointer to the struc xyz,

the only way I can see is to push the address on the
stack and then do "ret"

that would preserve all registers including rsp and rflags,

however I was wondering if there was a way of doing
it via modifying "jmp [ gs : xyz.abc ]"
Post 19 Mar 2007, 21:54
View user's profile Send private message Reply with quote
lazer1



Joined: 24 Jan 2006
Posts: 185
lazer1 19 Mar 2007, 22:03
can I do it like this maybe?:


Code:
      jmp  [ gs : .next + xyz.abc ]
.next:

    


gs contains a relocated address and I want to jmp
from the address stored at an offset of xyz.abc
from gs,
Post 19 Mar 2007, 22:03
View user's profile Send private message Reply with quote
lazer1



Joined: 24 Jan 2006
Posts: 185
lazer1 19 Mar 2007, 23:06
lazer1 wrote:
can I do it like this maybe?:


Code:
      jmp  [ gs : .next + xyz.abc ]
.next:

    


gs contains a relocated address and I want to jmp
from the address stored at an offset of xyz.abc
from gs,


this still fails, the following code fails:

Code:
   ; THIS CODE IS RELOCATED, expressions like [ somelabel ]
   ;  are ok after relocation, lea is needed to determine the
   ; relocated address,

   lea rax, [ .xyz ]    ; read relocated address of .xyz to rax,
   mov [ .uvw ], rax  ; set up the relocated address to jmp to

   lea rax, [ .uvw ]  ; relocated address of .uvw to rax

   write_to_gs_macro  rax   ; write rax to gs via wrmsr

   mov rax, 0    ; set rax to 0 

   jmp near qword [ gs : .next + 0 ] ; supposed to jmp to .xyz

.next:
.abc:  echo_bad      ; macro to echo 'bad'
.xyz:  echo_good    ; macro  to echo 'good'

.x:         jmp .x


.uvw    dq    0  ; relocated address of .xyz to be stored here,

    


if I run this the machine crashes, but if instead I do the
same but replace the jmp instruction by

"jmp near qword [ gs : rax + 0 ]"

then it indeed echoes 'good'

why is the initial code fragment failing?

"jmp near qword [ gs : 0 ]"

also crashes, tried it just now,


Last edited by lazer1 on 19 Mar 2007, 23:19; edited 1 time in total
Post 19 Mar 2007, 23:06
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8367
Location: Kraków, Poland
Tomasz Grysztar 19 Mar 2007, 23:17
If your code changes position in a way that you really need to use absolute addressing, you can enforce 32-bit absolute addressing like this:
Code:
jmp near qword [ gs : dword 0 ]    

But note that there is no absolute 64-bit mode addressing available (except for some of the MOV forms), so if you needed to use address not fitting in 32 bits, you'd have to use register anyway.

The reference - section 2.1.19 of manual:
fasm's manual wrote:
The long mode uses also the instruction pointer based addresses, you can specify it manually with the special RIP register symbol, but such addressing is also automatically generated by flat assembler, since there is no 64-bit absolute addressing in long mode. You can still force the assembler to use the 32-bit absolute addressing by putting the dword size override for address inside the square brackets. There is also one exception, where the 64-bit absolute addressing is possible, it's the mov instruction with one of the operand being accumulator register, and second being the memory operand. To force the assembler to use the 64-bit absolute addressing there, use the qword size operator for address inside the square brackets. When no size operator is applied to address, assembler generates the optimal form automatically.
Code:
    mov [qword 0],rax  ; absolute 64-bit addressing
    mov [dword 0],r15d ; absolute 32-bit addressing
    mov [0],rsi        ; automatic RIP-relative addressing
    mov [rip+3],sil    ; manual RIP-relative addressing    
Post 19 Mar 2007, 23:17
View user's profile Send private message Visit poster's website Reply with quote
lazer1



Joined: 24 Jan 2006
Posts: 185
lazer1 19 Mar 2007, 23:31
Tomasz Grysztar wrote:
If your code changes position in a way that you really need to use absolute addressing, you can enforce 32-bit absolute addressing like this:
Code:
jmp near qword [ gs : dword 0 ]    

But note that there is no absolute 64-bit mode addressing available (except for some of the MOV forms), so if you needed to use address not fitting in 32 bits, you'd have to use register anyway.


SUCCESS! Razz

gs wont fit in 32 bits but the offset is some small value,
probably not even 8 bit, in the above example just 0,

gs is just an absolute relocated pointer to a struct

the fragment you give does function the way I want,
so that resolves the problem,

the following quote is the explanation then,

Quote:

The reference - section 2.1.19 of manual:
fasm's manual wrote:
The long mode uses also the instruction pointer based addresses, you can specify it manually with the special RIP register symbol, but such addressing is also automatically generated by flat assembler, since there is no 64-bit absolute addressing in long mode. You can still force the assembler to use the 32-bit absolute addressing by putting the dword size override for address inside the square brackets. There is also one exception, where the 64-bit absolute addressing is possible, it's the mov instruction with one of the operand being accumulator register, and second being the memory operand. To force the assembler to use the 64-bit absolute addressing there, use the qword size operator for address inside the square brackets. When no size operator is applied to address, assembler generates the optimal form automatically.
Code:
    mov [qword 0],rax  ; absolute 64-bit addressing
    mov [dword 0],r15d ; absolute 32-bit addressing
    mov [0],rsi        ; automatic RIP-relative addressing
    mov [rip+3],sil    ; manual RIP-relative addressing    
Post 19 Mar 2007, 23:31
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.