Ok, I haven't touched assembly in a couple years and I've forgotten pretty much everything I learned before (I am, as you can see, a member, here, and did contribute for a while a long time ago, though I doubt anyone remembers me).

I've forgotten exactly how to do the real basic console input and output in a 32bit windows program. Pretty much all the code I've found googling has been geared towards using actual windows, but all I want right now is the console (I don't need a fancy interface for what I'm trying).

Can anyone either give me a little bit of code, or link me to someplace that deals with 32bit console input/output (preferably geared towards NASM, as I can't stand needing to toss in a whole bunch of damn libraries and such if I don't need them, and most MASM tutorials want me to do just that).

My goal right now is to learn enough assembly to do the necessary ASM programming required to program your own hobby operating system kernel. Most of that can be done in C, but there are parts in ASM that are unavoidable, and so I need to brush up (heavily) on my Assembly. I don't need to learn how to interface with the windows API, I just need to do basic text input and output, since my kernel will only have basic text input/output for a long time anyway.
Posted on 2008-03-29 00:51:57 by Bobbias
If you want to "do the real basic console input and output in a 32bit windows program" you can't avoid the win32 api.
If you want to "program your own hobby operating system kernel" then it isn't windows or even DOS - it's the BIOS or direct hardware I/O.
Have a look at OS Construction at the FASM site
Posted on 2008-03-29 01:04:23 by sinsi
Thanks for the response, but it doesn't really help me...

My point was that I wanted to use as little Windows API as necessary, because there's more to coding assembly than simply doing input and output. I'd program in DOS if I had that on my computer, but I don't. I don't need to make a window just to output whatever calculation I might want to make. I don't even need a MessageBox. All I need is a "DOS" console. Plus, it's easier to take input from a console, than a window...

I'd try to get my kernel to the point where I could do basic textual I/O if it wasn't for the fact that I'm currently having a hell of a time trying to get it booted in VMWare (I don't have another computer to boot it on, nor do I have an actual floppy drive in this computer, which makes some things a LOT harder).

I don't even have linux on here (because linux seems to disagree with me and I end up breaking things like my partition tables really quickly.) So I'd rather get better at assembly programming in general at the moment.

Basically, I'm just asking what I need to to to get a console application and do consol etext I/O in windows because aside from the exact calls I'm going to need to make, all algorithms, text manipulation, etc. etc. etc. will more or less be the same.
Posted on 2008-03-29 01:13:52 by Bobbias
Its easier to take input from a console than a window?
I disagree.
Common controls such as EDIT are windows.
Getting data from them is not more difficult than getting data from a console stream.



Posted on 2008-03-29 11:57:58 by Homer
Bobbias, I remember you. Or your interesting nick :)
Console input/output is done via "int 21h" iirc, function 3 iirc.
I don't know which interrupts/"functions" are implemented by BIOS alone, and which are added later by DOS - you have to look-up materials like the ones Sinsi gave.
In the worst case, you'll handle the keyboard semi-directly and draw the screen yourself in text-mode :P (addresses A000 or B000 ?)
Maybe you also forget that for 32-bit, you have to switch to protected-mode.
It's kinda a mess initially.

what Sinsi meant for "console under windows" is the WriteFile/ReadFile, which are internally used by the C funcs printf() and scanf(). Not fancy GUI.
I think VMWare makes things a lot easier. Faster boots, combined with some custom app to update the partition with your new kernel should be great.
Posted on 2008-03-29 20:34:28 by Ultrano
Well, nice to see that there's some memory there, lol.

Well, there's a whole bunch of wasted space and such setting up a window and such, I figured it would probably take less space etc. (I'm trying to make this compact, not waste time dealing with unnecessary windows only stuff, etc.) to do this using the basic text I/O supported in windows using a console.

For example, I'm trying to make something that might do something like this:


int main()
{
int NumA, NumB, NumC;

cout << "This is a basic demonstration of what I'm talking about..." << endl;
cout << "Input a number:";
cin >> NumA;
cout << "Now input a second number:";
cin >> NumB;
NumC = NumA + NumB;
cout << "NumA + NumB = " << NumC << endl;

return 0;
}


This is C++, and a LOT more basic than what I plan on actually doing (I'll figure out something advanced to do so that I use a lot of math, and loops, and so-forth, maybe a recursive routine), but the code serves to show you what I want to do (in windows, for now.)

I'll tackle all the VGA textmode stuff when I'm working on the OS. For now, I want to work in windows simply because it's a lot easier to test my ASM. Once I'm confident that I'm good enough with ASM again, I'll get back onto working on the OS.

(Oh, and disregard anything sloppy or messed up in that C++ stuff, that was me being lazy and typing it up in notepad, so if anything's weird, just ignore it, lol. I'm one of those coders constantly fixing little things like forgotten semicolons and stupid stuff like that when the compiler complains.)
Posted on 2008-03-30 13:31:44 by Bobbias
You could be using some nifty macros for input and output... Look at the following:


.386
.model flat,stdcall
option casemap:none

include    \masm32\include\windows.inc
include    \masm32\include\kernel32.inc
include    \masm32\include\user32.inc
include    \masm32\include\masm32.inc

includelib  \masm32\lib\kernel32.lib
includelib  \masm32\lib\user32.lib
includelib  \masm32\lib\masm32.lib

cout MACRO Text, LineFeed
local szText
local szTextSize
.data
szText byte Text, LineFeed
szTextSize dword sizeof szText
.code
invoke WriteConsole, out_handle, offset szText, szTextSize, offset written, 0
ENDM

string MACRO Buffer
invoke lstrlen, Buffer
invoke WriteConsole, out_handle,  Buffer, eax, offset written, 0
ENDM

cin MACRO Buffer, ToRead

invoke ReadConsole, in_handle,  Buffer, ToRead, offset written, 0
ENDM

.data
hello      db 'Hello World!',0

.data?
out_handle              dd  ?
in_handle              dd  ?
pNumberOfCharsWritten  dd  ?
written dd ?
szTemp db 128 dup (?)
.const
CRLF equ 13, 10

.code

start:

    call    AllocConsole
    push STD_OUTPUT_HANDLE
    call GetStdHandle
    mov    out_handle,eax
    push    STD_INPUT_HANDLE
    call    GetStdHandle
    mov    in_handle,eax

cout "This is a Test", CRLF
cout "Tell me your name:", 0
cin offset szTemp, 30
string offset szTemp
cout "is a very nice name", CRLF
cin offset szTemp, 30

    push 0
    call    ExitProcess

END start


I whopped up these macros pretty quick and they could certainly be better but they do seem to do a basic job.
I know it's masm. Hopefully this will give you an idea and you will be able to translate it to Nasm or whatever.

Cheers
Posted on 2008-03-30 15:55:16 by JimmyClif
Alright, thanks. I've actually switched over to MASM now, lol. I'll use NASM for my OS related stuff, but I'll use MASM for windows ASM, just because it's a bit easier.
Posted on 2008-03-31 00:19:12 by Bobbias

Alright, thanks. I've actually switched over to MASM now, lol. I'll use NASM for my OS related stuff, but I'll use MASM for windows ASM, just because it's a bit easier.


NASMX???
Posted on 2008-03-31 07:22:21 by SpooK
Well, coming from a C/C++ background, .IF structures are really good for making things go quickly for me in ASM. A lot easier than doing all the cmp/jxx stuff, lol.
Basically, I'm being lazy.
Posted on 2008-03-31 19:09:36 by Bobbias
I think that's what SpooK was hinting at:

%include '..\..\..\inc\nasmx.inc'
%include '..\..\..\inc\win32\windows.inc'
%include '..\..\..\inc\win32\kernel32.inc'
%include '..\..\..\inc\win32\user32.inc'
%include '..\..\..\inc\win32\stdwin.inc'

entry    demo10


proc    demo10

    invoke  GetModuleHandleA, dword NULL
    mov      , eax
    invoke  WinMain, dword hInstance, dword NULL, dword NULL, dword SW_SHOWNORMAL
    invoke  ExitProcess, dword NULL
    ret

endproc

proc    WinMain, hinst, hpinst, cmdln, dwshow

    invoke  LoadIconA, dword NULL, dword IDI_APPLICATION
    mov      edx, eax
    mov      eax, dword argv(hinst)
    mov      ebx, dword szClass
    mov      ecx, dword WndProc
    mov      , eax
    mov      , ebx
    mov      , ecx
    mov      , edx
    mov      , edx

    invoke  RegisterClassExA, dword wc

    StdWindow szClass, szTitle, 100, 120, 212, 232, NULL,
    mov      , eax

    invoke  ShowWindow, dword hWnd, dword argv(dwshow)
    invoke  UpdateWindow, dword hWnd

    do
        invoke  TranslateMessage, dword message
        invoke  DispatchMessageA, dword message
        invoke  GetMessageA, dword message, dword NULL, dword NULL, dword NULL
    while eax, !=, 0


    mov      eax, dword
    ret

endproc

proc    WndProc, hwnd, umsg, wparam, lparam


    switch dword argv(umsg)
    case dword WM_CREATE

        ButtonCtl szStringA, 500, 0, 0, 100, 40, argv(hwnd),
        ButtonCtl szStringB, 501, 100, 0, 100, 40, argv(hwnd),
        StaticCtl szContent, 502, 0, 40, 200, 40, argv(hwnd),
        ComboCtl szContent, 503, 0, 80, 200, 100, argv(hwnd),
        ListBoxCtl szContent, 504, 0, 106, 200, 100, argv(hwnd),

    case dword WM_COMMAND
        if argv(wparam), ==, dword 500
            invoke  MessageBoxA, dword NULL, dword szMessageA, dword szTitle, dword MB_OK
        elsif argv(wparam), ==, dword 501
            invoke MessageBoxA, dword NULL, dword szMessageB, dword szTitle, dword MB_OK
        else
            jmp near .defwndproc
        endif

    case dword WM_DESTROY

        invoke  PostQuitMessage, dword NULL

    default
        .defwndproc:
        invoke  DefWindowProcA, dword argv(hwnd), dword argv(umsg), dword argv(wparam), dword argv(lparam)

    endswitch
    ret

endproc


    hInstance:  resd 1
    hWnd:        resd 1


    szStringA:  db    "Click Me!", 0x0
    szStringB:  db    "Me Too!", 0x0
    szContent:  db    "Win32Nasm Demo #10", 0x0
    szMessageA: db    "With the NasmX Library...", 0x0
    szMessageB: db    "Assembly is a cinche!", 0x0
    szTitle:    db    "Demo10", 0x0
    szClass:    db    "Demo10Class", 0x0

    wc:
    istruc WNDCLASSEX
        at WNDCLASSEX.cbSize,          dd    WNDCLASSEX_size
        at WNDCLASSEX.style,            dd    CS_VREDRAW + CS_HREDRAW
        at WNDCLASSEX.lpfnWndProc,      dd    NULL
        at WNDCLASSEX.cbClsExtra,      dd    NULL
        at WNDCLASSEX.cbWndExtra,      dd    NULL
        at WNDCLASSEX.hInstance,        dd    NULL
        at WNDCLASSEX.hIcon,            dd    NULL
        at WNDCLASSEX.hCursor,          dd    NULL
        at WNDCLASSEX.hbrBackground,    dd    COLOR_BTNFACE + 1
        at WNDCLASSEX.lpszMenuName,    dd    NULL
        at WNDCLASSEX.lpszClassName,    dd    NULL
        at WNDCLASSEX.hIconSm,          dd    NULL
    iend

    message:
    istruc MSG
        at MSG.hwnd,                    dd    NULL
        at MSG.message,                dd    NULL
        at MSG.wParam,                  dd    NULL
        at MSG.lParam,                  dd    NULL
        at MSG.time,                    dd    NULL
        at MSG.pt,                      dd    NULL
    iend
Posted on 2008-03-31 19:28:23 by Synfire
Hmm, I like the c style loops and such, but that type stuff is a bit uglier than wc.hInstance.
Posted on 2008-03-31 23:22:05 by Bobbias
%imacro ASSUME 2
%ifidni %2, NOTHING
  %undef %{1}.
%else
  %define %{1}.(_x_) %{1} + %{2}. %+ _x_
%endif
%endmacro


Then use:

ASSUME wc, WNDCLASSEX

mov wc.(hInstance), eax
mov wc.(lpszClassName), ebx
mov wc.(lpfnWndProc), ecx
mov wc.(hIcon), edx
mov wc.(hIconSm), edx
invoke RegisterClassExA, dword wc
StdWindow szClass, szTitle, 100, 120, 212, 232, NULL, wc.(hInstance)

ASSUME wc, NOTHING
Posted on 2008-04-01 10:44:32 by Synfire
Time for an update:

I've worked things out for the most part. I've got console input and output working, and I've come up with some ideas on game internals.

I'm thinking of using a Linked List, or some other system to hold the data for my "rooms", since I plan on using text files (possibly compressed, if I'm feeling really adventurous) to describe my world (I could hard-code everything, but I really don't like that idea.)

I'm not really sure what structure would best suit my needs here, and I can't seem to find anything that actually discusses making linked lists in assembly. Could anyone give me some pointers here?
Posted on 2008-04-08 22:13:51 by Bobbias
Linked-lists are so easy, that no discussion is necessary.
entry struct
  pNext dd ?
  ... the data here
entry ends

Do yourself a favor and make a "room-editor" as soon as you've decided on the data a room will have. I had insisted obstinately to not make editors in the beginning for my games, but right from my first commercial game it became evident that I need level-editors. (and every game after that proved it further). Takes just a day to make, saves weeks.
Though, man... linked-lists...
Posted on 2008-04-08 22:50:19 by Ultrano
Lol, well, I've never actually implemented linked lists before.

Making a level editor would also give me a chance to work on a GUI App (since this is all text based right now) as well as let me experiment with loading and saving in different formats, before I start tossing the code into my game.
Posted on 2008-04-09 13:05:52 by Bobbias
Sorry for the double post, but I figured this thread wouldn't get any attention if I just edited my last post.

I've hit a bit of a problem. I'm implementing a CLS function in my little game app, and no matter what I try, I keep getting this error on an invoke:

console.asm(188) : error A2114: INVOKE argument type mismatch : argument : 4

This error is saying there's a type mismatch with the COORD structure.

The line in questions is:

invoke FillConsoleOutputCharacter,hStdOut,' ',nConsoleSize,cHome,offset nCharsWritten

Windows defines a COORD structure as:
(pseudocode for being lazy)

COORD
short x
short y
END

But the masm32 windows.inc defines a COORD as as 2 DWORDs. I tried making my own struct and using that instead, and nothing worked. I've tried defining them as BYTEs, WORDs, and DWORDs, and still get the error. Any idea what the heck is wrong?
Posted on 2008-04-12 03:06:58 by Bobbias
Try passing its address, not it-itself as a value. I'm not sure if that's the problem because i'm not very familiar with masm syntax. To me it looks like you're trying to pass the structure 'by value' instead of 'by pointer'. You should add something like "addr" or "offset" to tell the compiler that it should push the pointer, not the structure.

If it was a problem with the members' sizes then it would compile and (once running) produce incorrect resutls.


(PS: I'm sleepy now, so I'm most likely completely wrong ^^' )
Posted on 2008-04-13 18:00:51 by ti_mo_n

Sorry for the double post, but I figured this thread wouldn't get any attention if I just edited my last post.

I've hit a bit of a problem. I'm implementing a CLS function in my little game app, and no matter what I try, I keep getting this error on an invoke:

console.asm(188) : error A2114: INVOKE argument type mismatch : argument : 4

This error is saying there's a type mismatch with the COORD structure.

The line in questions is:

invoke FillConsoleOutputCharacter,hStdOut,' ',nConsoleSize,cHome,offset nCharsWritten

Windows defines a COORD structure as:
(pseudocode for being lazy)

COORD
short x
short y
END

But the masm32 windows.inc defines a COORD as as 2 DWORDs. I tried making my own struct and using that instead, and nothing worked. I've tried defining them as BYTEs, WORDs, and DWORDs, and still get the error. Any idea what the heck is wrong?


The COORD structure should take up a DWORD's space, so define your own as two WORDs. I've noticed that the second argument to FillConsoleOutputCharacter is defined as a :DWORD, are you sure that an inline single quote will work in this instance with masm? Try changing that line to:

__COORD STRUCT
x WORD ?
y WORD ?
__COORD ENDS
...
mov ecx, 00000020h
invoke FillConsoleOutputCharacter, hStdOut, ecx, nConsoleSize, cHome, Offset nCharsWritten

I haven't tested any of that because I don't even have a copy of MASM installed anymore. But you can give it a shot.
Posted on 2008-04-13 23:24:19 by Synfire
Welcome back Bobbias
"been out of the loop..." 2 years!!!
talk about really nasty branch misprediction penalty :D
Posted on 2008-04-14 01:46:10 by daydreamer