News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Console Input-Output

Started by RuiLoureiro, March 18, 2005, 03:32:51 PM

Previous topic - Next topic

AeroASM

Instead of mov eax,[ebx] / call eax why dont you just use call [ebx]

RuiLoureiro

Hi
    [ My problem with the internet provider i had some days ago put my mind abroad. I am sorry ].

Nilrem,
       Of course, CLS ! It helps.
       Sometimes we are with our mind in one direction and we forget the obvious things. So, the obvious is not the obvious. The reason why, the masm forum is a good place to stay and interchange questions and answers.
       Thank you Nilrem

AeroASM,
   When we are touching something, we try one thing or form, we try onother, etc. many times based on some model we have in our mind or because we begin with some model.
   Thank you. The light comes from something and your reply is very important. It helps.

Hi MichaelW,
   Are you upset, Michael ? [Messieur  De La Palisse said the same thing: eax is equal to eax. But dont think nothing more! You can say all things that i will never upset with you. I have you in a particular good consideration].

   I am like a cat after taking a good bath with hot water! When the water is cold, ... we put our legs [ mind ] to run [ into another direction ].

   Coming back to asm, i ran your code and it works well [ that example is important, IMO ]. But as i said before, i followed the help from pbrennick without thinking and i have fallen in a trap [ La Palisse said eax=eax - but only when we are not tired or so !]. «call  [eax]» is an indirect call. So, this is why "the call" goes to 4110 B568 and not to eax=40 1000. It takes 4110 B568 from the memory address 40 1000. It is explained [ sometimes our mind crashes, too. We already passed the 15 years old of age – i am not a whisky. What do we do in the masm forum if we did all things correctly ? So, it is better to stay here "to put" mistakes in the posts and "to talk" ... with you.
   My thanks to you, Michael.

Here is the code. I will post the complete example file as soon as possible.


; Action:
;        Draws the window in the _WindowBuffer and puts it in the screen buffer
;
; Input:
;       ebx    - window pointer
;
; Output:
;        clc:  OK
;
;        stc:  error
;
WindowMake          proc   
                    pushad
                    ;
                    call    WindowGetpType
                    jc      short _eWindowMake
                    ;
                    mov     eax, dword ptr [ebx - WndAtrOnp$]   ; color
                    shl     eax, 16
                    ;
                    mov     edx, dword ptr [ebx - WndWidth$]    ; width
                    mov     ecx, dword ptr [ebx - WndHeight$]   ; height
                    sub     ecx, 2
                    sub     edx, 2
                    ;
                    mov     edi, offset _WindowBuffer
                    call    LineSupDraw
                    ;
@@:             
                    call    LineMidDraw
                    loop    short @B
                    ;                 
                    call    LineInfDraw
                    ; ---------
                    ; Add Title
                    ; ---------
                    mov     edi, offset _WindowBuffer
                    call    TitleAdd
                    ; --------------
                    ; Add Msg or Tbl
                    ; --------------
                    call    WindowMsgAdd
                    ;
                    ; transfer to screen
                    ; ------------------
@@:             
                    mov     ecx, dword ptr [ebx - WndHeight$]   ; height
                    shl     ecx, 16
                    mov     eax, dword ptr [ebx - WndWidth$]    ; width
                    mov     cx, ax     
                    call    WindowPutScreen

                    ; ---------------------
                    ; Prc table of messages
                    ; ---------------------
                    mov     eax, dword ptr [ebx - WndMsgPrc$]
                    or      eax, eax
                    jz      short _eWindowMake
                    ;
                    call     dword ptr [ebx - WndMsgPrc$]      ; = call eax
                    ;
_eWindowMake:       popad
                    ret
WindowMake          endp

................................................................................................
In the following example i show some problems i had - points 1 to 7 ( Restrictions ? )


;
; 1. Symbol £: we cannot use at the beginning \ in the end of a name .
; 2. Addresses inside procedures: we cannot use them outside ?
; 3. Local variables and reserved words: for example, we cannot use «type»
; 4. Ending a procedure with «enpd»: we get too many erros [there is one].
; 5. We need 2 compilations to get the correct result after we correct one error.
; 6. invoke  ProcA, ADDR PcrocB: it gives an error
; 7. The program ends in the line 78 and it reports an error in the line 87
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    .486                                          ; create 32 bit code
    .model flat, stdcall                        ; 32 bit memory model
    option casemap :none                  ; case sensitive

    include \masm32\include\windows.inc
    include \masm32\include\masm32.inc
    include \masm32\include\kernel32.inc
    includelib \masm32\lib\masm32.lib
    includelib \masm32\lib\kernel32.lib
    include \masm32\macros\macros.asm
;...............................................................
ProcB       PROTO    pAdrA:DWORD
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    .data

;£NameVar1       dd 0            ; it gives too many errors
;NameVar£        dd 0            ; it gives an error

offset_testproc dd OFFSET testproc
;...............................................................
_ADDRtestproc   dd OFFSET _testproc1
                dd OFFSET _testproc2
.code
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; ««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
               mov   ebx, OFFSET offset_testproc
               mov   eax, [ebx]
               call  eax

               invoke   ProcB, ADDR ProcA                      ; undefined symbol Proc A

               mov   eax, input(13,10,"Press enter to exit...")
               exit
;****************************************************************
Endproc        proc
               print chr$("Endproc")
               ret
Endproc        enpd
;****************************************************************           
testproc        proc

_testproc1       print chr$("testproc1")
                 ret
  _testproc2:    print chr$("testproc2")
                 ret
testproc         endp
;****************************************************************           
testType        proc
                LOCAL  type:DWORD
                print chr$("testproc1")
                ret
testType        endp
;****************************************************************
ProcA          proc
               print chr$("ProcA")
               ret
ProcA          endp
;****************************************************************           
ProcB          proc pAdrA:DWORD
               print chr$("ProcB")
               ret
ProcB          endp
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start


my best regards to all of you.
Stay well
RuiLoureiro

MichaelW

Hi Rui,

No, I am not upset. I was attempting to make a clever joke, and it worked about as well as it usually does.

(1)
From the MASM 6.0 Programmer's Guide:
Quote
The first character of an identifier can be an alphabetic character (A-Z) or any of these four characters: @ _ $ ?

The other characters in the identifier can be any of the characters listed above or a decimal digit (0-9)

Avoid starting an identifier with the at sign (@), because MASM 6.0 predefines some special symbols starting with @ (see Section 1.2.3). Beginning an identifier with @ may also cause conflicts with future versions of the Macro Assembler.

You cannot terminate a name with "\" because MASM recognizes "\" as a line continuation character.

(2)
If by address you mean a code label, for a code label defined in a procedure, if the label is defined with a single colon it is visible only within the procedure, and if it is defined with a double colon (for example, mylabel::) it is visible throughout the module. For a label defined outside of any procedure (in "module-level" code), a code label defined with a single colon is visible throughout the module.

(3)
You cannot use a reserved word as an identifier, but an identifier can include a reserved word (for example, type_ or _type or mytype).

(4)
The correct spelling is "endp".

(5)
?

(6)
Invoke does not support forward references to arguments. To correct this problem, create a prototype for ProcA and place it somewhere above the Invoke statement.
eschew obfuscation

RuiLoureiro

Hi all
   Sorry, i could not reply until now.

Hi Michael:
A)   How are you ?
   About the joke, you succeed.
   Thank you for that help. It was very good and important.  :U
                 

B)   About point (6) « Invoke does not support forward references to arguments »

I think we can have another solution:

   Solution 1: create a prototype for ProcA and place it somewhere above the
         Invoke statement. [ Invoke, ..., ADDR ProcA, ...]

   Solution 2:                    mov    eax, offset ProcA  [ ProcA anywhere ]
                                  and then
                                                Invoke, ..., eax, ...
................................................................................
   I have been writing ( organizing and reorganizing ) procedures to print strings, tables of strings, and to open and close ( my ) windows etc., testing them etc. and, now,

i need to know how to WAIT X milliseconds  [is to Open, wait X ms, Close the window ].

   My windows are defined like this [is a variable like _WndWarn ]

               dd 9
_MsgWarn       db " Warning "
               dd 25
_MsgInside     db " Press a key to continue "

$SHADAVISO$          equ 1
$LARGURAAVISO$     equ 68 + $SHADAVISO$         
$ALTURAAVISO$       equ 7  + 1
$BUFFERAVISO$        equ $LARGURAAVISO$ * $ALTURAAVISO$

            dd 0                             ; Timer / Prc to exec
            ...
                  dd Amareloclaro_Azul  ; -48 Title colour
                  dd offset _MsgWarn   ; -44 Title pointer
            ;
            dd Cinzento_Negro          ; -40 shadow colour
            dd $SHADAVISO$            ; -36 Flag shadow =0,1,2
            ;
               dd 0                              ; -32 Flag  buffer Full=1 /Empty=0
               dd 3                               ; -28 Type 1 a 5
               dd Brancoclaro_Vermelho   ; -24 Wnd Color
               dd 10                               ; -20 Wnd Column
               dd 15                               ; -16 Wnd Line
               dd $ALTURAAVISO$         ; -12 Wnd height
               dd $LARGURAAVISO$         ;  -8 Wnd width
               dd $BUFFERAVISO$             ;  -4 Total do buffer em dwords
_WndWarn      dd $BUFFERAVISO$ dup (?) ; buffer


Here are the 2 basic procedures where i need to set a proc
         [call a procedure to wait EAX milliseconds].

How to do this ? Can you help me, please ?


; Action:   Opens the window defined by the pointer pWnd
;
; Input:    pWnd    - window pointer
;
WindowOpen          proc    pWnd:DWORD
                    push    esi
                    ;
                    ; Read window in the screen to buffer
                    ; -----------------------------------
                    mov     esi, pWnd
                    call    WindowRead
                    jc      short @F
                    ;
                    ; Draw new window ESI
                    ; -------------------
                    call    WindowMake
                    ;
                    mov     eax, dword ptr [esi - $WndFlgExe]
                    or      eax, eax
                    jz      short @F
                    ;
                    cmp     eax, 1
                    jne     short @F
                    ;
                    ; Wait time
                    ; ---------
                    mov     eax, dword ptr [esi - $WndPrcExe]
                   
                    [call    a procedure to wait EAX miliseconds]

                    invoke   WindowClose, esi

@@:                 pop     esi
                    ret
WindowOpen          endp
; --------------------------------------------------------------------------
; Action:   Closes the window defined by the pointer pWnd
;
; Input:     pWnd    - window pointer
;
WindowClose         proc   pWnd:DWORD
                    push   esi
                    ;
                    mov    esi, pWnd
                    call   WindowWrite
                    ;
                    pop    esi
                    ret
WindowClose         endp

...............................................................................................
Here is a sample of my work, where i used the last help from Michael:


; Action: Reads the screen buffer.
;
; Input:    esi   - string buffer   [ dwords attr (high) + chars (low) ]
;
; Output:   esi   - string buffer   [ dwords attr (high) + chars (low) ]
;
; Info:
;        uses _hCurScreen 
;        The Rectangle is in _RWRectCoord 
ScreenRead           proc 
                     pushad
                     ;
                     call     RectGetNLC
                     ;
                     mov      edi, _hCurScreen
                     invoke   ReadConsoleOutput, edi,  ; handle
                                                 esi,  ; buffer ( DWORDS )
                                                 edx,  ; Lines (H)-Cols (L)
                                                 0,    ; first buffer cell
                                                 ADDR _RWRectCoord  ; rectangle
                     jmp      _eScreenWrite
ScreenRead           endp
; -----------------------------------------------------------------------------
; Input:  esi   - string buffer   [ dwords attr (high) + chars (low) ]
;       
; Info:
;        uses _hCurScreen [ current screen handle ]
;    The Rectangle is in _RWRectCoord 
ScreenWrite       proc 
                  pushad
                  ;
                  call     RectGetNLC
                  ;
                  mov      edi, _hCurScreen
                  invoke   WriteConsoleOutput, edi,  ; handle
                                               esi,  ; buffer ( DWORDS )
                                               edx,  ; Lines (H)-Cols (L)
                                               0,    ; first buffer cell
                                               ADDR _RWRectCoord  ; rectangle
_eScreenWrite::   cmp      eax, 0
                  je       short @F
                  ;
                  clc
                  popad
                  ret
                  ;
@@:               stc
                  popad
                  ret
ScreenWrite       endp
;-------------------------------------------------
RectGetNLC        proc
                  ;
                  ; Coordinates
                  ; -----------
                  call     CoordGet
                  call     RectCnvNLC
                  ret
RectGetNLC        endp
; -------------------------------------------------
; Input:  ebx   - first cell
;         edx   - last cell 
;
; Output: edx   - number of Lines (H) + number of Columns (L)
;
RectCnvNLC        proc
                  mov   ecx, edx
                  shr   edx, 16
                  inc   ecx
                  inc   edx
                  ;
                  sub   cx, bx               
                  shr   ebx, 16
                  sub   dx, bx
RectCnvNLC        endp
;--------------------------------------------
; Input:  ebx   - Lin ( high ) + Col ( low )     Left +Top    = First point
;         edx   -  =           + Col + Len       Right+Bottom = Last  point
;
CoordGet          proc     
                  ;
                  ; Coordinates
                  ; -----------
                  mov      ebx, dword ptr [_RWRectCoord + 0]
                  mov      edx, dword ptr [_RWRectCoord + 4]
                  ret
CoordGet          endp

.......................................................................
At the end of this week, i hope to be using a new internet connection.
Thank you for all

Best regards
Stay well
Rui Loureiro

Nilrem


MichaelW

eschew obfuscation

RuiLoureiro

Hi

   Thank Nilrem and Michael.  :U
My flash windows are working well with Sleep or SleepEx. [my file with procedures about this has already 1087 lines]

   There is a problem with characters B7h, BDh, to close the corners. It is related with CodePage, i think. But i dont know how to use that function.
   The Doc. said  «SetConsoleCP sets the input code page used by the console .... wCodePageID = the identifier of the code page. The identifiers of the code pages available on the local computer are stored in the registry under the following key. HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePage»

How to access it ? I am not seeing what to do !

All good things to you.
My Thanks
Rui

Mark Jones

Quote from: RuiLoureiro on May 17, 2005, 04:36:11 PM
   There is a problem with characters B7h, BDh, to close the corners. It is related with CodePage, i think. But i dont know how to use that function.

Recently I was trying to build an ASCII table plugin for the WinAsm IDE and had much difficulty with codepages and high-ASCII characters. In short, it was a nightmare. :eek One thing I noticed was that high-ASCII characters were not being saved the same as they were written in the .asm file. You could try loading the .asm file into a hex editor and checking those bytes for correctness, or use the masm32 macro CHR$(B7) in the source instead.

Also I'm sure you know, but you can make ASCII characters by holding down ALT and keying the decimal value into the numeric keypad. (At least this is the case in the US, I assume it will work for you too.) :)
"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

RuiLoureiro

Hi Mark,

   1. About ALT decimal value ( keypad ), in the masm32 editor it doesnt give any of that characters i want. For example, ALT 183, ALT 184, ALT 200, ALT 205, ALT 201. When i worked in DOS editors ( in BC ), it worked well.

   2. About Code Pages, i think it is the same as in DOS, no ? For EUA and Europe, it is 437; For International is 850; Portugal is 860; Canada is 863, etc. This numbers were used in the Config.sys files.

   3. When i use 
                         invoke   GetConsoleCP
                         invoke   GetConsoleOutputCP

      i get the number 352h = 850 in both cases !

   4. It accepts 
                         invoke   SetConsoleCP, 860
                         invoke   SetConsoleOutputCP, 860

   but the problem is the same: chars 213, 184, 212 and 190 are not the usual and are the same in the case 850 or 860. They changed the character set. How to see the definition of each char ?

last thing: who is in the photo with one eye in one direction and the other in the other ? It looks like my son. And he does it with his eyes. I am not able.

Stay well

Mark Jones

Hi Rui (may I call you Rui?)

Quote from: RuiLoureiro on May 19, 2005, 10:09:19 PM
   1. About ALT decimal value ( keypad ), in the masm32 editor it doesnt give any of that characters i want. For example, ALT 183, ALT 184, ALT 200, ALT 205, ALT 201. When i worked in DOS editors ( in BC ), it worked well.

Yes I think the ALT-numpad trick only works in certain applications and in DOS.

I noticed that when I embedded high-ASCII characters into a source file, the values were not saved as the values I entered. i.e., an ALT-248 (0xF8h, the "degree" symbol here) would be saved as 0xB0h (but it still displays as a degree symbol on my screen...) These characters were saved the same way in the executable also... that is when I gave up understanding code pages. :)

In the Win32.hlp there is some interesting information if you search for "console."

Quote
   2. About Code Pages, i think it is the same as in DOS, no ? For EUA and Europe, it is 437; For International is 850; Portugal is 860; Canada is 863, etc. This numbers were used in the Config.sys files.

That sounds right. Admittedly, I don't have much experience with codepages. I did find some old DOS information about codepages here however.

Quote
   but the problem is the same: chars 213, 184, 212 and 190 are not the usual and are the same in the case 850 or 860. They changed the character set. How to see the definition of each char ?

That is a very good question. I converted my WinASM plugin into a console app which displays the ASCII table and codepage. But, changing the codepage seems to have no effect. My code must be very buggy, but maybe you can fix it. :) See the attached file.

Quote
last thing: who is in the photo with one eye in one direction and the other in the other ? It looks like my son. And he does it with his eyes. I am not able.

:lol  That photo was actually part of a junkmail advertisement. I cut out the guy and "doctored" it with Paint Shop Pro. Finally: junk mail is good for something! :bg  Okay because it was not entirely ethical, I changed it. :)

p.s. It is easy to "cross your eyes"... just take a pencil, stare at the eraser, and slowly bring it to your nose. Then your eyes will cross. :toothy

[attachment deleted by admin]
"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

Mark Jones

Aaah, here is more info from MSDN:

Quote
If the current console font is a fixed-pitch Unicode font, SetConsoleOutputCP changes the mapping of the character values into the glyph set of the font, rather than loading a separate font each time it is called. This affects how extended characters (ASCII value greater than 127) are displayed in a console window. However, if the current font is a default raster font, SetConsoleOutputCP does not affect how extended characters are displayed.

EDIT: also, the ASCII table application does show the codepage differences if the window is made fullscreen (ALT+ENTER)
"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

RuiLoureiro

#41
Hi Mark, [ yes you may call me Rui ]

   1. I saw your file Console Ascii table. It is interesting. In fullscreen i cannot see all characters. It gives the same set of characters with CodePage 437 and 860. Based in your last information, at the beginning of my program, i need to know what font is installed or i need to set one font that has the extended characters i need to use ( one that i know ). It is one more problem i have to solve at the starting point !

   2. In the fullscreen mode, it is different. The character set is that i want to use ! I think i need to study something about FONTS !

   3. I put my cons29.zip. The code and data is not clean because it is under development. In the future, some procedures or data structures may be different. In anyway, it is to see the codes of the keys, the structure of the key and mouse records, how to use colours, how to edit strings (my type), how to open and close (my) windows. This file was created in 8/05.

   4. As you can see, ALT-numpad doesnt serve me. My windows are made by other means. In the variable that defines the window, i set a field with one type and the procedure that opens the window, makes it based on a structure i defined for each type.

   5. Now, i am working in a set of all files i have, to see what i need to restructure. It is giving me more work !

Finally: i think you can help me when i was prepared to take the fonts problems again.

Stay well


[attachment deleted by admin]

RuiLoureiro

Hi
    My procedure KeyOnlyWait doesnt WAIT for a key when it is called by the second time.
    In the Laboratory, topic "Sugestions with MSVCRT code", Jibz posts a C example waitforkeypressed from which i tried to use WaitForSingleObject.

    The complete example is in the file char1.zip (an .asm & .exe).
    When we remove «;» in the line where is « (1) INSERT THIS », the next KeyOnlyWait doesnt work. I am not seeing whats wrong. Any help ?


; Action:
;        Clean the input buffer and wait for a key.
;
; Out:
;       clc: key was pressed -> clean the input buffer -> exit
;
;       stc: error
;
KeyOnlyWait         proc
                    LOCAL    nEvents:DWORD
                   
                    ; ------------------
                    ; Clean input buffer
                    ; ------------------
                    invoke    FlushConsoleInputBuffer, _hInputBuffer
                   
                    ; ----------------------
                    ; Wait for input records
                    ; ----------------------
_iKeyOnlyWait:      invoke    WaitForSingleObject, _hInputBuffer, INFINITE
                                                   ;0     ; returns immediately
                    cmp       eax, WAIT_FAILED
                    jne       short @F
                    ;
                    stc
                    ret
                    ;
@@:                 cmp       eax, WAIT_OBJECT_0
                    jne       short _iKeyOnlyWait         ; no-> return

                    ; --------------------------------------
                    ; Object is signaled -> Number of events
                    ; --------------------------------------
                    invoke    GetNumberOfConsoleInputEvents, _hInputBuffer,
                                                             ADDR nEvents
                    cmp       eax, 0
                    jne       short _KeyOnlyWait0
                    ;
                    stc       ; error
                    ret
                   
                    ; ----------------
                    ; Next input event
                    ; ----------------   
_KeyOnlyWait0:      mov       eax, nEvents
                    cmp       eax, 0
                    je        short _iKeyOnlyWait

                    ; -----------------
                    ; Read input buffer
                    ; -----------------
                    dec       eax
                    mov       nEvents, eax
                    ;
                    invoke    ReadConsoleInputW, _hInputBuffer,         
                                               ADDR _InputBuffer,       
                                               1,                 ; read 1
                                               ADDR _InputBuffer - 8
                    cmp      eax, 0
                    jne      @F                                    ; not error
                    ;         
                    stc
                    ret
                   
                    ; ----------------------
                    ;     Key pressed ?
                    ; ----------------------
@@:                 cmp    word ptr [_InputBuffer + 0], KEY_EVENT  ; EventType
                    jne    short _KeyOnlyWait0
                   
                    ; -----------------------------------------------
                    ; KEY was pressed, so Clean input buffer and EXIT
                    ; -----------------------------------------------
                    invoke    FlushConsoleInputBuffer, _hInputBuffer
                    ;
                    clc
                    ret
KeyOnlyWait         endp

;...............................................................................
Thanks


[attachment deleted by admin]

hutch--

 :bg

Thats why I posted a far smaller and more reliable polling loop version.


; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

wait_key proc

  @@:
    invoke Sleep,10
    call crt__kbhit
    test eax, eax
    jz @B

    invoke FlushConsoleInputBuffer,rv(GetStdHandle,STD_INPUT_HANDLE)

    ret

wait_key endp

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««


31 bytes in length, 0% processor usage and it does EXACTLY what its supposed to do.  :green
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

RuiLoureiro

Hi
   Thanks Hutch, but the problem is that i have not msvcrt.inc and msvcrt.lib
   I downloaded SP2, i installed SP2, i saw all files it contains one by one and it hasnt those files.
   Moreover, i saw msvcrt.dll file in the folder \windows\system32\, used DumpPE and i studied «How to create your own masm import libraries» from iczlion. It gives more work to get those files.

Here is an exmple that shows i havent msvcrt.inc\lib
; Assembling: C:\masm32\exampl12\makecimp\vcrtdemo\vcrtdemo.asm
;...............................................................................

Microsoft (R) Macro Assembler Version 6.14.8444
Copyright (C) Microsoft Corp 1981-1997.  All rights reserved.

Assembling: C:\masm32\exampl12\makecimp\vcrtdemo\vcrtdemo.asm
C:\masm32\exampl12\makecimp\vcrtdemo\vcrtdemo.asm(12) : fatal error A1000: canno
t open file : \masm32\include\msvcrt.inc
_
Assembly Error
Prima qualquer tecla para continuar . . .

    Whould you mind posting it here ?
Thanks