flat assembler
Message board for the users of flat assembler.

Index > Windows > Writing to an Edit Control

Goto page Previous  1, 2, 3, 4
Author
Thread Post new topic Reply to topic
AsmGuru62



Joined: 28 Jan 2004
Posts: 1628
Location: Toronto, Canada
AsmGuru62 14 Aug 2024, 18:18
The debugger shows that all variables in ".data" section which have "?" initializer are all set to zeroes.
My guess is FASM is following the "C" style of global and static variables.
So, that [edithwnd] is NULL and no issues may arise.
Post 14 Aug 2024, 18:18
View user's profile Send private message Send e-mail Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20343
Location: In your JS exploiting you and your system
revolution 14 Aug 2024, 20:24
There is no guarantee that the ? will be zero.

If you rely on it to be zero then initialise it in the code to make sure you get what you expect.
Post 14 Aug 2024, 20:24
View user's profile Send private message Visit poster's website Reply with quote
Stancliff



Joined: 30 Jun 2024
Posts: 54
Location: Florida
Stancliff 14 Aug 2024, 23:01
AsmGuru, I'm tagging you into the ring on this one. The child has been flaky all day and I presume it has to do with parameters for the create. Also, when I try to use the Msg macro to put a string on the data stack and pass it to Type the program shuts down as soon as it gets there.
Code:
; Working file for Go4th32 Forth Compiler
format PE GUI 4.0
entry start
include 'win32ax.inc'

macro SPush value               ; Push value to TOS (Top Of Stack)
{  sub edx, 4                   ; S - 4, new cell for TOS
   mov [edx], dword value       ; move value to TOS
}
macro Msg str                   ; msg string typed to screen
{     invoke  MessageBox,0,str,"Debug 3",MB_OK
   sub edx, 4                   ; S - 4, new cell for TOS
   mov [edx], dword str         ; move byte addr of string to eax
   call Type                    ; Display string on screen
}
section '.data' data readable writeable
; establish R and S stacks, BoR = bottom (end) of R, R0 = start of R
; == Return Stack =====
; R:      [ESP]                 ; Return Stack ptr, in ESP
BoR       DD 0                  ; Last cell of R, allow 64 cells ESP-256
R0        DD 0                  ; R stack start (one beyond first) ESP
; == Data Stack ======            Ret Stk start, at run = initial [ESP]
; S:      [EDX]                 ; Data Stack ptr, in EDX
BoS:      DD 128 Dup ?          ; Last cell of S, allow 128 cells
S0:                             ; S Stack start (one beyond first)

; Note: many good names from Forth are reserved by assembler, find alt's
NameSz   EQU 256                 ; max name cnt, increases dictionary size
New^     DD Reserved             ; ptr to next unused rec in Name
N^       DD 0                    ; Name Ptr, index for Name, was DP
TIB      DB 128 Dup " "          ; Term Input Buf adr, 128 b
T^       DD 0                    ; Text Ptr to current source, was IN
Pad      DB 128 Dup " "          ; Pad adr, 128 b
P^       DD Pad                  ; Pad ptr (temp work area)
H^       DD EndKern              ; ptr to current unused cell for code
Fence    DD Reserved -17         ; adr of last protected dictionary word
Base     DD 10                   ; initial value for base conversion

; Start Dictionary with major words of kernal core
; Names have 8 char length w/trailing zeros, no cnt byte for string
; Code Adr = 4 byte, Param Adr = 4 byte, Status = 1 byte (0=IMM,1=Defer)
Name:
  DB  "Cold",0,0,0,0
    DD Cold,0
    DB 1
  DB  "Abort",0,0,0
    DD Abort,0
    DB 1
  DB  "Quit",0,0,0,0
    DD Quit,0
    DB 1
  DB  "Query",0,0,0
    DD Query,0
    DB 1
  DB  "Type",0,0,0,0
    DD Type,0
    DB 1
Reserved: DB ((NameSz *17) +Name -Reserved) Dup ?  ; clear Name space
; Forth searches the dictionary to find the address of a command.  My bare
; bones kernal will need close to 60 names.  The Forth standard has almost
; 140 names, and with extensions like floating point, a simple assembler,
; and various data structures this can easily go over 200.

; Windows assignments
  _class       TCHAR 'Go4th',0
  _title       TCHAR 'Go4th32',0
  _about_title TCHAR 'About Go4th32',0
  _about_text  TCHAR 'Windows based Forth Compiler',13,10,\
                     'Created with FLAT assembler.',0
  _edit        TCHAR 'EDIT',0
  _error       TCHAR 'Startup failed.',0
  _fontface    TCHAR 'Courier New',0

  _bEnter  dd ?                 ; flag for 'Return' detection
  editfont dd ?                 ; return from CreateFont in WindowProc
  edithwnd dd ?                 ; handle for child from CreateWindow(2)
  parhwnd  dd ?                 ; handle for parent from CreateWindow(1)
  client RECT
  msg MSG

IDC_MLEDIT = 1001               ; ID for 'EDIT' control
IDR_ICON   = 17
IDR_MENU   = 37
         ; Menu entries
IDM_FILE   = 100
IDM_NEW    = 110
IDM_OPEN   = 120
IDM_EXIT   = 130
IDM_SVSEL  = 140
IDM_SAVE   = 150
IDM_SAVEAS = 160

IDM_EDIT   = 200
IDM_UNDO   = 210
IDM_FIND   = 220
IDM_CUT    = 230
IDM_COPY   = 240
IDM_PASTE  = 250
IDM_DEL    = 260

IDM_HELP   = 900
IDM_ABOUT  = 910

wc WNDCLASS 0,WindowProc,0,0,NULL,NULL,NULL,COLOR_BTNFACE+1,NULL,_class
Banner:   DB "Go4th: The Windows Forth Compiler",13,10,0
NewLine:  DB 13,10,0
Prompt:   DB "4th? ",0

section '.idata' import data readable writeable
   library    advapi32,          'ADVAPI32.DLL',\
              comctl32,          'CONCTL32.DLL',\
              comdlg32,          'COMDLG32.DLL',\
              gdi32,             'GDI32.DLL',\
              kernel32,          'KERNEL32.DLL',\
              shell32,           'SHELL32.DLL',\
              user32,            'USER32.DLL',\
              wsock32,           'WSOCK32.DLL'
   include    'api\advapi32.inc'
   include    'api\comctl32.inc'
   include    'api\comdlg32.inc'
   include    'api\gdi32.inc'
   include    'api\kernel32.inc'
   include    'api\shell32.inc'
   include    'api\user32.inc'
   include    'api\wsock32.inc'

section '.rsrc' resource data readable
directory     RT_MENU, menus,  RT_VERSION, versions,  RT_ICON, icons,\
              RT_GROUP_ICON, group_icons

resource  menus,       IDR_MENU, LANG_ENGLISH +SUBLANG_DEFAULT, main_menu
resource  versions,    1, LANG_NEUTRAL, version
resource  group_icons, IDR_ICON, LANG_NEUTRAL, main_icon
resource  icons,       1, LANG_NEUTRAL, icon_data

  versioninfo version,VOS__WINDOWS32,VFT_APP,VFT2_UNKNOWN,LANG_ENGLISH+\
            SUBLANG_DEFAULT,0,\
              'FileDescription','MiniPad - example program',\
              'LegalCopyright','No rights reserved.',\
              'FileVersion','1.0',\
              'ProductVersion','1.0',\
              'OriginalFilename','MINIPAD.EXE'
  icon main_icon,icon_data,'Go4th.ico'

menu main_menu
    menuitem '&File', IDM_FILE, MFR_POPUP
          menuitem '&New', IDM_NEW
          menuitem '&Open', IDM_OPEN
          menuitem '&Exit', IDM_EXIT
          menuseparator
          menuitem '&SaveSelect', IDM_SVSEL
          menuitem 'Sa&ve', IDM_SAVE
          menuitem 'Save &As', IDM_SAVEAS, MFR_END
    menuitem '&Edit', IDM_EDIT, MFR_POPUP
          menuitem '&Undo', IDM_UNDO
          menuitem '&Find', IDM_FIND
          menuseparator
          menuitem '&Cut', IDM_CUT
          menuitem 'C&opy', IDM_COPY
          menuitem '&Paste', IDM_PASTE
          menuitem '&Delete', IDM_DEL, MFR_END
    menuitem '&Help',IDM_HELP, MFR_POPUP + MFR_END ; LAST POPUP - MFR_END"
          menuitem '&About', IDM_ABOUT, MFR_END

section '.code' code readable executable writeable
  start:
          mov     [R0],esp      ; set esisting stack point as stack start
          mov     [BoR],esp     ; End of stack will offset from ESP
          sub     [BoR],256     ; allow 64 cells for local return stack

; Cold:  full restart, reset N^ , New^, and Fence, run Abort
Cold:     mov     eax, [Name]
          mov     [N^], eax
          mov     eax, [Fence +17]
          mov     [New^], eax
; Abort:  reset data stack, set base, run Quit
Abort:    mov     edx, S0        ; clear S, wipes all pending parameters
          mov     [Base], 10
; Quit:  reset return stack. clears all outstanding function calls
Quit:    ; mov     esp, R0       ; clear R, cancels all pending functions

        invoke  GetModuleHandle,0
        mov     [wc.hInstance],eax
        invoke  LoadIcon,eax,IDR_ICON
        mov     [wc.hIcon],eax
        invoke  LoadCursor,0,IDC_ARROW
        mov     [wc.hCursor],eax
        invoke  RegisterClass,wc
        test    eax,eax
        jz      error

        invoke  LoadMenu,[wc.hInstance],IDR_MENU
        invoke  CreateWindowEx,0,_class,_title,WS_TILEDWINDOW+\
        WS_VISIBLE,200,100,900,600,NULL,eax,[wc.hInstance],NULL
;        mov     [parhwnd],eax
        test    eax,eax
        jz      error

  msg_loop:
        invoke  GetMessage,msg,NULL,0,0
        cmp     eax,0
        je      end_loop
        jb      error
        ; Some message received
        mov     [_bEnter], 0    ; clear test flag for 'Return'
        mov     ecx, msg
        mov     eax, [edithwnd]
        cmp     [ecx + MSG.hwnd], eax
        jne     .translate
        ; message to be processed by [edithwnd]
        cmp     [ecx + MSG.message], WM_CHAR
        jne     .translate
        ; Message was WM_CHAR, was it [ENTER]?
        cmp     [ecx + MSG.wParam], VK_RETURN
        jne     .translate
        ; [edithwnd] is getting WM_CHAR for [ENTER] key. raise a flag.
        inc     [_bEnter]
.translate:
        invoke  TranslateMessage,msg
        invoke  DispatchMessage,msg
        ; Message is processed, test flag for processing 'Return'
        cmp     [_bEnter], 0
        je      msg_loop
        call    Query
        jmp     msg_loop
error:  invoke  MessageBox,NULL,_error,NULL,MB_ICONERROR+MB_OK
end_loop:
        invoke  ExitProcess,[msg.wParam]

; Query:  Move a null terminated string into Terminal Input Buffer
Query:  mov     [TIB], 122      ; input limit (128 -prompt & null)
        invoke  SendMessage,[edithwnd],EM_GETLINECOUNT,0,0
        dec     eax             ; Last line is blank, back up one
        dec     eax             ; try one more (this confuses me)
        invoke  SendMessage,[edithwnd],EM_GETLINE,eax,TIB
        mov     [TIB +eax], 0   ; add null to string
; Test results - Write input line back out
invoke  MessageBox,0,TIB,"Debug 1",MB_OK
        invoke  SendMessage,[edithwnd],EM_SETSEL,-1,-1
        invoke  SendMessage,[edithwnd],EM_REPLACESEL,0,TIB
        Msg     TIB
        ret

; Type: (str)  output str to screen
Type:
invoke  MessageBox,0,dword[edx],"Debug 2",MB_OK
        invoke  SendMessage,[edithwnd],EM_SETSEL,-1,-1
        invoke  SendMessage,[edithwnd],EM_REPLACESEL,0, dword[edx]
        add     edx,4           ; drop TOS
        ret

; Add most new code here

proc WindowProc hwnd,wmsg,wparam,lparam
        push    ebx esi edi
        mov     eax,[wmsg]
        cmp     eax,WM_CREATE
        je      .wmcreate
        cmp     eax,WM_SIZE
        je      .wmsize
        cmp     eax,WM_SETFOCUS
        je      .wmsetfocus
        cmp     eax,WM_COMMAND
        je      .wmcommand
        cmp     eax,WM_DESTROY
        je      .wmdestroy
  .defwndproc:
        invoke  DefWindowProc,[hwnd],[wmsg],[wparam],[lparam]
        ret
  .wmcreate:
        invoke  GetClientRect,[hwnd],client
invoke  MessageBox,0,"Child 1","Debug 0",MB_OK
        invoke  CreateWindowEx,0,_edit,0,WS_VISIBLE+ES_MULTILINE+\
                WS_HSCROLL+WS_VSCROLL+ES_AUTOHSCROLL+ES_AUTOVSCROLL+\
                WS_CHILD+ES_WANTRETURN,[client.left],[client.top],\
                [client.right],[client.bottom],[hwnd],IDC_MLEDIT,\
                [wc.hInstance],NULL
invoke  MessageBox,0,"Child 2","Debug 0",MB_OK
                ; IDC_MLEDIT
        mov     [edithwnd],eax
        or      eax,eax
        jz      .finish
        invoke  CreateFont,16,0,0,0,0,FALSE,FALSE,FALSE,ANSI_CHARSET,\
                OUT_RASTER_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,\
                FIXED_PITCH+FF_DONTCARE,0
                ;  FF_DONTCARE  +FF_MODERN,_fontface
        mov     [editfont],eax
        or      eax,eax
        jz      .finish
        invoke  SendMessage,[edithwnd],WM_SETFONT,eax,FALSE

        invoke  SendMessage,[edithwnd],EM_SETSEL,-1,-1
        invoke  SendMessage,[edithwnd],EM_REPLACESEL,0,Banner
        invoke  SendMessage,[edithwnd],EM_SETSEL,-1,-1
        invoke  SendMessage,[edithwnd],EM_REPLACESEL,0,Prompt
;        Msg     Banner
;        Msg     Prompt
        ret
  .wmsize:
        invoke  GetClientRect,[hwnd],client
        invoke  MoveWindow,[edithwnd],[client.left],[client.top],\
        [client.right],[client.bottom],TRUE
        ret
  .wmsetfocus:
        invoke  SetFocus,[edithwnd]
        ret
  .wmcommand:
        mov     eax,[wparam]
        and     eax,0FFFFh
        cmp     eax, IDM_NEW
        je      .new
        cmp     eax, IDM_OPEN
        je      .open
        cmp     eax, IDM_SVSEL
        je      .svSel
        cmp     eax, IDM_SAVE
        je      .save
        cmp     eax, IDM_SAVEAS
        je      .saveAs
        cmp     eax, IDM_UNDO
        je      .undo
        cmp     eax, IDM_FIND
        je      .find
        cmp     eax, IDM_CUT
        je      .cut
        cmp     eax, IDM_COPY
        je      .copy
        cmp     eax, IDM_PASTE
        je      .paste
        cmp     eax, IDM_DEL
        je      .del
        cmp     eax, IDM_ABOUT
        je      .about
        cmp     eax, IDM_EXIT
        je      .wmdestroy
        jmp     .defwndproc

  .new: invoke  SendMessage,[edithwnd],WM_SETTEXT,0,0
        ret
  .open:                       ; Load file to Edit Control

        ret
  .svSel:                      ; Write Selected to a File
        invoke  SendMessage,[edithwnd],EM_GETSEL,0,0

        ret
  .save:                       ; Write Session to a File

        ret
  .saveAs:                     ; Write Session to a different File name

        ret
  .undo: invoke  SendMessage,[edithwnd],EM_UNDO,0,0
        ret
  .find:                       ; Get Search str and try to Find it in text

        ret
  .cut:  invoke SendMessage,[edithwnd],WM_CUT,0,0
        ret
  .copy: invoke SendMessage,[edithwnd],WM_COPY,0,0
        ret
  .paste:invoke SendMessage,[edithwnd],WM_PASTE,0,0
        ret
  .del:  invoke SendMessage,[edithwnd],WM_CLEAR,0,0
        ret
  .about:invoke MessageBox,[parhwnd],_about_text,_about_title,MB_OK
        ret
  .wmdestroy:
        invoke  DeleteObject,[editfont]
        invoke  PostQuitMessage,0
  .finish:
        ret
endp
EndKern:        ; New compiled functions will be added starting here.
    
Post 14 Aug 2024, 23:01
View user's profile Send private message Reply with quote
AsmGuru62



Joined: 28 Jan 2004
Posts: 1628
Location: Toronto, Canada
AsmGuru62 15 Aug 2024, 14:47
1. I think we should set all '?' into '0' as revolution suggested.
2. What should I do to create an issue in the code? Steps?
3. We also need to preserve ESI,EDI,EBX in the Window Procedure, because it is requirement from OS.
Post 15 Aug 2024, 14:47
View user's profile Send private message Send e-mail Reply with quote
Stancliff



Joined: 30 Jun 2024
Posts: 54
Location: Florida
Stancliff 15 Aug 2024, 17:53
I will set the var's to zero, no prob.
I eventually need esi, edi, and ebx unless I do a lot of my later processing from vars instead of registers. Currently it isn't happening so that isn't my problem. I noticed that the Msg macro is crashing the windows when I assign a string addr to my S stack (edx). On rare occasions Type will print something, but mostly failure.
I put PushAD and POPAD around the call to Query and nothing changed that I could see. As a guess I wonder if windows is using most of the reg's and leaving none for me but EAX?
I fully expect the top of my Compiler code to originate where Query is called. I need Type printing strings before I can do much else. It is essential for getting status and debug info as I try to add more functions.
Post 15 Aug 2024, 17:53
View user's profile Send private message Reply with quote
AsmGuru62



Joined: 28 Jan 2004
Posts: 1628
Location: Toronto, Canada
AsmGuru62 15 Aug 2024, 21:44
I have noticed that you are debugging your code with "MessageBox" calls.
I suggest to download OllyDbg and use it --- an excellent tool, I've been using it for decades, nothing but joy.
Windows will use all registers except: EBX,ESI,EDI,EBP,ESP --- which means the code below will lose EDX after calling Windows API:
Code:
; Type: (str)  output str to screen
Type:
invoke  MessageBox,0,dword[edx],"Debug 2",MB_OK
        invoke  SendMessage,[edithwnd],EM_SETSEL,-1,-1
        invoke  SendMessage,[edithwnd],EM_REPLACESEL,0, dword[edx]
        add     edx,4           ; drop TOS
        ret
    

I will post some more analysis later --- have something to do right now.
Post 15 Aug 2024, 21:44
View user's profile Send private message Send e-mail Reply with quote
AsmGuru62



Joined: 28 Jan 2004
Posts: 1628
Location: Toronto, Canada
AsmGuru62 15 Aug 2024, 22:52
Ok, so few things:
Code:
proc WindowProc hwnd,wmsg,wparam,lparam
        push    ebx esi edi
        mov     eax,[wmsg]
        cmp     eax,WM_CREATE
        je      .wmcreate
    

The PUSH-es are not needed, just use "uses" keyword:
Code:
proc WindowProc uses ebx esi edi, hwnd,wmsg,wparam,lparam
        mov     eax,[wmsg]
        cmp     eax,WM_CREATE
        je      .wmcreate
    

Also, when processing the WM_CREATE, WM_SIZE, WM_COMMAND --- WindowProc should return EAX=0 and it does not. Just make a label inside WindowProc:
Code:
.return_zero:
    xor eax,eax
    ret
    

And jump to it from all the places you have "RET".
The line below is moving BYTE as 1st byte in TIB, but Windows wants a WORD there, not BYTE:
Code:
Query:  mov     [TIB], 122      ; input limit (128 -prompt & null)
    

Need to specify type directly:
Code:
Query:  mov     word [TIB], 122      ; input limit (128 -prompt & null)
    

Instead of EDX being a stack pointer --- you can use one of EBX,ESI,EDI.
Even better, use a model of a stack, where you are not dependent on the values in any registers.
And, of course ESP --- this register changes when you CALL any function or RETURN from one of your own functions.
Post 15 Aug 2024, 22:52
View user's profile Send private message Send e-mail Reply with quote
Stancliff



Joined: 30 Jun 2024
Posts: 54
Location: Florida
Stancliff 15 Aug 2024, 23:01
AsmGuru62 wrote:
I have noticed that you are debugging your code with "MessageBox" calls. I suggest to download OllyDbg and use it --- an excellent tool, I've been using it for decades, nothing but joy.

Windows will use all registers except: EBX,ESI,EDI,EBP,ESP --- which means the code below will lose EDX after calling Windows API:
Code:
; Type: (str)  output str to screen
Type:
invoke  MessageBox,0,dword[edx],"Debug 2",MB_OK
        invoke  SendMessage,[edithwnd],EM_SETSEL,-1,-1
        invoke  SendMessage,[edithwnd],EM_REPLACESEL,0, dword[edx]
        add     edx,4           ; drop TOS
        ret
    

A good print goes a long way and I have never used a debugger, prob will give it a try.
Since you specifically did not mention EDX why did you say the code will break. IF wiwdows isn't using ESP and EBP then I could use both for stack pointers, it would be an improvement. I am worried you reversed the negation of the sentence. As long as windows can stick to the hidden registers I would have no problem, but my current problem leads me to believe the public registers are being used for something.
Post 15 Aug 2024, 23:01
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20343
Location: In your JS exploiting you and your system
revolution 15 Aug 2024, 23:09
EAX, ECX and EDX are not preserved in the STDCALL convention. Meaning that invoke will change those registers.
Post 15 Aug 2024, 23:09
View user's profile Send private message Visit poster's website Reply with quote
Ali.Z



Joined: 08 Jan 2018
Posts: 718
Ali.Z 16 Aug 2024, 00:38
you should read about x86 calling conventions, and for debugging use ollydbg and outputdebugstring function and keep your eyes on log window.

_________________
Asm For Wise Humans
Post 16 Aug 2024, 00:38
View user's profile Send private message Reply with quote
Stancliff



Joined: 30 Jun 2024
Posts: 54
Location: Florida
Stancliff 16 Aug 2024, 03:44
revolution wrote:
EAX, ECX and EDX are not preserved in the STDCALL convention. Meaning that invoke will change those registers.

In the standard calling convention who saves and restores those registers?
You just said that EBP is NOT used so I can make it my data stack instead of EDX, is this valid?
Using ESP as the return stack is perfectly reasonable since that was it's design intention. The big question is whether windows is using it at the same time I would be. Is there going to be a collision or do we use them at separate times? (alternating as such)

I opened OllyDbg it and had trouble seeing the faint color contrast. When I went into appearances the lines were not even showing up due to the colors selected. I also need a larger font for more clarity. Not impossible, just working hard against me seeing much of anything. Plus I have no idea how it works... another learning curve.

I'm 66 and about 30% blind at this point. My cataract surgeon barely cleared me to drive at the minimum required vision level and I currently don't even have a license. I'm saying my vision is BAD.

More comments and responses tomorrow, it's nearly midnight
Post 16 Aug 2024, 03:44
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20343
Location: In your JS exploiting you and your system
revolution 16 Aug 2024, 03:54
It is "normal" to use EBP as a pointer into the stack.

It is NOT normal to manipulate ESP directly.

Windows, and all OSes, do not use your stack, ever. It is your stack. Do with it whatever you want. But I suggest you don't try to be "clever" with it. Just use it the natural way and then the programming is much simpler and has fewer bugs.
Post 16 Aug 2024, 03:54
View user's profile Send private message Visit poster's website Reply with quote
uu



Joined: 20 Jul 2024
Posts: 44
uu 16 Aug 2024, 08:44
Stancliff wrote:

I opened OllyDbg it and had trouble seeing the faint color contrast. ....I also need a larger font for more clarity.


Me too, with my shortsightedness. But I can increase the font size in x64dbg (another popular debugger) for better clarity.

There is also setting for colors.


Description: Larger font in x64dbg
Filesize: 121.36 KB
Viewed: 875 Time(s)

Capture.PNG


Post 16 Aug 2024, 08:44
View user's profile Send private message Reply with quote
Furs



Joined: 04 Mar 2016
Posts: 2505
Furs 16 Aug 2024, 13:27
revolution wrote:
It is "normal" to use EBP as a pointer into the stack.

It is NOT normal to manipulate ESP directly.

Windows, and all OSes, do not use your stack, ever. It is your stack. Do with it whatever you want. But I suggest you don't try to be "clever" with it. Just use it the natural way and then the programming is much simpler and has fewer bugs.
Are you sure about that? Raymond Chen says the opposite.
Post 16 Aug 2024, 13:27
View user's profile Send private message Reply with quote
Stancliff



Joined: 30 Jun 2024
Posts: 54
Location: Florida
Stancliff 16 Aug 2024, 15:14
Thanks revolution, I feel you give decent advice. I am more worried about learning assumptions or methods that have become entrenched and need to be honored for safety reasons in situations where I don't have final authority. Dealing with my operating system falls into that group. If windows really needs a register I want to avoid it but I have to learn it from somewhere. You guys often keep me informed where I do weird things. I based my software on a 40 year old design and am trying to make it more modern, not throw it out and start over.
Post 16 Aug 2024, 15:14
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20343
Location: In your JS exploiting you and your system
revolution 16 Aug 2024, 20:15
Furs wrote:
revolution wrote:
It is "normal" to use EBP as a pointer into the stack.

It is NOT normal to manipulate ESP directly.

Windows, and all OSes, do not use your stack, ever. It is your stack. Do with it whatever you want. But I suggest you don't try to be "clever" with it. Just use it the natural way and then the programming is much simpler and has fewer bugs.
Are you sure about that? Raymond Chen says the opposite.
Yes, I am sure of that. You misunderstand what the article says. If you use fancy tricks to access memory below ESP (the "red zone") then you are accessing memory beyond your stack and into no-man's-land.

Everything above ESP is your stack. The OS never touches it.

Everything below ESP is not your stack. Indeed, memory below ESP isn't even guaranteed to be present, because it might be a guard page, or no page at all. If you skip over the guard page then you get a page fault, and your code crashes, even though you can theoretically still be within your address allocation.
Post 16 Aug 2024, 20:15
View user's profile Send private message Visit poster's website Reply with quote
Stancliff



Joined: 30 Jun 2024
Posts: 54
Location: Florida
Stancliff 17 Aug 2024, 00:28
Agreed, he was saying to not mess with space reserved for the stack since the stack can move down most any time and change the data. As long as it's used as a stack it is good.

I had to rebuild from MiniPad for about the eight time, but the child is working, the data stack is working, and I/O is working.
Code:
; Working file for Go4th32 Forth Compiler
format PE GUI 4.0
entry start
include 'win32ax.inc'

macro SPush value               ; Push value to TOS (Top Of Stack)
{  sub      [Stk], 4            ; S - 4, new cell for TOS
   mov      [Stk], dword value  ; move value to TOS
}
macro Msg str                   ; msg string typed to screen
{  sub     [Stk], 4             ; S - 4, new cell for TOS
   mov     [Stk], dword str     ; move addr of string to Stk
           call Type            ; Display string on screen
}

section '.data' data readable writeable
; establish R and S stacks, BoR = bottom (end) of R, R0 = start of R
; == Return Stack =====
; R:       [ESP]                ; Return Stack ptr, in ESP
BoR        DD 0                 ; Last cell of R, allow 64 cells ESP-256
R0         DD 0                 ; R stack start (one beyond first) ESP
; == Data Stack ======            Ret Stk start, at run = initial [ESP]
; S:       [Stk]                ; Data Stack ptr, in Stk
BoS:       DD 128 Dup ?         ; Last cell of S, allow 128 cells
S0:                             ; S Stack start (one beyond first)

; Note: many good names from Forth are reserved by assembler, find alt's
NameSz     EQU 256              ; max name cnt, increases dictionary size
New^       DD Reserved          ; ptr to next unused rec in Name
N^         DD 0                 ; Name Ptr, index for Name, was DP
TIB        DB 128 Dup " "       ; Term Input Buf adr, 128 b
T^         DD 0                 ; Text Ptr to current source, was IN
Pad        DB 128 Dup " "       ; Pad adr, 128 b
P^         DD Pad               ; Pad ptr (temp work area)
H^         DD EndKern           ; ptr to current unused cell for code
Fence      DD Reserved -17      ; adr of last protected dictionary word
Stk        DD S0                ; data stack implemented in a variable
Base       DB 10                ; initial value for base conversion
State      DB 0                 ; Compiler/Interpreter state, 1=comp

; Start Dictionary with major words of kernal core
; Names have 8 char length w/trailing zeros, no cnt byte for string
; Code Adr = 4 byte, Param Adr = 4 byte, Status = 1 byte (0=IMM,1=Defer)
Name:
  DB  "Cold",0,0,0,0
    DD Cold,0
    DB 1
  DB  "Abort",0,0,0
    DD Abort,0
    DB 1
  DB  "Quit",0,0,0,0
    DD Quit,0
    DB 1
  DB  "Query",0,0,0
    DD Query,0
    DB 1
  DB  "Type",0,0,0,0
    DD Type,0
    DB 1
  DB  "Interp",0,0
    DD Interp,0
    DB 1
  DB  "Wrd",0,0,0,0,0
    DD Wrd,0
    DB 1
Reserved: DB ((NameSz *17) +Name -Reserved) Dup ?  ; clear Name space
; Forth searches the dictionary to find the address of a command.  My bare
; bones kernal will need close to 60 names.  The Forth standard has almost
; 140 names, and with extensions like floating point, a simple assembler,
; and various data structures this can easily go over 200.

  _class       TCHAR 'Go4th',0
  _title       TCHAR 'Go4th32',0
  _about_title TCHAR 'About Go4th32',0
  _about_text  TCHAR 'Windows based Forth Compiler',13,10,\
                     'Created with FLAT assembler.',0
  _edit        TCHAR 'EDIT',0
  _error       TCHAR 'Startup failed.',0
  _fontface    TCHAR 'Courier New',0

  _bEnter  dd 0                 ; flag for 'Return' detection
  editfont dd 0                 ; return from CreateFont in WindowProc
  parhwnd  dd 0                 ; handle for parent window from Create1
  edithwnd dd 0                 ; handle for editor child from Create2
  linehwnd dd 0                 ; handle for single line child from Create3
  client   RECT                 ; ptr to RECT struct
  msg      MSG                  ; ptr to MSG struct

IDC_MLEDIT = 1001               ; ID for 'EDIT' control
IDR_ICON = 17
IDR_MENU = 37

  ; Menu entries
IDM_FILE   = 100
IDM_NEW    = 110
IDM_OPEN   = 120
IDM_EXIT   = 130
IDM_SVSEL  = 140
IDM_SAVE   = 150
IDM_SAVEAS = 160

IDM_EDIT   = 200
IDM_UNDO   = 210
IDM_FIND   = 220
IDM_CUT    = 230
IDM_COPY   = 240
IDM_PASTE  = 250
IDM_DEL    = 260

IDM_HELP   = 900
IDM_ABOUT  = 910

wc WNDCLASS 0,WindowProc,0,0,NULL,NULL,NULL,COLOR_BTNFACE+1,NULL,_class
Banner:   DB "Go4th: The Windows Forth Compiler",0
NewLine:  DB 13,10,0
Prompt:   DB 13,10,"4th? ",0

section '.idata' import data readable writeable
   library    advapi32,          'ADVAPI32.DLL',\
              comctl32,          'CONCTL32.DLL',\
              comdlg32,          'COMDLG32.DLL',\
              gdi32,             'GDI32.DLL',\
              kernel32,          'KERNEL32.DLL',\
              shell32,           'SHELL32.DLL',\
              user32,            'USER32.DLL',\
              wsock32,           'WSOCK32.DLL'
   include    'api\advapi32.inc'
   include    'api\comctl32.inc'
   include    'api\comdlg32.inc'
   include    'api\gdi32.inc'
   include    'api\kernel32.inc'
   include    'api\shell32.inc'
   include    'api\user32.inc'
   include    'api\wsock32.inc'

section '.rsrc' resource data readable
directory     RT_MENU, menus,  RT_VERSION, versions,  RT_ICON, icons,\
              RT_GROUP_ICON, group_icons

resource  menus,       IDR_MENU, LANG_ENGLISH +SUBLANG_DEFAULT, main_menu
resource  versions,    1, LANG_NEUTRAL, version
resource  group_icons, IDR_ICON, LANG_NEUTRAL, main_icon
resource  icons,       1, LANG_NEUTRAL, icon_data

  versioninfo version,VOS__WINDOWS32,VFT_APP,VFT2_UNKNOWN,LANG_ENGLISH+\
      SUBLANG_DEFAULT,0,\
          'FileDescription','Go4th32 Forth Compiler',\
          'LegalCopyright','RDStancliff (c) 2024 All rights reserved',\
          'FileVersion','1.0',\
          'ProductVersion','1.0',\
          'OriginalFilename','Go4th32.exe'
  icon main_icon,icon_data,'Go4th.ico'

menu main_menu
    menuitem '&File', IDM_FILE, MFR_POPUP
          menuitem '&New', IDM_NEW
          menuitem '&Open', IDM_OPEN
          menuitem '&Exit', IDM_EXIT
          menuseparator
          menuitem '&SaveSelect', IDM_SVSEL
          menuitem 'Sa&ve', IDM_SAVE
          menuitem 'Save &As', IDM_SAVEAS, MFR_END
    menuitem '&Edit', IDM_EDIT, MFR_POPUP
          menuitem '&Undo', IDM_UNDO
          menuitem '&Find', IDM_FIND
          menuseparator
          menuitem '&Cut', IDM_CUT
          menuitem 'C&opy', IDM_COPY
          menuitem '&Paste', IDM_PASTE
          menuitem '&Delete', IDM_DEL, MFR_END
    menuitem '&Help',IDM_HELP, MFR_POPUP + MFR_END ; LAST POPUP - MFR_END"
          menuitem '&About', IDM_ABOUT, MFR_END

section '.code' code readable executable writeable
  start:
        mov     [R0],esp        ; save esisting stack point as upper bound
        mov     [BoR],esp       ; End of stack will offset from ESP...
        sub     [BoR],256       ; allow 64 cells for lower bound

Cold:   mov     eax, [Name]
        mov     [N^], eax       ; Name to N^, N^ ready to scan Name table
        mov     eax,[Fence +17] ; Fence is last word delete protected
        mov     [New^], eax     ; New^ gets next added word
Abort:  mov     [Stk], S0       ; clear S, wipes all pending parameters
        mov     [Base], 10      ; system starts with Base 10
Quit:   mov     [State],0       ; system starts in Interpret state

        invoke  GetModuleHandle,0
        mov     [wc.hInstance],eax
        invoke  LoadIcon,eax,IDR_ICON
        mov     [wc.hIcon],eax
        invoke  LoadCursor,0,IDC_ARROW
        mov     [wc.hCursor],eax
        invoke  RegisterClass,wc
        cmp     eax,0
        jz      error

        invoke  LoadMenu,[wc.hInstance],IDR_MENU
        invoke  CreateWindowEx,0,_class,_title,WS_OVERLAPPEDWINDOW+\
        WS_VISIBLE,200,100,1000,600,NULL,eax,[wc.hInstance],NULL
        cmp     eax,0
        jz      error

msg_loop:
        invoke  GetMessage,msg,NULL,0,0
        cmp     eax,0
        je      end_loop
        jb      error
                                ; Some message received
        mov     [_bEnter],0     ; clear test flag for 'Return'
        mov     ecx, msg
        mov     eax, [edithwnd]
        cmp     [ecx + MSG.hwnd], eax
        jne     .translate
                                ; message to be processed by [edithwnd]
        cmp     [ecx + MSG.message], WM_CHAR
        jne     .translate
                                ; Message was WM_CHAR, was it [ENTER]?
        cmp     [ecx + MSG.wParam], VK_RETURN
        jne     .translate
                                ; [edithwnd] getting [ENTER] key. flag
        inc     [_bEnter]
.translate:
        invoke  TranslateMessage,msg
        invoke  DispatchMessage,msg
                                ; Message sent, process flag for 'Return'
        cmp     [_bEnter], 0
        je      msg_loop

        call    Query
;        Msg     NewLine
        Msg     Prompt

        jmp     msg_loop
error:   invoke  MessageBox,NULL,_error,NULL,MB_ICONERROR+MB_OK
end_loop:invoke  ExitProcess,[msg.wParam]

; Type: (str)  print output str to screen
Type:   invoke  SendMessage,[edithwnd],EM_SETSEL,-1,-1
        invoke  SendMessage,[edithwnd],EM_REPLACESEL,0, dword[Stk]
        add     [Stk],4         ; pop TOS
        ret

; Query:  Move a null terminated string into Terminal Input Buffer
Query:  mov     word[TIB],122   ; input limit (128 - prompt & null)
        invoke  SendMessage,[edithwnd],EM_GETLINECOUNT,0,0
        dec     eax             ; Last line is blank, back up one
        dec     eax             ; try one more (this confuses me)
        invoke  SendMessage,[edithwnd],EM_GETLINE,eax,dword TIB
        mov     [TIB +eax], 0   ; add null to string
        ret

;Interpret:
Interp:
        ret

;Word:
Wrd:
        ret

; add most new functions here

proc WindowProc hwnd,wmsg,wparam,lparam
        push    ebx esi edi
        mov     eax,[wmsg]
        cmp     eax,WM_CREATE
        je      .wmcreate
        cmp     eax,WM_SIZE
        je      .wmsize
        cmp     eax,WM_SETFOCUS
        je      .wmsetfocus
        cmp     eax,WM_CHAR
        je      .wmchar
        cmp     eax,WM_COMMAND
        je      .wmcommand
        cmp     eax,WM_DESTROY
        je      .wmdestroy
  .defwndproc:
        invoke  DefWindowProc,[hwnd],[wmsg],[wparam],[lparam]
        jmp     .finish
  .wmcreate:
        invoke  GetClientRect,[hwnd],client
        invoke  CreateWindowEx,0,_edit,0,WS_VISIBLE+ES_WANTRETURN+\
        WS_CHILD+WS_HSCROLL+WS_VSCROLL+ES_AUTOHSCROLL+ES_AUTOVSCROLL+\
        ES_MULTILINE,[client.left],[client.top],[client.right],\
        [client.bottom],[hwnd],0,[wc.hInstance],NULL

        or      eax,eax
        jz      .finish
        mov     [edithwnd],eax
        invoke  CreateFont,16,0,0,0,0,FALSE,FALSE,FALSE,ANSI_CHARSET,\
        OUT_RASTER_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,\
        FIXED_PITCH+FF_DONTCARE,NULL
        or      eax,eax
        jz      .finish
        mov     [editfont],eax
        invoke  SendMessage,[edithwnd],WM_SETFONT,eax,FALSE
        Msg     Banner
        Msg     Prompt
        jmp     .finish
  .wmsize:
        invoke  GetClientRect,[hwnd],client
        invoke  MoveWindow,[edithwnd],[client.left],[client.top],\
        [client.right],[client.bottom],TRUE
        jmp     .finish
  .wmsetfocus:
        invoke  SetFocus,[edithwnd]
        jmp     .finish
  .wmchar:
          invoke  SendMessage,[edithwnd],WM_CHAR,ebx,ecx
          cmp     ebx,VK_RETURN
          jne     .defwndproc
          jmp     .defwndproc
  .wmcommand:
          mov     eax,[wparam]
          and     eax,0FFFFh
          cmp     eax, IDM_NEW
          je      .new
          cmp     eax, IDM_OPEN
          je      .open
          cmp     eax, IDM_SVSEL
          je      .svSel
          cmp     eax, IDM_SAVE
          je      .save
          cmp     eax, IDM_SAVEAS
          je      .saveAs
          cmp     eax, IDM_UNDO
          je      .undo
          cmp     eax, IDM_FIND
          je      .find
          cmp     eax, IDM_CUT
          je      .cut
          cmp     eax, IDM_COPY
          je      .copy
          cmp     eax, IDM_PASTE
          je      .paste
          cmp     eax, IDM_DEL
          je      .del
          cmp     eax, IDM_ABOUT
          je      .about
           cmp     eax, IDM_EXIT
          je      .wmdestroy
          jmp     .defwndproc

   .new:  invoke  SendMessage,[edithwnd],WM_SETTEXT,0,0
          jmp     .finish
   .open:                       ; Load file to Edit Control

          jmp     .finish
   .svSel:invoke  SendMessage,[edithwnd],EM_GETSEL,0,0
                                ; Write Selected to a File
          jmp     .finish
   .save:                       ; Write Session to a File

          jmp     .finish
   .saveAs:                     ; Write Session to a different File name

          jmp     .finish
   .undo: invoke  SendMessage,[edithwnd],EM_UNDO,0,0
          jmp     .finish
   .find:                       ; Get Search str and try to Find it in text

          jmp     .finish
   .cut:  invoke  SendMessage,[edithwnd],WM_CUT,0,0
          jmp     .finish
   .copy: invoke  SendMessage,[edithwnd],WM_COPY,0,0
          jmp     .finish
   .paste:invoke  SendMessage,[edithwnd],WM_PASTE,0,0
          jmp     .finish
   .del:  invoke  SendMessage,[edithwnd],WM_CLEAR,0,0
          jmp     .finish
  .about: invoke  MessageBox,[parhwnd],_about_text,_about_title,MB_OK
          jmp     .finish
  .wmdestroy:
          invoke  DeleteObject,[editfont]
          invoke  PostQuitMessage,0
  .finish:        ret
endp
EndKern:        ; New compiled functions will be added starting here.
    
Post 17 Aug 2024, 00:28
View user's profile Send private message Reply with quote
Stancliff



Joined: 30 Jun 2024
Posts: 54
Location: Florida
Stancliff 18 Aug 2024, 02:37
I have had to come back and grab copies of this twice already, it corrupts so quickly. I have started to work ahead importing functions. Will be busy for a while.
Post 18 Aug 2024, 02:37
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

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