News:

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

x86 Assembler on windows...how to start?

Started by falcon01, July 28, 2011, 03:32:03 PM

Previous topic - Next topic

mineiro

I have commented the code based in your questions.

grupo group seg_cod,seg_dados ;here I'm telling masm to join 2 segments, the code segment(cs) and data segment(ds)
assume cs:grupo,ds:grupo ;telling to masm to treat cs and ds like a joined group segment, the name is grupo, but you can put here any other name

seg_cod segment public ;public tell to masm that this segment can be seen by other procedures
                                 ;this is the same as ".code"
org 100h                     ;I'm going to build a .com(exe2bin) file and not .exe, this is the same as .model small

imp_string proc far
mov ah,9
mov dx,offset grupo:string
int 21h
int 20h                       ;.com files end(return to O.S) with int 20, if this one is a .exe, you need end it in another way, continue reading.
imp_string endp

seg_cod ends             ;here is where my code segment ends.

seg_dados segment public    ;my data segment, the same as .data
string db "Hello x86!$"
seg_dados ends                  ;data segment ends here

end imp_string                  ;the entry point of this program.

Some questions are in the air, I know, like "why I have joined 2 segments?", follow link below:
http://www.masm32.com/board/index.php?topic=17059.0
Sr dedndave posted in the link below a hello world, in ms-dos(.exe format) or win32:
http://www.masm32.com/board/index.php?topic=17128.0

baltoro

The problem is that in Windows XP and later Operating Systems, many of the original MS DOS interrupts are NOT supported.
Troubleshooting MS-DOS-based programs in Windows XP
Baltoro

mineiro

To not confuse you, I have rewriten that example. This one is to generate .exe files. Save it as hello.asm

code_segment segment public
imp_string proc far
mov ax,data_segment
mov ds,ax
mov ah,9
mov dx,offset string
int 21h
mov ah,4ch    ;end of our program, lets give control back to O.S.
int 21h
imp_string endp

code_segment ends

data_segment segment public
string db 'hello world!$'
data_segment ends

stack_segment segment stack
db 10 dup ('stack   ')
stack_segment ends

end imp_string

masm hello.asm
link hello.obj

Assembled with masm v5.0, link v3.60.

jj2007

Quote from: mineiro on July 28, 2011, 10:50:34 PM
To not confuse you, ...
...
masm hello.asm
link hello.obj

Hi Mineiro,

You are confusing him. He needs 32-bit console apps, not 16-bit code; besides, in a standard Masm32 installation link launches the 32-bit linker, which will fail on your code.

Here is hello world in 32-bit console mode, no macros and no invoke. Don't forget your linker needs /Subsystem:CONSOLE

include \masm32\include\masm32rt.inc

.code
txHW db "Hello World", 0

start: push offset txHW
call StdOut
call ret_key
push 0
call ExitProcess

end start

falcon01

Thanks everybody for helping!
Mineiro code works fine as long as I compile/link it with masm 5.0, anyway what's the problem with 16 bit code?Maybe it's because I can't use extended registers?You just say "it's obsolete" in your site but I'd like to know some reason...

jj2007 your code runs but I can't see the "hello world" string...maybe it's because it closes too fast? And what's the meaning of ret_key subroutine?
Moreover I can't see .data segment...it's ok to put everything in .code?
Anyway where can I find a list of 32 bit system call?For now I woud just need these:

1)Print a string on console (StdOut after putting string address on top of the stack right?)
2)Get a char or string or integer from console (I'm not so sure I can use 8086 interrupts now...)

so if you can simply write them here would be great

Quote from: dedndave on July 28, 2011, 09:13:44 PM
as far as i know, you can't make a GUI window with interrupts   :P
at least, not easily - lol
What part of
Quote from: falcon012 everyone:
I don't really mind programming in windows or MS DOS, as long I can make command line programs...the thing is I don't want message boxes or any sign of gui...
Is not clear to you?XD

dedndave

for some of these programs....
try opening the console window and typing the program name at the prompt
that way, the console doesn't close immediately
if you click on the program in explorer, it may run and close before you see it

jj2007

Quote from: falcon01 on July 29, 2011, 12:31:19 PM
jj2007 your code runs but I can't see the "hello world" string...
> maybe it's because it closes too fast?
Try from a DOS prompt. But I have a suspicion that you ignored the remark about Subsystem console above.

> And what's the meaning of ret_key subroutine?
To wait for a keypress.

> Moreover I can't see .data segment...it's ok to put everything in .code?
Read-only stuff, yes.

> Anyway where can I find a list of 32 bit system call?For now I woud just need these:
\masm32\macros\macros.asm is a very good source of inspiration.

> 1)Print a string on console (StdOut after putting string address on top of the stack right?)
Yes, exactly.

> 2)Get a char or string or integer from console (I'm not so sure I can use 8086 interrupts now...)
invoke StdIn, lpszBuffer, bufferLen

falcon01

Ok solved, my fault! I actually forgot console linking lol!

So, an example of reading a single char from keyboard would be

push  eax ;char will be in eax
push  1    ;just a char
call StdIn

?

dedndave

are you using the correct command line switches ?
\masm32\bin\ml /c /coff MyProg.asm
\masm32\bin\link /SUBSYSTEM:CONSOLE /OPT:NOREF MyProg.obj

FORTRANS

Hi,

   Modifying your original program with my suggested changes.
And such...

Steve


.model small
.stack 1024

.data
MyMessage      db "Hello x86!",13,10," Press a key to exit. $"

.code
start:
; Put these two lines as the first lines in your program
        MOV     AX,SEG DGROUP ; Can use @DATA as well.
        MOV     DS,AX

lea bx,MyMessage ; unused
mov dx,offset MyMessage
mov ah,9
int 21h            ;prints the string MyMessage on the console
;;return ; Not a valid opcode.

        MOV     AH,1    ; Console input character.
        INT     21H

        MOV     AH,04CH ; Exit to DOS.
        INT     21H
end start

jj2007

Quote from: falcon01 on July 29, 2011, 12:45:33 PM
Ok solved, my fault! I actually forgot console linking lol!

So, an example of reading a single char from keyboard would be

push  eax ;char will be in eax
push  1    ;just a char
call StdIn

?

Not the best design. Eax should point to a buffer, and the user should not enter more than one char, otherwise bang...
Try this:
include \masm32\include\masm32rt.inc

.data?
zebuffer db 100 dup(?) ; create a buffer here

.code
zeprompt db "Type something and hit Return: ", 13, 10, 0
zeresultis db 13, 10, 10, "The result is: ", 0

start: invoke StdOut, offset zeprompt
invoke StdIn, offset zebuffer, 100
invoke StdOut, offset zeresultis
invoke StdOut, offset zebuffer
call ret_key
exit

end start

falcon01

So I can't put user's digit in a register before actually storing it in memory?
That's not very effective...say I have to do a check on the character, I have to do 2 accesses in memory, one for storing and one for retrieving again...8086 "wait for keystroke" int which puts the char in AL register was way better in this case :(

Anyway, in order to have some pratice I did this small piece of code (before reading your last post), could you tell me what you think about? It does pretty much the same thing: requests an input to user and displays it.


include \masm32\include\masm32rt.inc

.data
firstStr db "Enter a number (1-3 digit):", 0
secStr   db "You entered: ",0
buff     db 0

.code

start:
            push offset firstStr
            call StdOut
            invoke StdIn,ADDR buff,3 ;if user enters more than 3 char I discovered they are ignored
            lea  ebx,buff            ;loading buff address in ebx (in x86 addresses are 32 bit long, right?)
            xor  al,al               ;putting 0 in al
            mov  [ebx+3],al          ;putting \0 at the end of char array
           
            push offset secStr
            call StdOut              ;displaying the second string
           
            push ebx
            call StdOut              ;displaying the number
           
push 0                   ;exiting
call ExitProcess

end start

falcon01

Oh and another thing...how come if I call subsequently stdout->stdin->stdout->stdin
the latter stdin is skipped? I think it's because keyboard still contains \n char...is there a way to "flush"?

jj2007

You are on the right track, but try this:

buff     db 0
Ouch db "That was a valuable text", 0
...
           push offset Ouch
           call StdOut              ; display your 'valuable text' ;-)
           push 0                   ;exiting
           call ExitProcess

dedndave

the StdIn "value" is stored in memory because it is a string - not a single character
it can be any practical length so, once converted to a binary value, it could easily be too large for a register

all versions of windows include a library of functions called the "MS Visual C Runtime Library"
the file is named msvcrt.dll
in the msvcrt, there are a number of functions that handle single-character keyboard input for the console
while it can be done with windows API functions, the msvcrt is much easier to work with
i have written a few keyboard routines using the API, and they never seem to behave as nicely as the msvcrt functions
this is due, in part, because the console has bugs that are difficult to overcome

2 of the functions that you may be interested in behave like the old INT 16h stuff
crt__kbhit lets you know if there is a character in the keyboard buffer
crt__getch gets a single character from the keyboard buffer
have a look at the masm32\m32lib\wait_key.asm file
you will see how crt__kbhit and crt__getch may be used
using those 2 functions, you can write a single-character entry routine
that way, you could do something like filtering out non-numeric keys, etc