The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: n00b! on September 30, 2008, 11:31:22 AM

Title: call a (relative) virtual address
Post by: n00b! on September 30, 2008, 11:31:22 AM
Hello,
I'm sorry, but I have again some noobish and basic questions:

VA (Virtual Address): This is the address in RAM where some bytes were saved (for an pe executable it starts at IMAGE_BASE + Bytes of opcodes). f.e. 400100 - PUSH EBX

RVA (Relative Virtual Address): This is the address in RAM only within the executable and not the whole 4GB. f.e. 100 - PUSH EBX

1. Can I easily call a VA by typing "call 400100"
Is something similar with a RVA possible?


EIP contains the VA of the current instruction. f.e.
400100 - PUSH EBX (1 Byte)
400101 - PUSH 188 (2 Bytes)
400103 - MOV EAX, 1 (5 Bytes)
400108 -...

EIP = 400100

2. Could I add 3 to EIP that it contains 400103 and so I would bypass the "PUSH 188"?

Or could I save the value of EIP in EAX, add 3 to EAX and then jmp there by typing "jmp EAX"?

PS: Thanks and Sorry for my bad English
Title: Re: call a (relative) virtual address
Post by: Tedd on September 30, 2008, 12:31:33 PM
.
Title: Re: call a (relative) virtual address
Post by: n00b! on September 30, 2008, 12:58:40 PM
I'm sorry, I wont edit the questions anymore :-/
(If you mean that *hem*)
Title: Re: call a (relative) virtual address
Post by: Mark Jones on September 30, 2008, 04:19:59 PM
Quote from: n00b! on September 30, 2008, 11:31:22 AM
2. Could I add 3 to EIP that it contains 400103 and so I would bypass the "PUSH 188"?

Or could I save the value of EIP in EAX, add 3 to EAX and then jmp there by typing "jmp EAX"?

A: No, EIP is not user-accessible. That has already been said before.

Q: Why would you want to do such a thing? This is not how a newcomer "learns" assembler, by starting their journey by learning how to jump over instructions.
Title: Re: call a (relative) virtual address
Post by: n00b! on September 30, 2008, 05:23:47 PM
I want a "jmp" without having labels [...]
Title: Re: call a (relative) virtual address
Post by: BlackVortex on September 30, 2008, 06:14:03 PM
Quote from: n00b! on September 30, 2008, 05:23:47 PM
I want a "jmp" without having labels [...]
Your questions don't make a lot of sense, so my answers won't either, but if you don't want to use labels you can use short jumps, which are relative to the current instruction. For example, if you want to jump 14h bytes ahead, you need a 2-byte instruction :  EB 14
(using db 0ebh, 14h)

Or if you want to create relocatable code, you can use the "delta offset" trick to get the currect eip, put it in a register and then use it as a fixup to all memory accesses. Google for that.

If you want to jump to a "non-relative to current eip" address, you can push that address and then ret. Because long jumps are relative to the current eip.

EDIT: I think you haven't actually understood some basic assembler concepts, like labels etc. I'd suggest making a small example program that jumps around labels etc and step through it in a debugger.
Title: Re: call a (relative) virtual address
Post by: jj2007 on September 30, 2008, 08:23:37 PM
Quote from: Mark Jones on September 30, 2008, 04:19:59 PM
A: No, EIP is not user-accessible. That has already been said before.

call @F   ; equivalent to mov EIP, offset @@
@@:
pop eax   ; eax contains EIP of pop instruction
Title: Re: call a (relative) virtual address
Post by: n00b! on September 30, 2008, 08:44:07 PM
Ok, da es so scheint, als könne ich mich im Englischen nicht entsprechend artikulieren, sodass der Sinn meiner Frage nicht hervorgeht, versuche ich es einmal auf Deutsch.

Ich möchte folgenden Code ohne Labels schreiben:
push ebx
jmp @@1
push eax
@@1:
push edx


Ich habe mir so etwas vorgestellt (Der Code ist nur theoretisch und abstrakt, da EIP ja nicht ansprechbar ist):
push ebx
mov eax, eip
add eax, 8
;Soll übersprungen werden:
;MOV EAX, EIP  (2 Bytes)
;ADD EAX, 8     (3 Bytes)
;JMP EAX          (2 Bytes)
;PUSH EAX       (1 Byte)
jmp eax
push eax
push edx    ;<-- Springe hierhin


Nun weiß ich leider nicht, wie das funktionieren soll, da es ja keine Instruktion mit EIP gibt.
Außerdem fände ich es toll, wenn mir jemand sagen könnte, wie ich schnell die Anzahl der Bytes einer Instruktion bekomme.
Gibt es da vielleicht Merksätze, anhand welcher ich mir die Größen schnell ausrechnen kann oder hat jemand ein kleines Tool, dass Instruktionen in Opcodes umwandelt (Oder weiß jemand, wie man ein solches Tool machen könnte)?

Eventuell zeigt sich der Vorteil daran nicht sofort, wobei ich auch sagen muss, dass dieses Beispiel jenen nicht aufweist, dennoch gibt es ihn, was bedeutet, dass Hilfe erwünscht ist, jedoch keine "Das macht keinen Sinn"-Posts  :P
Title: Re: call a (relative) virtual address
Post by: bozo on September 30, 2008, 09:13:37 PM
noob, you can calculate relative addresses using LEA
as long as you have value of EIP in some register, subtract/add the number of bytes of the label in your source.
Title: Re: call a (relative) virtual address
Post by: n00b! on September 30, 2008, 09:58:50 PM
@jj2007:
Oh, sorry. At first I didn't understand your post, since I didn't know that a call only pushs the EIP of the next instruction to the stack :-/
And since the next instruction simply pops the EIP value from the stack you have the EIP of the current instruction and the stack is corrected.
Thanks, that's exactly what I wanted!  :bg

@Kernel_Gaddafi:
Sorry, but I don't know how to do what you're saying :-(
Could you please give an example code?
Title: Re: call a (relative) virtual address
Post by: bozo on September 30, 2008, 10:15:11 PM

@geip_label:
        pop ebp
        lea eax,[ebp + (proc_label - geip_label)]
        jmp eax
       
        xor eax,eax
        mov edx,ecx
proc_label:
        nop


you can also use FPU to get EIP


        fldz
        fnstenv [esp-12]
        pop ebp
        add ebp,1?
Title: Re: call a (relative) virtual address
Post by: Mark Jones on October 01, 2008, 03:36:44 AM
Quote from: jj2007 on September 30, 2008, 08:23:37 PM
call @F   ; equivalent to mov EIP, offset @@
@@:
pop eax   ; eax contains EIP of pop instruction

This is a hack, again, EIP cannot be accessed directly.
Title: Re: call a (relative) virtual address
Post by: japheth on October 01, 2008, 10:52:35 AM
Quote from: n00b! on September 30, 2008, 08:44:07 PM
Ich möchte folgenden Code ohne Labels schreiben:
push ebx
jmp @@1
push eax
@@1:
push edx

Nun weiß ich leider nicht, wie das funktionieren soll, da es ja keine Instruktion mit EIP gibt.

Es gibt das $ Symbol. Damit geht's auch ohne Label:

push ebx
jmp $+3
push eax
push edx


Man muss dann allerdings wissen, dass "jmp $+3" 2 Bytes und "push eax" 1 Byte lang ist.
Title: Re: call a (relative) virtual address
Post by: n00b! on October 01, 2008, 11:41:56 AM
@Mark Jones:
I got that, thanks :-)

@japheth:
Das ist mir gestern beides auch noch aufgefallen, aber dennoch danke ich dir für deine Antwort  :P

Btw. Is there a way to easily get the size of an instruction (maybe with the help of a tool or by following some guidelines, etc.)?
Title: Re: call a (relative) virtual address
Post by: jj2007 on October 01, 2008, 09:51:02 PM
Quote from: Mark Jones on October 01, 2008, 03:36:44 AM
Quote from: jj2007 on September 30, 2008, 08:23:37 PM
call @F   ; equivalent to mov EIP, offset @@
@@:
pop eax   ; eax contains EIP of pop instruction

This is a hack, again, EIP cannot be accessed directly.

Oh my god, are we again in the "or eax, eax ruthlessly destroys registers" debate??? :dazzled:
Title: Re: call a (relative) virtual address
Post by: bozo on October 01, 2008, 09:59:08 PM
QuoteBtw. Is there a way to easily get the size of an instruction (maybe with the help of a tool or by following some guidelines, etc.)?

not that i'm aware of, but there are tiny LDE's (Length Disassembler Engine) you could use.
Title: Re: call a (relative) virtual address
Post by: jj2007 on October 02, 2008, 12:56:01 PM
Quote from: n00b! on October 01, 2008, 11:41:56 AM
Btw. Is there a way to easily get the size of an instruction (maybe with the help of a tool or by following some guidelines, etc.)?

include \masm32\include\masm32rt.inc

.code
AppName db "Get the size of an opcode:", 0
start:

call @F
@@: pop ecx   ; ecx contains EIP of pop instruction

mov edx, offset AppName

call @F   ; equivalent to mov EIP, offset @@
@@: pop eax   ; eax contains EIP of pop instruction
sub eax, ecx
sub eax, 6
MsgBox 0, str$(eax), addr AppName, MB_OK

call @F
@@: pop ecx   ; ecx contains EIP of pop instruction

lea edx, offset AppName

call @F   ; equivalent to mov EIP, offset @@
@@: pop eax   ; eax contains EIP of pop instruction
sub eax, ecx
sub eax, 6
MsgBox 0, str$(eax), addr AppName, MB_OK

exit ; short form of invoke ExitProcess, 0

end start
Title: Re: call a (relative) virtual address
Post by: FORTRANS on October 02, 2008, 01:34:12 PM
Quote
Btw. Is there a way to easily get the size of an instruction (maybe with the help of a tool or by following some guidelines, etc.)?

   Why not assemble with a listing?  Makes counting easy.


      88 001F  8A E0         MOV     AH,AL   ; save
      89 0021  BB 0078 R         MOV     BX,OFFSET DivRes
      90 0024  D7         XLAT


Steve
Title: Re: call a (relative) virtual address
Post by: jj2007 on October 02, 2008, 03:18:50 PM
Quote from: FORTRANS on October 02, 2008, 01:34:12 PM
   Why not assemble with a listing?  Makes counting easy.

What? Counting with your FINGERS?? ::)

include \masm32\include\masm32rt.inc

; CONSOLE assemble and link

opsize MACRO arg
ifndef OpSizeDD
.data?
OpSizeDD dd ?
.code
echo dd defined
endif
ifb <arg>
call @F
@@: pop OpSizeDD   ; contains EIP of pop instruction
else
call @F
@@: push eax
mov eax, [esp+4]
sub eax, 11
sub OpSizeDD, eax   ; contains EIP of pop instruction
neg OpSizeDD
pop eax
add esp, 4
pushad
print chr$(13, 10, <arg>, 9)
print str$(OpSizeDD)
print chr$(" bytes")
; invoke MessageBox, 0, str$(OpSizeDD), chr$(<arg>), MB_OK
popad
endif
ENDM

.code
AppName db "Get the size of a piece of code:", 0
start:

print offset AppName, 13, 10

opsize
push eax
pop eax
opsize "push & pop"

opsize
pushad
popad
opsize "pushad & popad"

opsize
inc eax
opsize "inc eax    "

opsize
add eax, 1
opsize "add eax, 1"

opsize
mov eax, -1
opsize "mov eax, -1"

opsize
or eax, -1
opsize "or eax, -1"

opsize
mov eax, 0
opsize "mov eax, 0"

opsize
and eax, 0
opsize "and eax, 0"

opsize
mov edx, offset AppName
opsize "mov edx, offset AppName"

opsize
lea edx, AppName
opsize "lea edx, AppName"

print chr$(13, 10,10)
inkey "Hit any key to get outta here"
exit

end start
Title: Re: call a (relative) virtual address
Post by: jj2007 on October 02, 2008, 03:51:12 PM
For joyful playing, I attach the code. Usage:

opsize
   m2m ecx, 99
   .While !ZERO?
      dec ecx
   .Endw
opsize ".While not zero (fails miserably!)"

Some results:
push eax        1 bytes
pop eax         1 bytes
pushad & popad (/2)     2 bytes
inc eax         1 bytes
add eax, 1      3 bytes
mov eax, -1     5 bytes
or eax, -1      3 bytes
mov eax, 0      5 bytes
and eax, 0      3 bytes
mov edx, offset AppName 5 bytes
lea edx, AppName        6 bytes
lea edx, [AppName+4*eax]        7 bytes
lea edx, [AppName+4*eax+8]      7 bytes
jmp @F          2 bytes
simple loop, version A  8 bytes
simple loop, version B  6 bytes
.While/.Endw    10 bytes
.While not sign 8 bytes
.While not zero (fails miserably!)      8 bytes
.Repeat/.Until zero?    6 bytes
.Repeat/.Until ecx==0   8 bytes
.Repeat/.Until sign     6 bytes


Apart from that, Steve is perfectly right that a listing does the job, too. The macro is easier to handle if you are trying to size-optimise a longer piece of code.

[attachment deleted by admin]
Title: Re: call a (relative) virtual address
Post by: n00b! on October 02, 2008, 10:50:41 PM
Nice, many thanks for your replies!  :U

But I thought of a extern tool (maybe using a lookup-table or something like that) instead of assembling or disassembling an assembly  :red
Title: Re: call a (relative) virtual address
Post by: BlackVortex on October 02, 2008, 11:21:09 PM
Quote from: n00b! on October 02, 2008, 10:50:41 PM
Nice, many thanks for your replies!  :U

But I thought of a extern tool (maybe using a lookup-table or something like that) instead of assembling or disassembling an assembly  :red
RadAsm has a codesize plugin, but you need to use "projects" for it to work, doesn't work with single asm files   *sob*

It shows the size of each instruction at the side.

Some of the older members here, plz make a better alternative, I hate using "projects" lolz
Title: Re: call a (relative) virtual address
Post by: jj2007 on October 02, 2008, 11:35:53 PM
The macro does the job, but attention, it actually executes the instructions, so make sure the code is correct.
It comes in two versions:

1. For one instruction: Start the string with a colon, :

opsize ":lea edx, [AppName+4*eax+ecx+8]"

2. For multiple instructions, start with a blank "opsize" and end with an explanatory text:
opsize
mov ecx, 99
@@: dec ecx
jne @B
opsize "loop: mov ecx, 99 - dec ecx - jne @B"


Code attached, sample output below.

Bytes
0      .if 1 ... .endif
5      .if eax ... nop ... .endif
5      test eax, eax .. nop ... je @F
2      .While 0 ... .Endw
3      sub [esp], eax
4      sub dword ptr [esp], 127
7      sub dword ptr [esp], 128
1      push eax
1      pop eax
1      pushad
1      popad
1      inc eax
3      add eax, 1
3      or eax, -1
5      mov eax, -1
3      and eax, 0
5      mov eax, 0
4      mov ax, 0
2      mov al, 0
3      add eax, 127
4      add ax, 127
2      add al, 0
5      add eax, 128
4      add ax, 128
2      add al, 128
5      mov edx, offset AppName
6      lea edx, AppName
7      lea edx, [AppName+4*eax]
7      lea edx, [AppName+4*eax+8]
7      lea edx, [AppName+4*eax+ecx+8]
7      mov edx, dword ptr [AppName+4*eax+ecx+8]
2      jmp @F
8      loop: mov ecx, 99 - dec ecx - jne @B
6      loop: m2m ecx, 99 - dec ecx - jne @B
10     .While ecx - dec ecx - .Endw
8      .While not sign
8      .While 1 - dec ecx - ,break .if zero?, ecx=0
8      .While 1 - dec ecx - ,break .if sign?, ecx=-1
8      .While not zero (fails miserably)
8      .Repeat/.Until ecx==0, ecx=0
6      .Repeat/.Until zero?, ecx=0
6      .Repeat/.Until sign?, ecx=-1

[attachment deleted by admin]
Title: Re: call a (relative) virtual address
Post by: n00b! on October 03, 2008, 01:06:36 PM
Sure your code gets all the information I want, but it would be nice to not have to always reassemble the code.
Title: Re: call a (relative) virtual address
Post by: FORTRANS on October 03, 2008, 01:44:08 PM
Quote from: n00b! on October 03, 2008, 01:06:36 PM
Sure your code gets all the information I want, but it would be nice to not have to always reassemble the code.

   Well, get yourself an opcode list for finding out about single
instructions.  The Intel and AMD references will have that.  Or
use a debugger to disassemble a block of code.  If it's your code,
a listing still sounds good to me.

Ducks,

Steve N.
Title: Re: call a (relative) virtual address
Post by: jj2007 on October 03, 2008, 02:03:25 PM
Quote from: FORTRANS on October 03, 2008, 01:44:08 PM
   Well, get yourself an opcode list for finding out about single
instructions.  The Intel and AMD references will have that.

\masm32\help\opcodes.chm is a good start, too.