flat assembler
Message board for the users of flat assembler.

Index > Main > Where to start?

Goto page Previous  1, 2, 3, 4, 5, 6, 7  Next
Author
Thread Post new topic Reply to topic
Inagawa



Joined: 24 Mar 2012
Posts: 153
Inagawa 12 Apr 2012, 18:59
By the way, I have written my own library of functions on dealing with the console, but I have discovered a problem with my Console.WriteLine function. I can only feed it one string... How would I go about multiple?

Code:
;============================================================================
proc !Console.WriteLine uses ecx edx, Text

  ;=== WRITE A LINE OF TEXT ======================
  invoke       lstrlen, [Text]                                    ; Get length of the string
  invoke       WriteConsole, [_outHandle], [Text], eax, _ioTemp, 0

  ret
endp
    


I am guessing something like an infinite amount of parameters and iteration in printing them out, but how do I do something like that with a proc? Thanks for any suggestions. (Btw I have replied on the previous page)
Post 12 Apr 2012, 18:59
View user's profile Send private message Reply with quote
AsmGuru62



Joined: 28 Jan 2004
Posts: 1717
Location: Toronto, Canada
AsmGuru62 12 Apr 2012, 20:03
I see... the console we looking at here right now is not a DOS console - it is a Win32 console application and the thread mentioned is not the way to go. If you planning a side scroller game, where your world scrolls around sideways and up and down -- you need Win32 application for that. Now, sidescrollers can be done in a couple of ways:

1. Tiled approach - in here you can have a 2D matrix of tiles. For example, you can have 256x256 tiles, each tile can be 16x16 pixels in size. Then, every time the worlds needs painting - you examine the scrollbars and figure out what tiles to start painting with. This way the wolds can be scrolled around following some action. Each tile has a type and image to be drawn: it can be anything you desire -- sea, ground, mountains, trees - i.e. nature based world. or it can be walls inside some building, like a castle or some base.... no limit, really. All you need is images for tiles and the map of the world -- where each tile is.

2. You can have polygon based world -- it will look better then tiles, because tiles will allow only square corners in your world. With polygons, you can have much better worlds -- better looking, I mean. More realistic. Here you should have a coordinate system for polygons, so you can paint each polygon. Also, the scroll bars will set up the point of origin for the window and you paint only polygons visible at this moment.

Personally, I think #1 is easier for the beginner.
Post 12 Apr 2012, 20:03
View user's profile Send private message Send e-mail Reply with quote
AsmGuru62



Joined: 28 Jan 2004
Posts: 1717
Location: Toronto, Canada
AsmGuru62 12 Apr 2012, 20:06
Print the string like this one:
Code:
NextLine db 0Dh,0Ah,0
    

And the console will print on next line.
Or if you want to print multiple lines -- simply encode these bytes into text, like so:
Code:
Text2Lines db 'LINE #1',0Dh,0Ah,'LINE #2',0Dh,0Ah,0
    
Post 12 Apr 2012, 20:06
View user's profile Send private message Send e-mail Reply with quote
Inagawa



Joined: 24 Mar 2012
Posts: 153
Inagawa 12 Apr 2012, 20:29
I can print multiple lines. I know carriage return and line feed. But what if I want to make a call like this?

Code:
invoke    !Console.WriteLine, <'This is the first argument - %i', 0Dh, 0Ah>, eax ;<= EAX is the second argument
    


That would be two arguments, but my !Console.WriteLine only supports one argument..



Win32 application.. I don't think I am ready for that. I will study console, since there is not much left to explore.
And while creating some lame game I can at least focus on pure assembly in a console environment that I'll be
already familiar with. I think that is what I must do. I want to learn it properly, so I don't have any gaps in
knowledge later. Thanks for the info, though. Tiled approach would be my choice if I made the win32 app.

Can I ask how complex do you consider OpenGL to be in assembly? Because that is my
distant goal anyway, may as well break any dreams and hopes now. Very Happy
Post 12 Apr 2012, 20:29
View user's profile Send private message Reply with quote
AsmGuru62



Joined: 28 Jan 2004
Posts: 1717
Location: Toronto, Canada
AsmGuru62 12 Apr 2012, 20:35
I think you can find a few OpenGL codes here on the FASM forum.
Post 12 Apr 2012, 20:35
View user's profile Send private message Send e-mail Reply with quote
Inagawa



Joined: 24 Mar 2012
Posts: 153
Inagawa 13 Apr 2012, 19:27
I have rewritten the code for the third time (took the whole day, gahh). This time using the trick I've learned by studying the easy part of huvaligen code to make the console screen bigger.
I have also created my own basic windowing system. All the windows are objects and if I had mouse input, it should be easy to move and resize them.

But I do not understand huvaligen code, it's just too mashed together and I have no idea which part does what. It's a great piece of code, but certainly not for beginners. Guru, could you please explain the mouse input in some very easy fashion? Pretty please?

Image

Edit: Replaced the image
Post 13 Apr 2012, 19:27
View user's profile Send private message Reply with quote
AsmGuru62



Joined: 28 Jan 2004
Posts: 1717
Location: Toronto, Canada
AsmGuru62 13 Apr 2012, 20:09
This is the API you need for mouse in console:
http://msdn.microsoft.com/en-us/library/ms684961(v=vs.85).aspx

You need to make a thread which will call this function and read just one record. Then you check if this record represents a MOUSE_EVENT and if it does - you Post a custom message to your main thread and then in response to that message you do whatever needed in your panels.

That is a short explanation, but there is just too much there - read that link. You need a separate thread, because that function is a blocking call if no messages are detected in queue and you do not wish to block your main thread.

Also, take a look at PeekConsoleInput -- maybe you need this function, if you want to preserve the non-mouse messages in queue. Otherwise, they will be lost.

edit by revolution: Fixed URL
Post 13 Apr 2012, 20:09
View user's profile Send private message Send e-mail Reply with quote
Inagawa



Joined: 24 Mar 2012
Posts: 153
Inagawa 14 Apr 2012, 00:03
Oh god, it's 2AM, I am half dead, but I finally made it. I have working mouse input on a separate thread.
Thanks a lot for sending me in the right direction with the link. I also absolutely took apart huvaligen code,
this time documenting each line and finding out what it does. There are some things I don't understand - not
from assembly perspective, but simply "why do this" kind of. I'll ask tomorrow.
Ah, going to sleep with a feeling of victory. Cool
Post 14 Apr 2012, 00:03
View user's profile Send private message Reply with quote
mindcooler



Joined: 01 Dec 2009
Posts: 423
Location: Västerås, Sweden
mindcooler 14 Apr 2012, 09:42
Ask away, there are probably a lot of strange things in it; it isn't exactly a finished program, just experimental. If you wonder about the midiInGetNumDevs, it's supposed to support MIDI input as well in the future.
Post 14 Apr 2012, 09:42
View user's profile Send private message Visit poster's website MSN Messenger ICQ Number Reply with quote
Inagawa



Joined: 24 Mar 2012
Posts: 153
Inagawa 14 Apr 2012, 11:09
Yes, what I basically did at first was to comment out as much as I could of the code that seemed to do nothing. Also I noticed this

Code:
  jmp          .eventLoop

  ;
  ; Jump to the inputLoop - I don't think this code can be reached
  ;
  jmp          .inputLoop
    


Btw, thanks a lot for the code.
Post 14 Apr 2012, 11:09
View user's profile Send private message Reply with quote
mindcooler



Joined: 01 Dec 2009
Posts: 423
Location: Västerås, Sweden
mindcooler 14 Apr 2012, 21:27
Just leftovers from a do-while loop.
Post 14 Apr 2012, 21:27
View user's profile Send private message Visit poster's website MSN Messenger ICQ Number Reply with quote
Inagawa



Joined: 24 Mar 2012
Posts: 153
Inagawa 14 Apr 2012, 22:52
Can I ask where I've made a mistake?

Code:
struct STR

  thing1 dd ?
  thing2 dw ?
  thing3 dw ?

ends
   _s STR

  lea          ebx, [_s]

  mov          [ebx], DWORD 1
  mov          [ebx+4], WORD 1
  mov          [ebx+6], WORD 1

  cinvoke      printf, <'Thing 1 - %i', 10>, DWORD[ebx]
  cinvoke      printf, <'Thing 2 - %i', 10>, DWORD[ebx+4]
  cinvoke      printf, <'Thing 3 - %i', 10>, DWORD[ebx+6]
    


Output is

Code:
  Thing 1 - 1
  Thing 2 - 65537
  Thing 3 - 1
    


It's something obvious that I'm missing
Post 14 Apr 2012, 22:52
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20686
Location: In your JS exploiting you and your system
revolution 14 Apr 2012, 22:59
All invoke calls push a dword value onto the stack. The dword value at [ebx+4] is a combination of two word values forming a single dword value 0x00010001.

You can "fix" if like this:
Code:
  cinvoke      printf, <'Thing 1 - %i', 10>, DWORD[ebx]
movzx eax, WORD[ebx+4]
  cinvoke      printf, <'Thing 2 - %i', 10>, eax
movzx eax, WORD[ebx+6]
  cinvoke      printf, <'Thing 3 - %i', 10>, eax    
BTW: Why use explicit offsets when you have already defined a structure for it?
Post 14 Apr 2012, 22:59
View user's profile Send private message Visit poster's website Reply with quote
Inagawa



Joined: 24 Mar 2012
Posts: 153
Inagawa 15 Apr 2012, 08:38
Because I have a piece of code that gets memory allocated by VirtualAlloc and I get a pointer.
I then need to initialize that structure just from that handle.

You zero extend the argument and place it in EAX so there's no overlapping when you pass them. I do understand this. But How do I put this into a structure?

Code:
struct STR

  thing1 dd ?
  thing2 dw ?
  thing3 dw ?

ends
   _s STR
;=====================
  lea          ebx, [_s]

  mov          [ebx], DWORD 1
  ;
  ; _s STR:
  ; Offset 0 : DWORD 1
  ; Offset 1 : DWORD 1
  ; Offset 2 : DWORD 1
  ; Offset 3 : DWORD 1
  ;

  mov          [ebx+4], WORD 2
  movzx        eax, WORD[ebx+4]
  ;
  ; _s STR:
  ; Offset 0 : DWORD 1
  ; Offset 1 : DWORD 1
  ; Offset 2 : DWORD 1
  ; Offset 3 : DWORD 1
  ; Offset 4 : WORD 2
  ; Offset 5 : WORD 2
  ;

  mov          [ebx+6], WORD 3
  movzx        edx, WORD[ebx+6]
  ;
  ; _s STR:
  ; Offset 0 : DWORD 1
  ; Offset 1 : DWORD 1
  ; Offset 2 : DWORD 1
  ; Offset 3 : DWORD 1
  ; Offset 4 : WORD 2
  ; Offset 5 : WORD 2
  ; Offset 6 : WORD 3
  ; Offset 7 : WORD 3
  ;

  cinvoke      printf, <'Thing 1 - %i', 10>, DWORD[ebx]
  cinvoke      printf, <'Thing 2 - %i', 10>, eax
  cinvoke      printf, <'Thing 3 - %i', 10>, edx


    



Am I wrong about the offsets? MOV is not limited to DWORDs, why am I still getting an output of (1, 12, 582600)?

Please please use this code to get the idea across. So I can better relate
Post 15 Apr 2012, 08:38
View user's profile Send private message Reply with quote
dancho



Joined: 06 Mar 2011
Posts: 74
dancho 15 Apr 2012, 10:00
this coding style will help you with structs offsets, and
remember that printf trashing eax,ecx,edx ... registers
and as Rev already said printf expect dword size value on the stack ,
that is why we used movzx for thing2 and thing3...

Code:
                                          ;
                      struct STR 
                   thing1 dd ? 
                        thing2 dw ? 
                        thing3 dw ? 
                      ends 
                       _s STR
                      ;
                   
                    lea ebx,[_s]
                        mov [ebx+STR.thing1],1
                      mov [ebx+STR.thing2],2
                      mov [ebx+STR.thing3],3                  
                    
                    cinvoke printf,<'Thing 1 - %u',13,10>,[ebx+STR.thing1]
                      movzx edx,[ebx+STR.thing2]
                  cinvoke printf,<'Thing 2 - %u',13,10>,edx
                   movzx edx,[ebx+STR.thing3]
                  cinvoke printf,<'Thing 3 - %u',13,10>,edx
    


and for the mem alloc:
Code:
                        ; ptr to memory
                        ;
                        pMem dd 0
                                          ;
                  ; need 5 STR structs
                        ;
                   MEM_SIZE = sizeof.STR*5                 
                    invoke VirtualAlloc,0,MEM_SIZE,MEM_COMMIT,PAGE_READWRITE
                    ;
                   ; remember to check eax ?!
                  ;
                   mov [pMem],eax
                      mov ebx,eax
                 ;
                   ; fill struct 1
                     ;
                   mov [ebx+STR.thing1],1
                      mov [ebx+STR.thing2],1
                      mov [ebx+STR.thing3],1
                      ;
                   ; go to the next one
                        add ebx,sizeof.STR      
                    ;
                   ; fill struct 2
                     ;
                   mov [ebx+STR.thing1],2
                      mov [ebx+STR.thing2],2
                      mov [ebx+STR.thing3],2
                      ;
                   ; etc
                       
                    ;
                   ; remember to free mem
                      invoke VirtualFree,[pMem],0,MEM_RELEASE
    
Post 15 Apr 2012, 10:00
View user's profile Send private message Reply with quote
Inagawa



Joined: 24 Mar 2012
Posts: 153
Inagawa 15 Apr 2012, 11:50
Yes, the register thrashing is one of my constant mistakes.. It's the price I pay for learning HLL first.

But an amazing piece of code! I knew I could use an offset, but it never occurred to me I can use a structure member offset! So easy compared to how I did it. Thanks a lot, now I need to go play with this Very Happy
Post 15 Apr 2012, 11:50
View user's profile Send private message Reply with quote
Inagawa



Joined: 24 Mar 2012
Posts: 153
Inagawa 15 Apr 2012, 13:44
I think I am going crazy. When I run this code:
Code:
  mov cx, WORD 5
  cinvoke printf, <'%i',10>, ecx
    

it outputs 5. When I run the exact same code in my application, it outputs a random number. No code is manipulating CX before the call to printf. It is just as you see it here. Is there any way to explain this? I can't figure out where I could've done an error.

cinvoke translates to the code below, so how can CX be modified after it has been pushed on the stack?

Code:
PUSH ECX
CCALL [PRINTF]
    


I write a code like this:

Code:
  push ecx
  cinvoke printf, <'X: %i', 10>, [ebx+Window.Location.X]
  cinvoke printf, <'Y: %i', 10>, [ebx+Window.Location.Y]
  cinvoke printf, <'W: %i', 10>, [ebx+Window.Width]
  cinvoke printf, <'H: %i', 10>, [ebx+Window.Height]
  pop  ecx
    


ECX is modified after this runs. I am baffled. I can already imagine it's something primitive and I'll be ashamed.

Very Happy


Last edited by Inagawa on 15 Apr 2012, 13:55; edited 1 time in total
Post 15 Apr 2012, 13:44
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20686
Location: In your JS exploiting you and your system
revolution 15 Apr 2012, 13:46
CX != ECX
Code:
mov ecx,5
cinvoke printf, <'%i',10>,ecx    
Post 15 Apr 2012, 13:46
View user's profile Send private message Visit poster's website Reply with quote
Inagawa



Joined: 24 Mar 2012
Posts: 153
Inagawa 15 Apr 2012, 13:55
Edit: I'll rephrase the question. I am working with 16bit variables. How am I supposed to push and pop them, if push can only push a DWORD?

I have this code (I cut out the unimportant things in between):

Code:
mov          cx, [PosX] ; PosX is a WORD argument

;Now I need to printf out debug info and preserve CX

  push  ecx
  cinvoke printf, <'X: %i', 10>, [ebx+Window.Location.X]
  cinvoke printf, <'Y: %i', 10>, [ebx+Window.Location.Y]
  cinvoke printf, <'W: %i', 10>, [ebx+Window.Width]
  cinvoke printf, <'H: %i', 10>, [ebx+Window.Height]
  pop ecx

cinvoke printf, <'%i', 10>, cx ; <==== THIS should still be equal to PosX but it's not
    


Even though CX != ECX, pushing the 32bits on stack and then retrieving them should leave the low 16bits intact, no?
Post 15 Apr 2012, 13:55
View user's profile Send private message Reply with quote
Inagawa



Joined: 24 Mar 2012
Posts: 153
Inagawa 15 Apr 2012, 14:11
And even using this code at the end, as dancho said:
Code:
  movzx        edx, cx
  cinvoke      printf,<'Original CX - %i',13,10>,edx
    


It still outputs 0, not 5 (the original value)
Post 15 Apr 2012, 14:11
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page Previous  1, 2, 3, 4, 5, 6, 7  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-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.