Author Topic: Using ASM to Plot Pixels.  (Read 12148 times)

0 Members and 1 Guest are viewing this topic.

Offline Clyde

  • A Little Fuzzy Wuzzy
  • DBF Aficionado
  • ******
  • Posts: 7271
  • Karma: 71
    • View Profile
Using ASM to Plot Pixels.
« on: March 20, 2007 »
Hi,

Does anyone know what instructions in Assembler I'd need to use in order to be able to plot pixels, using TinyPTC and ScreenBuffer(XRES*YRES). And also what the instructions are doing please?

Many thanks,
Clyde.
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.

Challenge Trophies Won:

Offline ferris

  • Pentium
  • *****
  • Posts: 841
  • Karma: 84
    • View Profile
    • Youth Uprising Home
Re: Using ASM to Plot Pixels.
« Reply #1 on: March 20, 2007 »
I've seen your sourcecode, so I'm sure you have a freebasic routine like drawpixel(x,y,color). I'm writing this here and it's the basic idea of how to do it, but unfortunately I can't test it here. I am also assuming that "scrw" is a constant set to the screen width.

Code: [Select]
Sub drawpixel(x,y,color)
asm
mov ecx,[color]
mov eax,y
imul eax,scrw
add eax,x
shl eax,2
mov ebx,eax
mov eax,[ScreenBufferArrayPointer]
mov [eax + ebx],ecx
End asm
End Sub

should work ;)

Reply if you have problems.
http://iamferris.com/
http://youth-uprising.com/

Where the fun's at.
Challenge Trophies Won:

Offline Paul

  • Pentium
  • *****
  • Posts: 1490
  • Karma: 47
    • View Profile
Re: Using ASM to Plot Pixels.
« Reply #2 on: March 20, 2007 »
I'm not gettign this  ???

what is the ScreenBufferArrayPointer ??

I will bite you - http://s5.bitefight.se/c.php?uid=31059
Challenge Trophies Won:

Offline ferris

  • Pentium
  • *****
  • Posts: 841
  • Karma: 84
    • View Profile
    • Youth Uprising Home
Re: Using ASM to Plot Pixels.
« Reply #3 on: March 20, 2007 »
A memory pointer pointing to the start of the screenbuffer array.
http://iamferris.com/
http://youth-uprising.com/

Where the fun's at.
Challenge Trophies Won:

Offline Shockwave

  • good/evil
  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 17414
  • Karma: 498
  • evil/good
    • View Profile
    • My Homepage
Re: Using ASM to Plot Pixels.
« Reply #4 on: March 20, 2007 »
Use the stosd instruction for plotting single pixels and stosb for lines of them and whay thygrion said :)
Shockwave ^ Codigos
Challenge Trophies Won:

Offline ferris

  • Pentium
  • *****
  • Posts: 841
  • Karma: 84
    • View Profile
    • Youth Uprising Home
Re: Using ASM to Plot Pixels.
« Reply #5 on: March 20, 2007 »
If it were pure asm for tinycoding I'd use stosb, but this is good enough for inline asm.

The person to talk to for this is Fryer/Stonemonkey.
http://iamferris.com/
http://youth-uprising.com/

Where the fun's at.
Challenge Trophies Won:

Offline Clyde

  • A Little Fuzzy Wuzzy
  • DBF Aficionado
  • ******
  • Posts: 7271
  • Karma: 71
    • View Profile
Re: Using ASM to Plot Pixels.
« Reply #6 on: March 20, 2007 »
Quote from: Shockwave
Use the stosd instruction for plotting single pixels and stosb for lines of them and whay thygrion said

What and how do I know what is stosd and stosb instructions?

Thanks,
Clyde.
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.

Challenge Trophies Won:

Offline ferris

  • Pentium
  • *****
  • Posts: 841
  • Karma: 84
    • View Profile
    • Youth Uprising Home
Re: Using ASM to Plot Pixels.
« Reply #7 on: March 20, 2007 »
stosd and stosb are kinda strange.

stosb stores al into the memory address [es:di], and I am unfamiliar with stosd. Kinda like small macros.
http://iamferris.com/
http://youth-uprising.com/

Where the fun's at.
Challenge Trophies Won:

Offline Clyde

  • A Little Fuzzy Wuzzy
  • DBF Aficionado
  • ******
  • Posts: 7271
  • Karma: 71
    • View Profile
Re: Using ASM to Plot Pixels.
« Reply #8 on: March 20, 2007 »
Ok, say if I am using the following one dimensional array method of drawing directly to the screenbuffer:

Example:
ScreenBuffer(PosX+PosY*ScreenWidth)=Colour

What would the instructions be for that please, and if possible could you give comments on what it's doing?

Cheers and many thanks,
Clyde.
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.

Challenge Trophies Won:

Offline ferris

  • Pentium
  • *****
  • Posts: 841
  • Karma: 84
    • View Profile
    • Youth Uprising Home
Re: Using ASM to Plot Pixels.
« Reply #9 on: March 20, 2007 »
(hehe...looks liek my crap code worked ;D )

First, you need an extra variable for your screenbuffer. This is why I don't usually use asm to plot pixels in FB. Someone PLEASE post a way around this :) :

Code: [Select]
dim screenpointer as unsigned integer ptr = @ScreenBuffer(0) ' I think "@" is the right symbol ;)

Then the code would be:

Code: [Select]
asm
mov ecx,[Colour] ' Move color into ecx register
mov eax,PosY ' "PosY * ScreenWidth"
imul eax,ScreenWidth ' ^ cotd.
add eax,x ' "PosX + "
shl eax,2 ' * 4 because they're integers
mov ebx,eax
mov eax,[ScreenBufferArrayPointer]
mov [eax + ebx],ecx
End asm
http://iamferris.com/
http://youth-uprising.com/

Where the fun's at.
Challenge Trophies Won:

Offline Shockwave

  • good/evil
  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 17414
  • Karma: 498
  • evil/good
    • View Profile
    • My Homepage
Re: Using ASM to Plot Pixels.
« Reply #10 on: March 20, 2007 »
Ok Clyde, first you need a pointer.

    DIM PNTR AS UINTEGER PTR
    PNTR = @BUFFER(LOCATION)   

Where LOCATION is the location to start drawing.

The STOSD command is not strange, it just means "Store String"

You could have;

STOSB, STOSW, STOSD.
They all use different registers to grab the data from.

STOSB  uses AL And stores a BYTE.
STOSW uses AX And stores a WORD.
STOSD  uses EAX And stores a DOUBLE WORD.

What they all have in common is that they store the word, byte or double word they grab at the memory address it gets from the register EDI.

So... you could just have (to plot one pixel at 100 * 100 in white);

Code: [Select]
    DIM PNTR AS UINTEGER PTR

    PNTR = @BUFFER(100*(100*XRES))   
    CLR=&HFFFFFF

asm
        MOV EAX,DWORD PTR[CLR]
        MOV EDI, [PNTR]
        STOSD
end asm

You can repeat the storestring in a kind of loop by preceeding the STOSB, STOSW, STOSD instruction with rep.
Rep looks in the register ECX to see how many times to repeat it (incrimenting the address it writes to each time). So to draw a 50 pixel long line in white at 100 * 100 do;

Code: [Select]
    DIM PNTR AS UINTEGER PTR

    PNTR = @BUFFER(100*(100*XRES))   
    CLR=&HFFFFFF
    WIDTH = 50
asm
        MOV EAX,DWORD PTR[CLR]
        MOV EDI, [PNTR]
        MOV ECX,WIDTH
        REP STOSD
end asm

That's probably the method you should use tbh Clyde, I don't know of much that's faster.. For information rep stosb,rep stosw,rep stosd are all 2 bytes, and all 3 clock cycles + the count of bytes, words or dwords they have to move, or to put it simply the length of the line you want to draw.

Shockwave ^ Codigos
Challenge Trophies Won:

Offline Clyde

  • A Little Fuzzy Wuzzy
  • DBF Aficionado
  • ******
  • Posts: 7271
  • Karma: 71
    • View Profile
Re: Using ASM to Plot Pixels.
« Reply #11 on: March 20, 2007 »
Huge thanks dudes!! :)

Cheers,
Clyde.
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.

Challenge Trophies Won:

Offline Shockwave

  • good/evil
  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 17414
  • Karma: 498
  • evil/good
    • View Profile
    • My Homepage
Re: Using ASM to Plot Pixels.
« Reply #12 on: March 20, 2007 »
Ok, say if I am using the following one dimensional array method of drawing directly to the screenbuffer:

Example:
ScreenBuffer(PosX+PosY*ScreenWidth)=Colour

What would the instructions be for that please, and if possible could you give comments on what it's doing?

Cheers and many thanks,
Clyde.

There are thousands and thousands of pages on the web about assembly language syntax that you could use. Don't be put off with asm, it's not hard. In many ways its a lot simpler as you have less commands to remember :P
Shockwave ^ Codigos
Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: Using ASM to Plot Pixels.
« Reply #13 on: March 20, 2007 »
Quote
Someone PLEASE post a way around this
Code: [Select]
lea eax,[ScreenBuffer]

Quote
stosb stores al into the memory address [es:di], and I am unfamiliar with stosd. Kinda like small macros.
stosw stores ax (a 16 bit number) to [es:edi], and stosd stores eax (a 32 bit number) to [es:edi].  An RGBA pixel is 32bits so you use stosd.  These instructions are a lot more interesting than just mov(ing) a value because they can be prefixed with REP which says 'repeat this instruction ecx times, each time adding (or subtracting) the size of the value from the address'.
So
Code: [Select]
mov ecx,10
mov eax,$ffffffff
lea esi,[address]
rep stosd
Will store 10 white pixels at address.

Jim
Challenge Trophies Won:

Offline Stonemonkey

  • Pentium
  • *****
  • Posts: 1315
  • Karma: 96
    • View Profile
Re: Using ASM to Plot Pixels.
« Reply #14 on: March 20, 2007 »
If it's more speed you're after I would recommend (not wanting to put you off looking into asm as it is useful to have an understanding of it) looking at other ways of optimising, using asm to replace single instructions or a couple of instructions generally won't make all that much difference.

Offline Clyde

  • A Little Fuzzy Wuzzy
  • DBF Aficionado
  • ******
  • Posts: 7271
  • Karma: 71
    • View Profile
Re: Using ASM to Plot Pixels.
« Reply #15 on: March 20, 2007 »
Cheers Guys, very much appreciate the help and tips.
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.

Challenge Trophies Won:

Offline MrP

  • Atari ST
  • ***
  • Posts: 176
  • Karma: 18
    • View Profile
Re: Using ASM to Plot Pixels.
« Reply #16 on: March 24, 2007 »
This may be a bit late in the day for this post, but i'll add something anyway....

Quote
ScreenBuffer(PosX+PosY*ScreenWidth)=Colour

I've found that if your plotting lots of individual pixels using this code the most expensive thing is that multiply by the screenwidth.

For example if your plotting a 100x100 pixel box thats 10,000 multiplies, and 10,000 additions to get them all into the screenbuffer, I wrote some inline assembly to replace the above code and while it was faster than the freebasic commands you can still get it faster by removing all those nasty multiplies...

because the value you get from multiplying posy by the screenwidth will always be the same regardles of which line your on you can precalculate this beforehand, eg if your plotting a pixel at 100, 10 and your screen resolution is 800x600 the (posy*screenwidth) bit will be 10*600 which equals 6000, if your plotting at 100, 5 it will be 3000 so we can store these calculations in an array, then just reference that to avoid doing a multiply every time you want to plot a pixel......

create an array of 600 uinteger values (the height of your screen) then calculate the offset for each line of the screen as in the following code

Code: [Select]
dim y_offset(screen_y) as uinteger
for i = 0 to 599
    y_offset(i) = i * screen_x
next i

once this is done you can then replace your original drawing command with the following

Code: [Select]
scr_buffer(100 + y_offset(100)) = rgb(255, 255, 255)
as you can see you have now eliminated the expensive multiply and you should find that this is even faster than using inline asm to calculate the offset for your pixel... Of course if your trying to write small code the array of 600 integers wont help, but if speed is what your after then I don't think theres a much faster way of plotting single pixels in freebasic than this..

I'll put the complete code listing at the end, but please be aware this uses the standard ptc lib that comes with freebasic. I myself use the gfxlib and  I dont have the fantastic extended lib by Jim and Rbraz (I think thats who did it, if not my apologies for the incorrect credit) Hope this helps in some way.....

Code: [Select]
#include "tinyptc.bi"

const screen_x = 800
const screen_y = 600
const screen_size = screen_x * screen_y

dim shared scr_buffer(0 to screen_size - 1) as integer

ptc_open("test", screen_x, screen_y)

dim y_offset(screen_y) as uinteger
for i = 0 to screen_y - 1
    y_offset(i) = i * screen_x
next i

while inkey$ = ""
    scr_buffer(100 + y_offset(100)) = rgb(255, 255, 255)
    ptc_update @scr_buffer(0)
wend

ptc_close()
end

Offline Paul

  • Pentium
  • *****
  • Posts: 1490
  • Karma: 47
    • View Profile
Re: Using ASM to Plot Pixels.
« Reply #17 on: March 24, 2007 »
I did a little test code to try this and the results where a little strange.

in tinyptc_ext the time with multyplying was 19.6 sec for 1000 frames
in tinyptc_ext the time using the array it  was 19.9 sec for 1000 frames

in tinyptc the time with multyplying was 18.6 sec for 1000 frames
in tinyptc the time using the array it  was 17.3 sec for 1000 frames

I will bite you - http://s5.bitefight.se/c.php?uid=31059
Challenge Trophies Won:

Offline Shockwave

  • good/evil
  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 17414
  • Karma: 498
  • evil/good
    • View Profile
    • My Homepage
Re: Using ASM to Plot Pixels.
« Reply #18 on: March 24, 2007 »
It is faster to do the multiplications outside the loop, I think Mr.p Is right here, what might be clouding your judgement is that tinyptc_ext waits for the vbl.

Also if you have replaced the mmx libs etc you are using a fair chunk of rbraz's code anyway so just use tinyptc ext and precalc as much as possible outside loops :) Same in any language.
Shockwave ^ Codigos
Challenge Trophies Won:

Offline Paul

  • Pentium
  • *****
  • Posts: 1490
  • Karma: 47
    • View Profile
Re: Using ASM to Plot Pixels.
« Reply #19 on: March 24, 2007 »
just changing the contents of the array mot flipping or anything, 6000*800*600

time with precalc for 59.7245110761289
time without precalc 59.86356981124747
I will bite you - http://s5.bitefight.se/c.php?uid=31059
Challenge Trophies Won: