flat assembler
Message board for the users of flat assembler.

Index > Main > Seeking alternate methods...

Goto page 1, 2  Next
Author
Thread Post new topic Reply to topic
bitshifter



Joined: 04 Dec 2007
Posts: 796
Location: Massachusetts, USA
bitshifter 04 May 2009, 08:39
Hello, i am seeking alternate methods for my pixel routine.
No matter how fast or slow your version is, i like to see it.
I am using double buffer in my program so buffer is at es:di.
Code:
    ;---------------------------------------------
    ;
    ; al: color
    ; bx: x
    ; cx: y
    ; di: buffer
    ;
    ; offset = y * 320 + x
    ; so...
    ; offset = (y << 6) + (y << 8) + x
    ;
    ;---------------------------------------------
    SetPixel:
        pusha
        mov     dx,cx
        shl     cx,6
        shl     dx,8
        add     di,bx
        add     di,cx
        add     di,dx
        mov     byte[di],al
        popa
        ret
    

_________________
Coding a 3D game engine with fasm is like trying to eat an elephant,
you just have to keep focused and take it one 'byte' at a time.
Post 04 May 2009, 08:39
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20309
Location: In your JS exploiting you and your system
revolution 04 May 2009, 08:46
So imul doesn't work for you then?
Code:
imul cx,cx,320    
Post 04 May 2009, 08:46
View user's profile Send private message Visit poster's website Reply with quote
bitshifter



Joined: 04 Dec 2007
Posts: 796
Location: Massachusetts, USA
bitshifter 04 May 2009, 08:51
Yes, but why take all the fun out of it?

_________________
Coding a 3D game engine with fasm is like trying to eat an elephant,
you just have to keep focused and take it one 'byte' at a time.
Post 04 May 2009, 08:51
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20309
Location: In your JS exploiting you and your system
revolution 04 May 2009, 09:19
bitshifter wrote:
... buffer is at es:di.
Code:
...
mov     byte[di],al  ;<--- where is es?
...    
I think you forgot something!
Post 04 May 2009, 09:19
View user's profile Send private message Visit poster's website Reply with quote
bitshifter



Joined: 04 Dec 2007
Posts: 796
Location: Massachusetts, USA
bitshifter 04 May 2009, 09:32
Is that ok if es = cs = ds...
Or should i use mov byte[es:di],al
Post 04 May 2009, 09:32
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20309
Location: In your JS exploiting you and your system
revolution 04 May 2009, 09:48
bitshifter wrote:
Is that ok if es = cs = ds...
No. You will overwrite your code!
bitshifter wrote:

Or should i use mov byte[es:di],al
Yes. And make sure that es <> cs and that es <> ss.
Post 04 May 2009, 09:48
View user's profile Send private message Visit poster's website Reply with quote
bitshifter



Joined: 04 Dec 2007
Posts: 796
Location: Massachusetts, USA
bitshifter 04 May 2009, 10:18
Ok thanks.
I guess i need to read up on segment registers more.
(I thought .com file entry sets all those to the same 0x100)

PS: <> means 'not equal to' correct?

_________________
Coding a 3D game engine with fasm is like trying to eat an elephant,
you just have to keep focused and take it one 'byte' at a time.
Post 04 May 2009, 10:18
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20309
Location: In your JS exploiting you and your system
revolution 04 May 2009, 10:47
bitshifter wrote:
Ok thanks.
I guess i need to read up on segment registers more.
(I thought .com file entry sets all those to the same 0x100)
The DOS .com file loader sets all segments to the same. But you need to change that else when writing pixels to the ES segment you will overwrite your code, data and stack.
bitshifter wrote:
PS: <> means 'not equal to' correct?
Yes, just like in the fasm conditional syntax.
Post 04 May 2009, 10:47
View user's profile Send private message Visit poster's website Reply with quote
bitshifter



Joined: 04 Dec 2007
Posts: 796
Location: Massachusetts, USA
bitshifter 04 May 2009, 11:52
First off, thanks for being so kind revolution :P
I am unsure about translation of your last post
so maybe you take a look at what i have here...
Code:
;------------------------------------------------
;
;------------------------------------------------
use16
org 0x100

        ;----------------------------------------
        ; enter graphics mode
        ;----------------------------------------
        mov     ax,0x0013
        int     0x10

    mloop:

        ;----------------------------------------
        ; clear buffer to desired color
        ;----------------------------------------
        mov     ax,0x0707   ; bk-fg pixel color (twice)
        mov     cx,0x7D00   ; 64k buffer bytes / 2
        mov     di,g_buffer ; destination pointer
        cld                 ; set direction for incrementing DI
        rep     stosw       ; stores word at AX into DI and increments DI

        ;----------------------------------------
        ; set color of buffer pixel
        ;----------------------------------------
        mov     al,0x01     ; bk-fg pixel color
        mov     bx,1        ; x position (column)
        mov     cx,1        ; y position (row)
        mov     di,g_buffer ; destination pointer
        call    SetPixel

        ;----------------------------------------
        ; wait for vertical reset
        ;----------------------------------------
        mov     dx,0x03DA
    vend:
        in      al,dx
        test    al,0x08
        jz      vend
    vres:
        in      al,dx
        test    al,0x08
        jnz     vres

        ;----------------------------------------
        ; copy buffer into video memory
        ;----------------------------------------
        push    es
        mov     ax,0xA000 ; video memory segment
        mov     es,ax
        xor     di,di
        mov     si,g_buffer
        mov     cx,0x7D00 ; 64k video memory bytes / 2
        cld
        rep     movsw
        pop     es

        ;----------------------------------------
        ; check for keypress
        ;----------------------------------------
        mov     ah,0x01
        int     0x16
        jz      mloop

        ;----------------------------------------
        ; enter text mode
        ;----------------------------------------
        mov     ax,0x0003
        int     0x10

        ;----------------------------------------
        ; return to operating system
        ;----------------------------------------
        int     0x20
        ret

    ;---------------------------------------------
    ;
    ; al: color
    ; bx: x
    ; cx: y
    ; di: buffer
    ;
    ; offset = y * 320 + x
    ; so...
    ; offset = (y << 6) + (y << 8) + x
    ;
    ;---------------------------------------------
    SetPixel:
        pusha
        mov     dx,cx
        shl     cx,6
        shl     dx,8
        add     di,bx
        add     di,cx
        add     di,dx
        mov     byte[es:di],al
        popa
        ret

;------------------------------------------------
;
;------------------------------------------------
g_buffer rb 64000
    

_________________
Coding a 3D game engine with fasm is like trying to eat an elephant,
you just have to keep focused and take it one 'byte' at a time.


Last edited by bitshifter on 04 May 2009, 15:57; edited 1 time in total
Post 04 May 2009, 11:52
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20309
Location: In your JS exploiting you and your system
revolution 04 May 2009, 12:00
That code only works because the total size is less than 0x500 bytes and uses almost no stack. Any code of substantial size will force g_buffer higher than 0x600 (or into your stack) and then you will get many problems.
Post 04 May 2009, 12:00
View user's profile Send private message Visit poster's website Reply with quote
bitshifter



Joined: 04 Dec 2007
Posts: 796
Location: Massachusetts, USA
bitshifter 04 May 2009, 12:12
So i need to use...
Code:
mov byte[es:di],al    

But do i need to change ES also? If so, where to?

_________________
Coding a 3D game engine with fasm is like trying to eat an elephant,
you just have to keep focused and take it one 'byte' at a time.
Post 04 May 2009, 12:12
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20309
Location: In your JS exploiting you and your system
revolution 04 May 2009, 14:18
bitshifter wrote:
But do i need to change ES also? If so, where to?
Well this will work in most circumstances:
Code:
mov ax,es
add ax,1 shl 12
mov es,ax    
Do it once at program startup and now your es segment is safe to write anywhere/anytime without clobbering your stack or code.
Post 04 May 2009, 14:18
View user's profile Send private message Visit poster's website Reply with quote
bitshifter



Joined: 04 Dec 2007
Posts: 796
Location: Massachusetts, USA
bitshifter 04 May 2009, 15:52
Nice revolution, thanks.
That works ok if my code plus my data are less than 4096 bytes, right?

I was blind to this type of problem since i was mostly
writing win32 apps, which have data and code sections.
Maybe i need to look into fasm and see how these work.
(doesnt it align these sections on 1024 byte boundary and pad the rest)

_________________
Coding a 3D game engine with fasm is like trying to eat an elephant,
you just have to keep focused and take it one 'byte' at a time.
Post 04 May 2009, 15:52
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20309
Location: In your JS exploiting you and your system
revolution 04 May 2009, 15:58
Segment registers are shift 4 places (x16) before adding to the address. So "1 shl 12" moves es up by 64kB.
Post 04 May 2009, 15:58
View user's profile Send private message Visit poster's website Reply with quote
bitshifter



Joined: 04 Dec 2007
Posts: 796
Location: Massachusetts, USA
bitshifter 04 May 2009, 16:04
Oh yeah, i forget the segments are unique every 16, duh...

_________________
Coding a 3D game engine with fasm is like trying to eat an elephant,
you just have to keep focused and take it one 'byte' at a time.
Post 04 May 2009, 16:04
View user's profile Send private message Reply with quote
r22



Joined: 27 Dec 2004
Posts: 805
r22 04 May 2009, 17:26
Code:
    SetPixel: 
        pusha 
        shl     cx,6 ; x*64
        lea     dx,[cx+cx*4] ; (x*64) + (x*64) * 4 = x*320
;;;;;;lea      cx,[cx+cx*4] ; dont even use dx
        add     di,bx
        add     di,dx 
;;;;;;add     di,cx ; dont even use dx
        mov     byte[es:di],al 
        popa 
        ret 
    


In short, I'd use LEA instead of the MOV, SHL, ADD
Post 04 May 2009, 17:26
View user's profile Send private message AIM Address Yahoo Messenger Reply with quote
Goplat



Joined: 15 Sep 2006
Posts: 181
Goplat 04 May 2009, 19:58
You can't use that kind of addressing with 16-bit registers. "lea dx,[ecx+ecx*4]" would work, although it would require a 386 or higher.
Post 04 May 2009, 19:58
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4024
Location: vpcmpistri
bitRAKE 04 May 2009, 21:40
Code:
    SetPixel:
        pusha
        add     di,bx
        shl     cx,6
        add     di,cx    ; +64y
        shl     cx,2
        add     di,cx    ; +256y
        stosb ; mov [es:di],al
        popa
        ret    
(should be inlined as it's used only once, and now has a dependency on the direction flag)
Code:
    SetPixel:
        pusha
   add bh,cl ; +256y
        shl cx,6
        add di,cx ; +64y
   mov [es:di+bx],al
        popa
        ret    
...reducing the instruction count.

Maybe, you've already seen Michael Abrash's Graphics Programming Black Book Special Edition. Imagine the buffer is zero indexed from ES, and DI is used for X value: then IMUL/MOV is sufficient, destroying only a single register, BX.
Code:
; ES - screen buffer
; DI = X-coordinate
; CX = Y-coordinate
; AL = color
imul bx,cx,320
mov [es:di+bx],al    
...may as well inline it. Note IMUL also accepts a memory address: IMUL BX,[Y],320 -- now, how cool is that? Also, there are eight register combinations that work: one must be either BX/BP and the other must be SI/DI, but X or Y can be assigned in a way favorable to the algorithm.
Post 04 May 2009, 21:40
View user's profile Send private message Visit poster's website Reply with quote
bitshifter



Joined: 04 Dec 2007
Posts: 796
Location: Massachusetts, USA
bitshifter 05 May 2009, 06:15
How can i make a data section and point ES and DS to it?
I think that the LES and LDS instructions may be what i need
to set ES and DS to there but i never had used them before.
Maybe by using a label at the beginning of my data?
Then i can set ES and DS to that segment with LES and LDS?
Then DI would be zero based?
I am so confused now Confused

EDIT: I have tried the snippet that revolution has provided
for setting ES and for some reason it does not work correctly...
The program did not explode in my face, but the display was incorrect.
Post 05 May 2009, 06:15
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4024
Location: vpcmpistri
bitRAKE 05 May 2009, 15:37
Say the (linear) address of the buffer is $43210 then ES would be $4321 to point at this buffer.
Code:
push $4321
pop es    
...would do it. Then DI would be the offset added to that segment -- the syntax used is SEGMENT:OFFSET. Segment is just the linear address divided by 16. So, if the least four bits are zero then a segment register can be used like a pointer - allowing the addressing mode to perform ES*16 + DI + BX to obtain the linear address.

$4321:$0000 and $4000:$3210 are the same address - keep rereading the above until this is understood.
Code:
; COM assumptions:
;          AX BX = 0000
;             CX = 00FF
; DX CS DS ES SS = .... (same unknown value)
;             SI = 0100
;             DI = FFFE
;             BP = 09..
;             SP = FFFE
;             IP = 0100    
revolution's code should work - might want to repost what you're working with.
Post 05 May 2009, 15:37
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page 1, 2  Next

< 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.