Page 1 of 1

Printing a character with NASM

Posted: Tue May 03, 2011 8:36 pm
by gsingh2011
I'm using NASM with Cygwin. I thought that you could print characters using int 21h with NASM, but apparently that's only a DOS command? How do I do it in win32?

Re: Printing a character with NASM

Posted: Tue May 03, 2011 11:50 pm
by Love4Boobies
Open the file called CON and write to it. Here's a C example to illustrate the point:

Code: Select all

#include <stdio.h>

int main(void)
{
    FILE *f = fopen("CON", "w");
    fputs("hello, world!", f);
    fclose(f);
}

Re: Printing a character with NASM

Posted: Wed May 04, 2011 2:03 am
by Combuster
If you have to do it the portable way, just write to stdout and have the C runtime take care of the rest. But the OP did not ask for C code.

If you want native windows, use the console functions, which also gives you control over colours and whatnot. You only need three functions to get started, in order:
AllocConsole (if you didn't link for a console application and none is therefore created by default)
GetStdHandle
WriteConsole
which you can just import and call from assembly.

Re: Printing a character with NASM

Posted: Wed May 04, 2011 4:46 pm
by gsingh2011
Ok, I followed the example here and got it working: http://codewiki.wikispaces.com/winstdout.nasm

I shortened it to the following code:

Code: Select all

[list -]
%include 'win32n.inc'
[list +]

section .bss use32
section .data use32
section .code use32
cpu 386

extern  WriteFile
extern  GetStdHandle
extern ExitProcess
import WriteFile kernel32.dll
import GetStdHandle kernel32.dll
import ExitProcess kernel32.dll

section .code
..start:

	mov eax,1
	push eax
	mov eax,1
	pop ebx
	add eax, ebx

	push     STD_OUTPUT_HANDLE
	call    [GetStdHandle]          ;Get stdout
	mov     [stdout_handle], eax    ;Save the handle

	;Write a message to stdout
	push    dword 0                 ;error code
	push    dword 0                 ;octets_written
	push    dword textlen           ;in octets to write
	push    dword text1             ;in buffer
	push    dword [stdout_handle]   ;in handle
	call    [WriteFile]             ;Write message

exit:

        push    dword 0                    ;Point at error code
        call    [ExitProcess]
        jmp     exit                    ;Should never reach here

section .data
stdout_handle:  dd      0
text1:             db      53, 13, 10
textlen:        equ        $ - text1
and it works fine and outputs the number 5. But I did some calculations above, (1+1) and I want to output the result (don't worry about the roundabout way the numbers are added). I tried storing the result (eax) in another register (ebx) and then replacing push dword text1 with push dword ebx, but that didn't work.

EDIT: Nvmd, I got it. mov [text1], eax does the trick.

Re: Printing a character with NASM

Posted: Wed May 11, 2011 4:24 am
by Love4Boobies
Combuster wrote:If you have to do it the portable way, just write to stdout and have the C runtime take care of the rest.
That only works if you can guarantee that the C runtime actually prints to the console and not somewhere else.
Combuster wrote:But the OP did not ask for C code.
Indeed, so think of it as pseudocode. The point was writing to the CON file (and maybe use ANSI codes for colors, etc.). According to MSDN, both techniques should work and this one is apparently what the OP decided to go for. However, I'm not sure it's as flexible because NT added all sorts of functions to deal with security and so forth, but at least it works on 9x. :)

Re: Printing a character with NASM

Posted: Wed May 11, 2011 9:35 am
by Gigasoft
You do not need to call GetStdHandle. STD_INPUT_HANDLE, STD_OUTPUT_HANDLE and STD_ERROR_HANDLE can be used directly with the following functions.

ReadFile
WriteFile
CloseHandle
_lread
_lwrite
_lclose

Don't know of any others.

For text output, the functions from msvcrt.dll are often sufficient and easier to use. Don't reinvent something which is already there. The __getmainargs function, for example, is often overlooked and programmers invent their own way to read the command line.