One of the biggest hurdles I've faced while trying to learn assembly language programming (which I'm still doing) is how to output some simple variables to the console, so that I can see what happens when I'm trying things out. Just some humble variables - an unsigned integer, a signed integer, a floating point and a string. I searched but could only find examples that did literal strings, or examples that seemed like gibberish at my level - i.e. not much help. So after much sussing out I've finally managed to put together a simple little console program that does the trick, and I'm posting it here in case it comes in handy for anyone else trying to learn assembly language as I am:
;######################################################################################
; Output to console using printf and print CONSOLE BUILD conout.asm
;######################################################################################
; Make sure any floating point values are declared as real8
; Make sure any integer values are declared as either sdword or dword
; printf operates in the normal C manner and can take the following (useful) format specifiers:
; i signed integer
; u unsigned integer
; f floating point
; All the usual escape sequences can be used, for example \n
; print outputs any predefined nul-terminated string
; so assuming for example you have already defined
; mystring byte "hello",13,10,0
; then the syntax is
; print addr mystring
;--------------------------------------------------------------------------------------
.686
.model flat, stdcall
option casemap :none
; the following are the MINIMUM include and includelib files required for printf and
; print to function properly, but you may need to include others depending on what you
; wish to do if it is more than the small example shown below
include kernel32.inc
include macros.asm
include msvcrt.inc
include masm32.inc
includelib kernel32
includelib msvcrt
includelib masm32
.data
mysdword sdword -1234
mydword dword 5678
myreal8 real8 123.456789
mystring byte "Hello, World",13,10,0
.code
start:
printf("My sdword is %i\n",mysdword)
printf("My dword is %u\n",mydword)
printf("My real8 is %f\n",myreal8)
print addr mystring
printf("\n\n")
exit
end start
Hi hamper:
try:
include \masm32\include\masm32rt.inc
Which is this:
; \MASM32\INCLUDE\MASM32RT.inc Wednesday, March 18, 2009 4:21 AM
comment * «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
The MASM32 Runtime Library include file.
Differing from most compilers, MASM does not contain any built in
run time library so it is difficult for a programmer starting with
MASM to to get any code up and running without having to learn a lot
of extra information just to do basic things.
This file simplifies entry into assembler programming by making the
full capacity of the MASM32 library, macro system and include files
available to programmers undertaking this quest.
It specifies the normal conditions for building a 32 bit Windows
program with the minimum processor type, memory model and the need
for case sensitive capacity.
The include files are declared in the correct order so that the
windows.inc file is always first followed by static libraries and
import libraries for Windows API functions.
Where there is a corresponding library for either static or import
libraries, it is included after the include files.
NOTE : It is to the advantage of the programmer once they have their
basic code up and running to properly understand the architecture
of a MASM executable file so that they can construct their own
projects to more accurately reflect their own application design.
««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««« *
.486 ; create 32 bit code
.model flat, stdcall ; 32 bit memory model
option casemap :none ; case sensitive
; include files
; ~~~~~~~~~~~~~
include \masm32\include\windows.inc ; main windows include file
include \masm32\include\masm32.inc ; masm32 library include
; -------------------------
; Windows API include files
; -------------------------
include \masm32\include\gdi32.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\Comctl32.inc
include \masm32\include\comdlg32.inc
include \masm32\include\shell32.inc
include \masm32\include\oleaut32.inc
include \masm32\include\ole32.inc
include \masm32\include\msvcrt.inc
include \masm32\include\dialogs.inc ; macro file for dialogs
include \masm32\macros\macros.asm ; masm32 macro file
; libraries
; ~~~~~~~~~
includelib \masm32\lib\masm32.lib ; masm32 static library
; ------------------------------------------
; import libraries for Windows API functions
; ------------------------------------------
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\Comctl32.lib
includelib \masm32\lib\comdlg32.lib
includelib \masm32\lib\shell32.lib
includelib \masm32\lib\oleaut32.lib
includelib \masm32\lib\ole32.lib
includelib \masm32\lib\msvcrt.lib
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
And note the windows.inc
which should always be first.
Regards herge
Hi hamper:
mystring byte "hello",13,10,0
try:
mystring db "hello",13,10,0
.data
date_buf db 260 dup (0)
read_buf DB 128 DUP (0)
crlf DB 13,0
Sfile dd 0 ; Std Output(Console)
ByteSent dd 0 ; Byte Count
ByteRead dd 0 ; Byte Count
.code
invoke GetStdHandle, STD_OUTPUT_HANDLE
mov Sfile, eax
invoke WriteConsole, Sfile, addr date_buf, 128, addr ByteSent, 0
invoke WriteConsole, Sfile, addr crlf, 2, addr ByteSent, 0
invoke WriteConsole, Sfile, addr read_buf, 128, addr ByteSent, 0
invoke WriteConsole, Sfile, addr crlf, 2, addr ByteSent, 0
inkey "Hit any Key"; masm32\include\macros\macros.asm
invoke CloseHandle, Sfile
invoke ExitProcess, 0
You will have to put data in read_buf and date_buf
yourself but I think you will get the idea.
For windows APIs see if you can find this file:win32.hlp
It's a god send. Just google it and download it.
Regards herge
Quote from: herge on February 01, 2013, 04:54:25 PM
mystring byte "hello",13,10,0
try:
mystring db "hello",13,10,0
herge, the first definition is quite fine. You're only confusing a newbie with such proposals. Actually, hamper didn't even ask for help, on the contrary, he offered help for others.
hamper,
AFAIK the cfm$ macro, and its supporting macros, that the printf macro calls to process the format string, passes the format specification part of the string to the CRT function as is, so you can use the full range of types, flags, etc, for example:
.data
mysdword sdword -1234
mydword dword 5678
myqword qword 123456789123456789
myreal8 real8 123.456789
mystring byte "Hello, World",13,10,0
.code
start:
printf("My sdword is %i\n",mysdword)
printf("My dword is %u\n",mydword)
printf("My dword is %Xh\n",mydword)
printf("My qword is %I64d\n",myqword)
printf("My real8 is %f\n",myreal8)
printf("My real8 is %.15f\n",myreal8)
printf("My string is %s\n\n",addr mystring)
Hi hamper,
Welcome on board and compliments on your posted example. There are easier way to do many of these things but you have done well with your example.
Hi hamper,
welcome to the forum and have fun. :t
Gunther
Thanks all.
I realise that my example might not be the prettiest way of doing things, but at least it works and I can understand it (at least on the surface, what goes on behind the scenes to make it that simple on the surface I can't imagine). It's amazing how often I've used it so far, just trying things out to see what happens to bytes, words, doublewords and strings etc. when you play around with them -- all part of the learning process I guess.
Right, time for some structures of pointers to pass as parameters to procedures for pointers to structures...
Hi Hamper:
Welcome to the forum.
Regards herge
Hi hamper,
Welcome to the forum.