Lil' ASM tutes

Post your FreeBASIC tips and tricks here. Please don’t post your code without including an explanation.
dafhi
Posts: 1329
Joined: Jun 04, 2005 9:51

Lil' ASM tutes

Postby dafhi » Sep 07, 2013 1:31

A series of ASM tutes I plan on doing.

#1 - blit routine [bugfix - 2013 Sept. 15]
#2 - conditionals / branching [updated - 2013 Sept. 15]
#3 - labels
#4 - Labels II

- older -
mul / div
Last edited by dafhi on Sep 16, 2013 3:44, edited 10 times in total.
dafhi
Posts: 1329
Joined: Jun 04, 2005 9:51

Re: Lil' ASM tutes

Postby dafhi » Sep 07, 2013 1:32

Lil' ASM tute 1 - blit routine

[updated] 2013 Sept 15. UB1D calculation fix

Code: Select all

' ----------------------- Lil' ASM tutes  by dafhi ----------------------- '

'    Tute 1:  Blit routine

'  Tip:
' add [x], eax '' slow
' add eax, [x] '' fast

' I created the tImage type as a wrapper.  Yes it's huge.
' Anyway, have a look inside the blit() sub for the meat of this tutorial.

' Until next time!

' ------------------------------------------------------------------------ '

Type tImage
  As Integer              w, h, wm = -1, hm = -1, bpp, bypp, _pitch, _pitchBy, UB1D, num_pages, is_screen
  as uinteger ptr         pixels
  Declare Sub             screen_init(w As UShort=1, h As UShort=1, numPages as integer=1, Flags as integer=0, bpp_ as UInteger=32)
  Declare Function        create(w As UShort=1, h As UShort=1, color_ As UInteger=RGB(127,127,127), NoImage As Integer=0) As Any ptr
  Declare Sub             cls( ByVal pColor As UInteger=RGB(0,0,0) )
  Declare Sub             destroy
  declare sub             iflip
  Declare Sub             blit( byref dest as tImage, x as integer=0, y as integer=0 )
  As Any ptr              img = 0
  declare destructor
 private:
  Declare sub             UpdateInfo
  Declare Sub             ScrInfo
  Declare Sub             varsCommon
End Type
Destructor tImage
  Destroy
End Destructor
Sub tImage.Destroy(): If img = 0 Then Exit Sub
  ImageDestroy img: img = 0
End Sub
Sub tImage.varsCommon
  wm = w - 1: hm = h - 1: _pitchBy = _pitch \ bypp
  UB1D = h * _pitchBy - 1 '' 2013 Sept 15 fix - used to be " w * _pitchBy .."
End Sub
sub tImage.UpdateInfo: ImageInfo img, w, h, bypp, _pitch, pixels: End Sub
Sub tImage.ScrInfo: ScreenInfo w,h, bpp, bypp, _pitch: pixels = ScreenPtr: varsCommon: End Sub
Sub tImage.screen_init(Wid As UShort,Hgt As UShort,_
                       numPages as integer,Flags as integer,bpp_ as UInteger)
  Destroy: num_pages = numpages: ScreenRes Wid,Hgt,bpp_,numPages,Flags: ScrInfo: img=0: is_screen=-1: if numPages > 1 then screenset 0,1
End sub
Function tImage.create(_w As UShort,_
                       _h As UShort,_
                       color_ As UInteger,_
                       NoImage As Integer) As Any Ptr
  Destroy: If NoImage Then
  w = _w: h = _h
  Else: img = ImageCreate( _w, _h, color_, 32 )
  UpdateInfo: EndIf: varsCommon: is_screen=0: Return img
End Function
sub tImage.iflip
  if not is_screen then exit sub
  if num_pages > 1 then: flip
  else: screenlock: screenunlock: end if
End Sub
Sub tImage.Cls( ByVal pColor As UInteger)
  Dim As UInteger num = (_pitch * h) \ bypp
  Dim As UInteger Ptr dest = pixels ''http://www.freebasic.net/forum/viewtopic.php?t=15809&
  Asm mov eax, [pcolor]
  Asm mov edi, [dest]
  Asm mov ecx, [num]
  Asm rep stosd
End Sub
  #Macro cpy_varadd(reg, var, add_to_var, reg_tmp)
    mov reg, [var]
    mov reg_tmp, reg
    add reg_tmp, [add_to_var]
    mov [var], reg_tmp
  #EndMacro
sub tImage.blit( byref dest as tImage, _x1 as integer, _y1 as integer )

  dim as integer  x1 = _x1, x2 = x1 + wm:  if x1 < 0 then x1 = 0
  dim as integer  y1 = _y1, y2 = y1 + hm:  if y1 < 0 then y1 = 0
 
  if x2 > dest.wm then x2 = dest.wm
  if y2 > dest.hm then y2 = dest.hm

  dim as integer      cols = x2 - x1 + 1: if cols < 1 then exit sub
  dim as integer      rows = y2 - y1 + 1: if rows < 1 then exit sub

  dim as integer      x_sav_ecx, y_sav_ecx '' ASM loops
  dim as integer      pitch = _pitch, pitch_dst = dest._pitch
  dim as uinteger ptr src = pixels, dst = dest.pixels + y1 * dest._pitchBy + x1

  '' shortcut of saying "if _y1 < 0 then _y1 = 0"
  src += _y1 * (_y1 < 0) * _pitchBy + _x1 * (_x1 < 0)

  '' here's the ASM section :D

  asm

    mov ecx, [rows]

    yLoopBlit:                                '' unique labels across app
      mov [y_sav_ecx], ecx                    '' prepare to use ecx for anything

      '' will use this macro in future projects
      cpy_varadd( esi, src, pitch, edx )      '' esi = [src], increase src by pitch, edx is temp
      cpy_varadd( edi, dst, pitch_dst, edx )  '' edi = [dst], increase dst by pitch_dst, ..

      mov ecx, [cols]
      xLoopBlit:                              '' all ASM labels in one app must be unique

        mov eax, [esi]                        '' mov [edi], [esi] is not acceptable in asm
        mov [edi], eax

        add esi, 4                            '' src
        add edi, 4                            '' dst

      dec ecx                                 '' end xLoop
      jnz xLoopBlit

    mov ecx, [y_sav_ecx]                      '' end yLoop
    dec ecx
    jnz yLoopBlit

  end asm

end sub


sub Main

  dim as tImage buf, img

  buf.screen_init 500, 500, 2
  img.create 100, 100, rgb(255,255,0)

  for i as uinteger ptr = img.pixels to @img.pixels[img.ub1d]
    *i = rnd * &H1000000
  next

  for i as integer = -(img.w + img.h + 100) \ 2 to (buf.w + buf.h + 100) \ 2

    dim as string kstr = inkey
    if kstr = chr(27) then exit for

    buf.cls
    img.blit buf, i, i
    img.blit buf, i, buf.h - (img.h + i)
    buf.iflip

    sleep 10
  next

end sub

Main
Last edited by dafhi on Sep 15, 2013 4:57, edited 2 times in total.
MichaelW
Posts: 3500
Joined: May 16, 2006 22:34
Location: USA

Re: Lil' ASM tutes

Postby MichaelW » Sep 07, 2013 6:37

'' all ASM labels in one app must be unique

For the labels that the programmer specifies, it depends on the type of label. Local Labels can be reused.

Code: Select all

dim as integer x
asm
    mov ecx, 10
  0:
    inc DWORD PTR [x]
    dec ecx
    jnz 0b
end asm
print x
asm
    mov ecx, 10
  0:
    inc DWORD PTR [x]
    dec ecx
    jnz 0b
end asm
print x
asm
    mov ecx, 10
  0:
    inc DWORD PTR [x]
    dec ecx
    jnz 0b
end asm
print x
sleep

Code: Select all

 10
 20
 30
dafhi
Posts: 1329
Joined: Jun 04, 2005 9:51

Re: Lil' ASM tutes

Postby dafhi » Sep 15, 2013 4:49

Lil' ASM tute 2 - conditionals / branching

[update] - 2014 Sept 15 - simplified comments

Code: Select all

' ----------------------- Lil' ASM Tutes  by dafhi ------------------------ '
'                                                                           '
'    Tute 2: conditionals / branching                                       '
'                                                                           '
' ------------------------------------------------------------------------- '


'' The foundation for conditionals is subtraction.

dim as integer  N = 5                     '' set up a loop
dim as integer  some_value = 10           '' something to do inside the loop

asm mov eax, [some_value]                 '' arithmetic on registers is fast.  eax will be our hero

asm mov ecx, [N]                          '' skip over loop if N < 1
asm cmp ecx, 1                            '' flags are set
asm jl past_loop                          '' jump if less

asm here_is_our_loop:                     ''
  asm add eax, 1                          '' our hero saving the day!
asm dec ecx                               '' oh hey look!  a subtraction.  flags are set
asm jnz here_is_our_loop                  '' jump if zero flag is not 1

asm past_loop:                            ''
asm mov [some_value], eax                 '' stuff new value in santa's hat

? some_value

sleep

/'
  http://stackoverflow.com/questions/14841169/jnz-cmp-assembly-instructions

  list of jump mnemonics

  jo              OF = 1            overflow
  jno             OF = 0            not overflow
  jc, jb, jnae    CF = 1            carry / below / not above nor equal
  jnc, jae, jnb   CF = 0            not carry / above or equal / not below
  je, jz          ZF = 1            equal / zero
  jne, jnz        ZF = 0            not equal / not zero
  jbe, jna        CF or ZF = 1      below or equal / not above
  ja, jnbe        CF or ZF = 0      above / not below or equal
  js              SF = 1            sign
  jns             SF = 0            not sign
  jp, jpe         PF = 1            parity / parity even
  jnp, jpo        PF = 0            not parity / parity odd
  jl, jnge        SF xor OF = 1     less / not greater nor equal
  jge, jnl        SF xor OF = 0     greater or equal / not less
  jle, jng    (SF xor OF) or ZF = 1 less or equal / not greater
  jg, jnle    (SF xor OF) or ZF = 0 greater / not less nor equal

'/
Last edited by dafhi on May 18, 2014 23:26, edited 4 times in total.
dafhi
Posts: 1329
Joined: Jun 04, 2005 9:51

Re: Lil' ASM tutes

Postby dafhi » Sep 16, 2013 0:55

Lil' ASM tute 3 - Labels

Code: Select all

' ----------------------- Lil' ASM Tutes  by dafhi ------------------------ '
'                                                                           '
'    Tute 3: labels                                                         '
'                                                                           '
' ------------------------------------------------------------------------- '

/'
Before I get ahead of myself, I thought it would be a good idea
to discuss labels.

Depending on the environment, defining a label can take on different
forms.  One example:

label:  mov eax, 1   '' (Netwide Assembler)


This suggests that labels simply point to a specific "line of code."

Much like the good days of GOTO statements.

That's it for now!
'/
dafhi
Posts: 1329
Joined: Jun 04, 2005 9:51

Re: Lil' ASM tutes

Postby dafhi » Sep 16, 2013 3:41

Lil' ASM tute 4 - Labels II .. a re-hash of what MichaelW pointed out

Code: Select all

' ----------------------- Lil' ASM Tutes  by dafhi ------------------------ '
'                                                                           '
'    Tute 4: Labels II                                                      '
'                                                                           '
' ------------------------------------------------------------------------- '


'' label names must be unique across application, except in the
'' case of locals, which are simply recognized as a positive integer.

asm mov ecx, 1  '' loop setup
asm 0:          '' local label
  asm dec ecx   '' flags set as a result of subtraction (now jump will know what to do)
asm jnz 0b      '' must append 'b' or 'f' (backwards or forward)

asm mov ecx, 1
asm 0:          '' label name re-used.  integers 0 thru 9 are handled most efficiently.
  asm dec ecx
asm jnz 0b

? "Hello World!"
sleep

Return to “Tips and Tricks”

Who is online

Users browsing this forum: No registered users and 1 guest