flat assembler
Message board for the users of flat assembler.

Index > Programming Language Design > Pointer Arithmetic: *EDI++=*ESI--

Author
Thread Post new topic Reply to topic
codestar



Joined: 25 Dec 2014
Posts: 254
codestar 31 May 2015, 09:58
Example:
Code:
let (i8) eax=*esi++
let (u8) *ecx++=*edi++
let (i16) *edx--=eax
let (u32) *edi++=*esi--    
Let Arithmetic:
Code:
macro let p
  match a==&b, p
    lea a, b
  else match a==b, p
    mov a, b
  else match a>>>b, p
    sar a, b
  else match a<<b, p
    shl a, b
  else match a>>b, p
    shr a, b
  else match a&b, p
    and a, b
  else match a|b, p
    or a, b
  else match a+b, p
    if b=1
      inc a
    else
      add a, b
    end if
  else match a-b, p
    if b=1
      dec a
    else
      sub a, b
    end if
  else match a*b, p
    if b=2
      shl a, 1
    else if b=4
      shl a, 2
    else if b=8
      shl a, 3
    else
      imul a, b
    end if
  else match a/b, p
    if b=2
      sar a, 1
    else if b=4
      sar a, 2
    else if b=8
      sar a, 3
    else
      match =eax, a
        push edx
        cdq
        idiv
        pop edx
      else
        error 'Destiny must be eax'
      end match
    end if
  else
    error 'Invalid expression',\
      ': let ', `p
  end match
end macro

; upgrade let to support: a=1, b=2, c=3

macro let p&
  irp x, p
    let x
  end irp
end macro    
Get Type Size & Sign
Code:
; from type cast, return size and sign
; in globals

macro get_type_p type
  local size, sign
  size=0
  sign=0
  match =u32, type
    size=32
  else match =i32, type
    size=32
    sign=1
  else match =u16, type
    size=16
  else match =i16, type
    size=16
    sign=1
  else match =u8, type
    size=8
  else match =i8, type
    size=8
    sign=1
  else
    error `type, ' - Unknown type'
  end match
  its_size=size
  its_sign=sign
end macro    
Load & Store Pointer:
Code:
; get_p eax, [edi], '+' ; eax=*edi++

macro get_p a, b, c
  local size, sign
  size=its_size
  sign=its_sign
  if size=32
    mov a, b
  else if size=16
    if sign=1
      movsx a, word b
    else
      movzx a, word b
    end if
  else if size=8
    if sign=1
      movsx a, byte b
    else
      movzx a, byte b
    end if
  else
    error 'Invalid size'
  end if
  match [r], b
    if c='+'
      add r, size/8
    else if c='-'
      sub r, size/8
    end if
  end match
end macro

; get_p eax, (i8) *ebx++

macro get_p a, p&
  match (t) q, p
    get_type_p t
    match *z, q
      match r++, z
        get_p a, [r], '+'
      else match r--, z
        get_p a, [r], '-'
      else
        get_p a, [r], 0
      end match
    end match
  end match
end macro

; set_p eax, [edi], '+' ; *edi++=eax

macro set_p a, b, c
  local size, sign
  size=its_size
  sign=its_sign
  if size=32
    mov dword b, a
  else if size=16
    if a=eax
      mov b, ax
    else if a=ecx
      mov b, cx
    else if a=edx
      mov b, dx
    else if a=ebx
      mov b, bx
    end if
  else if size=8
    if a=eax
      mov b, al
    else if a=ecx
      mov b, cl
    else if a=edx
      mov b, dl
    else if a=ebx
      mov b, bl
    end if
  end if
  match [r], b
    if c='+'
      add r, size/8
    else if c='-'
      sub r, size/8
    end if
  end match
end macro

; set_p eax, (i8) *ebx++

macro set_p a, p&
  match (t) q, p
    get_type_p t
    match *z, q
      match r++, z
        set_p a, [r], '+'
      else match r--, z
        set_p a, [r], '-'
      else
        set_p a, [r], 0
      end match
    end match
  end match
end macro    
Pointer Arithmetic:
Code:
; upgrade let to support pointers.
; alters ebx if *m=*m

macro let p&
  irp q, p
    match (t) c, q
      match *a==*b, c
        get_p ebx, (t) *b
        set_p ebx, (t) *a
      else match a==*b, c
        get_p a, (t) *b
      else match *a==b, c
        set_p b, (t) *a
      end match
    else
      let p
    end match
  end irp
end macro    
Example: 4 lines
Code:
let (i8) eax=*esi++
let (u8) *ecx++=*edi++
let (i16) *edx--=eax
let (u32) *edi++=*esi--    
Output: 12 lines, 300%
Code:
0FBE06        MOVSX  EAX,BYTE PTR [ESI]
81C601000000  ADD    ESI,0x1
0FB61F        MOVZX  EBX,BYTE PTR [EDI]
81C701000000  ADD    EDI,0x1
8819          MOV    BYTE PTR [ECX],BL
81C101000000  ADD    ECX,0x1
668902        MOV    WORD PTR [EDX],AX
81EA02000000  SUB    EDX,0x2
8B1E          MOV    EBX,DWORD PTR [ESI]
81EE04000000  SUB    ESI,0x4
891F          MOV    DWORD PTR [EDI],EBX
81C704000000  ADD    EDI,0x4    


Last edited by codestar on 12 Jun 2015, 16:55; edited 1 time in total
Post 31 May 2015, 09:58
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20289
Location: In your JS exploiting you and your system
revolution 01 Jun 2015, 01:41
Can I ask why you chose the asterisk (*) instead of the more usual assembly style square brackets ([])?

[edi++] = [esi++] Question

Also, how does the code decide to use EBX? It becomes a hidden used register which makes it easy to forget that it is corrupted.

What about changing ADD REG,1 to INC REG?
Post 01 Jun 2015, 01:41
View user's profile Send private message Visit poster's website Reply with quote
codestar



Joined: 25 Dec 2014
Posts: 254
codestar 01 Jun 2015, 02:57
Quote:
revolution: Can I ask why you chose the asterisk (*) instead of the more usual assembly style square brackets ([])?

[edi++] = [esi++] Question
Standard notation. I didn't choose it, C chose it, and it's one of the few choices available in FASMG:
Code:
[edi++]=[esi++] ; wrong
[edi]++=[esi]++ ; right, get value first    
Quote:
Also, how does the code decide to use EBX?
Any register can be used. This is merely an example. ebx is the last register index (#3) that you can access the 8+16BIT sections of (BX/BH/BL), leaving eax-edx available to the programmer.

Now, may I ask you a question? What makes you think you're a "programmer" when you never write code and can't understand simple things? YOu can't teach an old dog new tricks. Answer: revolution is just a fake who comes online and pretends to have programming abilities which he can't prove. After 12,767 posts, he has never created one single program by himself. What little code he writes is so illogical and easy to improve in 5 seconds. Why follow their stupid rules - which have gotten them NOWHERE - unless you want to be like them and have no programs?

I challenge anyone to improve my code:
Code:
while c, c=*p++, endw, p-s, p--

while s<e, c=*s, *s++=*e, *e--=c, endw

if n=0, *p++='0', *p=0
  return s
end

loop n, c=*s++, *p++=c
  if c=0, break, end
endl, p--

while c, c=*s++, *p++=c, endw, p--

while c=d, c=*p++, d=*s++
  if c=0, break, end
  if d=0, break, end
endw, p=c, p-d

while n, x=n, x&1, x+'0'
  . *p++=x, n>>>1
endw, *p=0

forever, c=*p++
  if c=0, return n, end
  . x=n, x<<2, n+x, n+n
  . n-'0', n+c
endfv

; draw bit/byte

function draw.bit, n, x, y
  if n
    draw.image bit1.i, x, y
  else
    draw.image bit0.i, x, y
  end
endf

function draw.byte, n, x, y
  locals i
  . i=8
  loop i, r0=n, r1=i
    . r1--, r0>>cl, r0&1
    draw.bit r0, x, y
    . x+BIT.W
  endl
endf

; draw pixel

function draw.pixel, x, y, c
  alias p=r0, z=r1
  try clip.pixel x, y
  vga.xy x, y
  . z=c, (u32) *p=z
endf 1

; draw horizontal line

function draw.line.h, x, y, n, c
  alias p=r0, z=r1, w=r2
  . p=&x, z=&y, w=&n
  try clip.line 0, p, z, w
  vga.xy x, y
  . z=c
  loop n, (u32) *p++=z, endl
endf 1

; draw solid rectangle

function draw.box, x, y, w, h, c
  locals i
  try visible x, y, w, h
  . i=y, i--
  loop h, i++
    draw.line.h x, i, w, c
  endl
endf 1

; draw scanline

function draw.scanline, pixels, x, y, w
  alias p=r0, s=r1
  vga.xy x, y
  . s=pixels
  loop w, (u32) *p++=*s++, endl
endf 1

; draw 8BPP scanline/bitmap with palette

function draw.scanline.8, pixels, x, y, w
  alias p=r0, s=r1, c=r2, q=r3
  vga.xy x, y
  . s=pixels
  loop w, q=*s++, q*4, q+palette.p
    . (u32) c=*q, (u32) *p++=c
  endl
endf 1

function draw.bitmap.8, pixels, x, y, w, h
  locals i, p
  try visible x, y, w, h
  . i=y, i--, p=pixels
  loop h, i++
    draw.scanline.8 p, x, i, w
    . r0=w, p+r0
  endl
endf 1

function draw.my.numbers
  locals i, n, y
  . i=bits.h, y=404
  loop i, r0=my.numbers, r0+i, r0--
    . r0=*r0, n=r0
    draw.byte n, 4, y
    . y-BIT.H
  endl
endf

function draw.title.scene
  draw.text help.t, 16, 130
  draw.byte magic.n, 50, 300
endf

function draw.play.scene
  draw.board
  draw.my.numbers
endf

function draw.pause.scene
  draw.text pause.t, 16, 130
  draw.byte magic.n, 50, 300
endf

function draw.game.over
  print t, game.over.t, score
  draw.text t, 44, 170
  draw.byte magic.n, 50, 300
endf

; convert 32BIT binary number to text

function b2t, n, t
  alias p=r0, x=r1
  . p=t
  if n=0, *p++='0', *p=0
    return
  end
  while n, x=n, x&1, x+'0'
    . *p++=x, n>>>1
  endw, *p=0
  text.reverse t
endf

; text.copy a, b - standard copy with
; 0 after. return advanced address

function text.copy, a, b
  alias p=r0, s=r1, c=r2
  . p=a, s=b, c=1
  while c, c=*s++, *p++=c, endw, p--
endf

; text.copy.n a, b, n - copy with maximum
; size specified. return &

function text.copy.n, a, b, n
  alias p=r0, s=r1, c=r2
  . p=a, s=b
  loop n, c=*s++, *p++=c
    if c=0, break, end
  endl, p--
endf

; text.go t, n - advance to line #

function text.go, t, n
  loop n
    try t=text.find t, 0Dh
    . t+2
  endl
endf t

; text.skip.0 a - skip 0s, return address or 0

function text.skip.0, a
  alias p=r0, c=r1
  . p=a, c='0'
  while c='0', c=*p++, endw, p--
  if c=0, return 0, end
endf

; convert text to 32BIT binary

function t2b, t
  alias p=r0, c=r1, n=r2
  try text.skip.0 t
  . n=0
  loop, c=*p++
    if c=0, return n, end
    . n<<1, n-'0', n+c
  endl
endf

function draw.my.text, t, x, y
  locals p, n
  get n=text.n t
  . p=t
  loop n, r0=p, r0=*r0
    draw.my.c r0, x, y, WHITE
    . x+r0, x+4, p++
  endl
endf

function randomize.puzzle
  locals q, n
  alias p=r0, x=r1
  . q=puzzle, n=(MAP.W*MAP.H)
  loop n
    get x=get.random
    . p=q, (u32) *p=x, q+4
  endl
endf

function is.solved
  locals n
  alias p=r0, x=r1
  . p=puzzle, n=(MAP.W*MAP.H)
  loop n, (u32) x=*p++
    if x<>NORMAL, return 0, end
  endl
endf 1

function draw.puzzle
  locals x, y
  . y=0
  while y<8, x=0
    while x<8
      . r0=x, r0*TILE.W, r0+MAP.X
      . r1=y, r1*TILE.H, r1+MAP.Y
      draw.piece x, y, r0, r1
      . x++
    endw
    . y++
  endw
endf

function on.key
  if key.event='c'
    if scene=SCENE.TITLE
      . scene=SCENE.PLAY
      go .draw
    end
    if scene=SCENE.GAME.OVER
      go .reset
    end
    if key='r'
      .reset:
      reset.game
      go .draw
    end
    if key='p'
      .pause:
      if scene=SCENE.PLAY
        . scene=SCENE.PAUSE
      else.if scene=SCENE.PAUSE
        . scene=SCENE.PLAY
      end
      go .draw
    end
    .draw:
    render
  end
endf

function on.mouse
  locals r
  if mouse.event='c'
    . r0=&close.i.x
    if.select r0
      exit
    end
    if scene=SCENE.TITLE
      reset.game
      . scene=SCENE.PLAY
      go .draw
    end
    if scene=SCENE.PLAY
      if.select puzzle.box
        get.select.xy
        get r=get.piece.rotate \
         select.x, select.y
        . r++
        set.piece.rotate \
         select.x, select.y, r
        go .draw
      end
    end
    if scene=SCENE.SOLVED
      reset.game
      . scene=SCENE.TITLE
      go .draw
    end
    .draw:
    render
  end
endf    
Post 01 Jun 2015, 02:57
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20289
Location: In your JS exploiting you and your system
revolution 01 Jun 2015, 09:20
codestar wrote:
Quote:
revolution: Can I ask why you chose the asterisk (*) instead of the more usual assembly style square brackets ([])?

[edi++] = [esi++] Question
Standard notation. I didn't choose it, C chose it, and it's one of the few choices available in FASMG:
Code:
[edi++]=[esi++] ; wrong
[edi]++=[esi]++ ; right, get value first    
Okay, so standard for C. But not standard for assembly.

I also find the ++ notation for C to be ambiguous. Without the actual parsing rules being stated there can be other ways to interpret it.

[esi++]: increment ESI after getting the memory address for reading?

[esi]++: increment the memory at [esi] after reading it?
Post 01 Jun 2015, 09:20
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8349
Location: Kraków, Poland
Tomasz Grysztar 01 Jun 2015, 14:09
revolution wrote:
Okay, so standard for C. But not standard for assembly.

I also find the ++ notation for C to be ambiguous. Without the actual parsing rules being stated there can be other ways to interpret it.?
That's exactly what I wanted to say. I think the bracket notation is much more clear, and in this case less ambiguous.
Post 01 Jun 2015, 14:09
View user's profile Send private message Visit poster's website Reply with quote
codestar



Joined: 25 Dec 2014
Posts: 254
codestar 01 Jun 2015, 18:30
Your argument is basically, "X is not a real X-Tian. I think X is clearer than Y but I don't know why and can't give reasons". Who cares? I'm a programmer, period, and I believe in writing good code in Abakis, C/C++, ASM, Javascript, doesn't matter which language. What is "good" code? Whatever works. "The right way is the way that works".

Tomasz:

On all keyboards I've used, * is easier to type than []. No one can argue logically that 2 inaccessible symbols [] is better to use than *. I don't see the ambiguity that you're referring to. Please clarify. In C, *(p++) means advance pointer by its size first then get *(value) after: add [p], size | mov x, type [p]. And p[i] means p[i*size] due to automatic scale. [ means +. array[i*s] = [array+i*s].
Quote:
Opinion: X is clearer than Y (based on "I don't know but I believe")
Fact: X is standard, X requires less characters than Y. To type X requires less energy (based on numbers, real evidence)


Last edited by codestar on 12 Jun 2015, 17:02; edited 1 time in total
Post 01 Jun 2015, 18:30
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20289
Location: In your JS exploiting you and your system
revolution 01 Jun 2015, 22:18
codestar wrote:
On my good day, I can beat Tomasz at programming, but on his good day, he can beat me.
We're not here to "beat" each other. We're to help each other.
Post 01 Jun 2015, 22:18
View user's profile Send private message Visit poster's website Reply with quote
codestar



Joined: 25 Dec 2014
Posts: 254
codestar 02 Jun 2015, 01:46
It's harmless fun like kids playing video games. Since 2001/2-ish, I've always thought that Tomasz was a good programmer and I remember when vid first presented his FASMLIB which inspired me. Show me a better way so that I can learn. It's frustrating to hear people say "You're wrong" but they don't show me a right way.

Who is "we"? Speak for yourself. Personally, I write all code for my own satisfaction and development then I put it online with the hopes that it will help *advanced* programmers. I know that some people (sleepS, JohnS, they're everywhere) will misinterpret it as "Look at me, I'm so great, better than you" (nonsense).
Post 02 Jun 2015, 01:46
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.