flat assembler
Message board for the users of flat assembler.

Index > Macroinstructions > Pointer Arithmetic: *EDI++=*ESI--

Author
Thread Post new topic Reply to topic
m3ntal



Joined: 08 Dec 2013
Posts: 296
m3ntal 24 Sep 2014, 23:45
Pointer Arithmetic for X86. 32BIT registers only. Alters EBX if M,M.

Example:
Code:
. (i32) *p++=*s++    
Output:
Code:
mov ebx,dword [esi] ; X86
add esi,4
mov dword [edi],ebx
add edi,4

ldr r12, [r6], 4      ; ARM
str r12, [r7], 4

move.l (a6)+, (a7)+ ; M68K    
Example:
Code:
format pe gui
int3  ; disassemble

include 'pointer.inc'

alias \
 a=eax, c=ecx, p=edi, s=esi

. (i32) a=*s++
. (i32) *p++=c
. (i8) *p--=*s--
. (i16) *p++=c
. (i32) *a++=12345678h

nop    
Output:
Code:
00401000 int   3
00401001 mov   eax,dword [esi]
00401003 add   esi,4
00401006 mov   dword [edi],ecx
00401008 add   edi,4
0040100B movsx ebx,byte [esi]
0040100E sub   esi,1
00401011 mov   byte [edi],bl
00401013 sub   edi,1
00401016 mov   word [edi],cx
00401019 add   edi,2
0040101C mov   dword [eax],12345678h
00401022 add   eax,4
00401025 nop    
Advantages of register pointers:

* Portability
* Standard address/value syntax: & and *. Resembles C/C++ and 68K ASM.
* Superior optimizations on other CPUs such as ARM that can load/store then add/subtract pointers in one instruction.
* For readability, create alias names for registers. See Magic-ARM Compiler (latest), especially TEXT and DRAW.

POINTER.INC
Code:
;;;;;;;;;;;;;;;;;; POINTER.INC ;;;;;;;;;;;;;;;;;;;

is.i? fix eqtype 0   ; immediate?

is.m? fix eqtype [0] ; memory?

is.r32? fix in \     ; register?
 <eax,ecx,edx,ebx,\
 esp,ebp,esi,edi>
is.r16? fix in <ax,cx,dx,bx>
is.r8? fix in \
 <al,ah,cl,ch,dl,dh,bl,bh>
is.r8l? fix in <al,cl,dl,bl>
is.r8h? fix in <ah,ch,dh,bh>

is.r? fix in \       ; any?
 <eax,ecx,edx,ebx,\
 esp,ebp,esi,edi,\
 ax,cx,dx,bx,\
 al,ah,cl,ch,dl,dh,bl,bh>

macro verify.r a {
 if ~a is.r32?
  'Register expected:' a
 end if
}

macro verify a {
 if ?s eq 0
  'Syntax error:' a
 end if
}

;;;;;;;;;;;;;;;;;; GET SIZE/SIGN ;;;;;;;;;;;;;;;;;

; from t=type name, return s=size and
; i=sign in numeric constants. example:

; size=0
; sign=0
; @gets i32, size, sign ; s=32, i=1

macro @gets t, s, i {
 s=0
 i=0
 if t eq u32 | t eq i32 | t eq dword
  s=32
 else if t eq u16 | t eq i16 | t eq word
  s=16
 else if t eq u8 | t eq i8 | t eq byte
  s=8
 else
  'Unknown type'
 end if
 if t eq i32 | t eq i16 | t eq i8
  i=1
 end if
}

;;;;;;;;;;;;;;;;;; GET/SET VALUE ;;;;;;;;;;;;;;;;;

; helper load/store...

; t=type, r=register, v=value,
; s=size, i=sign

macro @gv t, r, v, s, i {
 if s=32
  mov r, v
 else if s=8
  if i=1
   movsx r, byte v
  else
   movzx r, byte v
  end if
 else if s=16
  if i=1
   movsx r, word v
  else
   movzx r, word v
  end if
 end if
}

macro @get t, r, [v] {
 common
  local s, i              ; get size
  @gets t, s, i           ; and sign
  define ?s 0
  match *a, v \{          ; *p
   match x++, a \\{       ; *p++
    ?a equ x
    ?o equ add
    define ?s 1
   \\}
   match =0 \
    x--, ?s a \\{         ; *p--
    ?a equ x
    ?o equ sub
    define ?s 1
   \\}
   match =0 x, ?s a \\{   ; else, *p
    ?a equ x
    ?o equ                ; no advance
    define ?s 1
   \\}
   if ~ ?a is.r?
    'Error'
   end if
   @gv t, r, [?a], s, i
   if ~ ?o eq             ; advance?
     ?o ?a, s/8           ; add/sub n
   end if
   verify
  \}
  match =0 a, ?s v \{     ; r
   @gv t, r, a, s, i
   define ?s 1
  \}
  verify
  restore ?a, ?o
}

; t=type, r=register, v=value

macro @sv t, r, v {
 if t eq u32 | t eq i32 | t eq dword
  mov dword v, r
 else if t eq u16 | t eq i16 | t eq word
  if r eq eax
   mov v, ax
  else if r eq ecx
   mov v, cx
  else if r eq edx
   mov v, dx
  else if r eq ebx
   mov v, bx
  else             ; assume i
   mov dword v, r
  end if
 else if t eq u8 | t eq i8 | t eq byte
  if r eq eax
   mov v, al
  else if r eq ecx
   mov v, cl
  else if r eq edx
   mov v, dl
  else if r eq ebx
   mov v, bl
  else             ; assume i
   mov dword v, r
  end if
 else
  'Unknown type/size'
 end if
}

macro @set t, r, [v] {
 common
  local s, i              ; get size
  @gets t, s, i           ; and sign
  define ?s 0
  match *a, v \{          ; *p
   match x++, a \\{       ; *p++
    ?a equ x
    ?o equ add
    define ?s 1
   \\}
   match =0 \
    x--, ?s a \\{         ; *p--
    ?a equ x
    ?o equ sub
    define ?s 1
   \\}
   match =0 x, ?s a \\{   ; else, *p
    ?a equ x
    ?o equ                ; no advance
    define ?s 1
   \\}
   if ~ ?a is.r?
    'Error'
   end if
   @sv t, r, [?a]
   if ~ ?o eq             ; advance
    ?o ?a, s/8            ; add/sub n
   end if
   verify
  \}
  match =0 a, ?s v \{     ; r
   @sv t, r, a
   define ?s 1
  \}
  verify
  restore ?a, ?o
}

;;;;;;;;;;;;;;;; POINTER OPERATION ;;;;;;;;;;;;;;;

macro . [p] {
 forward
  define ?s 0
  match \
   (t) a==b, p \{    ; (t) a=b
   match *x, a \\{   ; m,m
    match *y, b \\\{
     @get t, ebx, b  ; use ebx
     @set t, ebx, a
     define ?s 1
    \\\}
   \\}
   if ?s eq 0
    match *y, b \\{  ; source=*
     @get t, a, b
     define ?s 1
    \\}
    if ?s eq 0
     match *x, a \\{ ; destiny=*p
      @set t, b, a
      define ?s 1
     \\}
    end if
   end if
  \}
  if ?s eq 0
   'Error'
  end if
}

;;;;;;;;;;;;;;;;;;;;;; ALIAS ;;;;;;;;;;;;;;;;;;;;;

macro ?list.attach list, item {
 match any, list \{ list equ list, item \}
 match , list \{ list equ item \}
}

; aliases for register names

macro alias [x] {
 forward
  define ?s 0
  match name==r, x \{
   ?list.attach ?alias, name
   name equ r
   define ?s 1
  \}
  verify
}

; restore alias names

macro end.alias {
 match a, ?alias \{ restore a \}
}    


Last edited by m3ntal on 27 Sep 2014, 22:44; edited 1 time in total
Post 24 Sep 2014, 23:45
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20344
Location: In your JS exploiting you and your system
revolution 25 Sep 2014, 00:58
m3ntal wrote:
Code:
mov ebx,dword [esi] ; X86
add esi,4
mov dword [edi],ebx
add edi,4    
This can be just "movsd" when we can stipulate that DF is clear.
Post 25 Sep 2014, 00:58
View user's profile Send private message Visit poster's website Reply with quote
m3ntal



Joined: 08 Dec 2013
Posts: 296
m3ntal 25 Sep 2014, 08:12
movsX only works for *edi++=*esi++ and *edi--=*esi--, no other registers or variations, and it's Intel specific. Example:
Code:
. (i32) *edi=*esi     ; movsd can't do this
. (i32) *edi++=*esi-- ; or this    
The advantages of this syntax are portability, versatility and simplicity. One can easily change the type and operands without having to write code differently. In big libraries and programs, it really makes a difference.
Post 25 Sep 2014, 08:12
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-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.