Hi, I already had some experience with assembly programming for motorola68k,mips and intel 8086, everything went well because I had every simulator/tool I needed + readable guides.
Now I'm trying to learn x86 but
1)I can't find any simulator (I want to execute my code step by step, view registers/memory,things like that...with a gui would be the best)
2)I can't assemble!I tried masm but...every guide I find starts in a different way! One tells me to write a c program, another starts with a segment directive, another writes directly .data and .code, another one switches directly to code...
So, out of desperation, I beg for your help!
Can you give me tools and write here a small tutorial in order to build a simple "hello world" program?
A great place to start is: Hutch's Home Page (http://www.movsd.com/)
And, as for beginner's tutorials,...most of us started with: Iczelion's Example Code (http://www.movsd.com/icz.htm)
Have fun here,...It's really a great forum.
Thanks but...it's not different from what I already found on the net...iczelion just gives some code away, I'd like to have a "how to build and run your x86 assembly code" guide, I already know something about architecture, registers, op codes, ecc. it's just I can't get a program run!
For example I tried to make this code but it does not work:
.386 ;I added this looking at iczelion but it does assemble even without it
.model small
.stack 1024
.data
MyMessage db "Hello x86!$"
.code
start:
lea bx,MyMessage
mov dx,offset MyMessage
mov ah,9
int 21h ;prints the string MyMessage on the console
return
end start
I did this in order to compile:
Quote1. masm hello.asm
2. link hello.obj
Then I open my command line, write "hello.exe" and...no writing at all! Why?I'm sure the system call is correct...
My tips & tricks page (http://www.webalice.it/jj2006/Masm32_Tips_Tricks_and_Traps.htm) has a Hello World example and step by step instructions. Iczelion's tutorial should come once you get bored of Hello World.
Welcome to the Forum :thumbu
Thanks to you too, for help and welcome, but I'd like to not use any macro like in your example (masm32rt.inc is a macro file right?) ... don't you have a simple print on console (with system call) example?Or maybe try my program and suggest me what's wrong with it?
I think my level of assembler will stay confined on command line, I don't plan going so far like making a gui for my programs.
Your program uses int21h ... it is an old DOS kind of 16 bits program...
Try to forget about this kind of obsolete ASM examples and immerse your self into 32 bits windows programming (can be console and not gui if you so like).
Bogdan is right, forget 16-bit code. Here is a 32-bit Hello World example, for testing if your installation works:
include \masm32\include\masm32rt.inc
.code
AppName db "Masm32:", 0
start: MsgBox 0, "Hello World", addr AppName, MB_OK
exit
end start
As to macros: I understand that you want the "pure" code, but nothing is pure nowadays. Even if you replace print "hello world" with the full invoke StdOut etc stuff, you are using a third party code. In this context, \masm32\macros\macros.asm is a fascinating lecture :bg
Hi,
The masm32rt.inc is an include file that gived you access
to a run-time library (or DLL). You can look at 16-bit programs
in DEBUG.EXE. That will let you see the register contents.
Your program is not exiting correctly. An *.EXE program should
use function 4C to exit to DOS. You should use an input character
function to pause the program so you can see the message if
Windows is closing your program too quickly.
I don't use the .MODEL directive, so this may be extra but
won't hurt. You did not initialize the data segment.
; Put these two lines as the first lines in your program
MOV AX,SEG DGROUP
MOV DS,AX
HTH,
Steve N.
P.S.
Just saw Bogdan and JJ respond. This forum is intended
mostly for 32-bit Windows code using the MASM32 package.
SRN
he obviously does not have masm32 installed
he used "link" to create an MZ EXE :bg
step 1) install the masm32 package
the link is in the upper right corner of the forum
Quote from: dedndave on July 28, 2011, 05:23:55 PM
he obviously does not have masm32 installed
Again, see my signature for step by step instructions. By the way, your "emulator" is called Olly - see http://www.ollydbg.de/version2.html
Hello falcon01, welcome. Well, I'm putting here your question, but follow other peoples sugestions, don't have fear, programming to windows is more easy than to ms-dos. If you like to talk about ms-dos, this forum have a special section to this, look in front page.
Quotegrupo group seg_cod,seg_dados
assume cs:grupo,ds:grupo
seg_cod segment public
org 100h
imp_string proc far
mov ah,9
mov dx,offset grupo:string
int 21h
int 20h
imp_string endp
seg_cod ends
seg_dados segment public
string db "Hello x86!$"
seg_dados ends
end imp_string
Quote
masm hello.asm
link hello.obj
exe2bin hello.exe hello.com
Oh, I forgot to say, you can use "emu 8086" too, search by it on net.
Ok I installed masm32 and it gives me this error:
Quotemov dx,offset Mystring <--error A2022: instruction operands must be the same size
maybe it's for this reason my program does not work!What's its meaning?
2 mineiro:
your code works fine, could you help me to understand it?It's pretty much the same as mine except for the fact you use segments and no directives as .model,.data e .code...what's the difference?
Moreover I like 8086emu much (I used it for 8086 assembly indeed), but I need x86 programming...too bad I'll have to use ollydb:(
2 fortrans:
even with the exit function (thanks for the hint anyway!) it still does not work!
2 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 boxer or any sign of gui...
Offests are 32-bit values, so, use the full register (EDX) instead of the 16-bit portion.
mov edx, offset Mystring
This MASM forum thread: INVOKE and ADDR Directives (http://www.masm32.com/board/index.php?topic=16388.0) is an interesting discussion of the actual functions of the ADDR and OFFSET directives.
The reason the guys are showing you code that uses the MessageBox function is that it's a standard Windows API function. It's there primarily to demonstrate the INVOKE syntax, which is a very common and useful technique in MASM programming. Of course, you can accomplish essentially the same thing without using the MessageBox finction.
You can use the search function for the MASM forum, and, you will discover all kinds of great threads about subjects that you have not yet asked, but, other novice assembly programmers have. Here's what I do: I click on the Advanced Search link, and enter "dedndave" into the, "By User" text box,...then deselect all forums, and, re-select just the Campus, Workshop, and, Laboratory sub-forums. Supply keywords for the "Search For" text box (subject you are interested in), or, an asterisk (*) to select all. Dave posts all kinds of useful demo code. It's clear, it works, and, he explains everything in great detail. I'd still be a really crappy programmer, if it wasn't for Dave.
Here's a short example program that I stole from Dave:
INCLUDE \masm32\include\masm32rt.inc
.DATA
Hello db 'Hello World!'
.DATA?
ByteCnt dd ?
.CODE
_main PROC
INVOKE GetStdHandle,STD_OUTPUT_HANDLE
INVOKE WriteFile,eax,offset Hello,sizeof Hello,offset ByteCnt,NULL
INVOKE ExitProcess,0
_main ENDP
END _main
Thanks much the error is fixed but...program still doesn't work!
And I discovered another thing: mineiro program does work as long I execute the .com file, the .exe crashes!
Ah by the way I'm assembling mineiro's program with MASM5.0, if I try assembling it with MASM32 it gives some errors...I'm still far away from the solutionT_T
I'll try to see invoke functions, though I love explicit interrupts more...
the EXE crashes because the DS segment register is not set
for COM programs, CS, DS, ES, SS all point to the same segment
now, if your having trouble with the 32-bit example, it may be because you are not using the correct command line switches for ML and/or LINK
ml /c /Fl /coff MyProg.asm
link /SUBSYSTEM:CONSOLE /OPT:NOREF MyProg.obj
be sure you are using the link that is in masm32\bin for 32-bit programs
the one that came with masm 5.0 is for 16-bit programs
you may have to check the PATH environment variable, too
the /Fl switch is not necessary, but it may be used to generate a listing
QuoteI'll try to see invoke functions, though I love explicit interrupts more
as far as i know, you can't make a GUI window with interrupts :P
at least, not easily - lol
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
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 (http://support.microsoft.com/kb/314106/EN-US)
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.
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
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
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
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
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
?
are you using the correct command line switches ?
\masm32\bin\ml /c /coff MyProg.asm
\masm32\bin\link /SUBSYSTEM:CONSOLE /OPT:NOREF MyProg.obj
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
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
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
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"?
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
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
Thanks a bunch, these char routines are just what I wanted!Only problem is that echo is disabled..but I'll combine it with a print char function (whose name is..?XD), no problem.
And if I make a 100byte buffer I discovered I can handle strings too because the stdout->stdin->stdout->stdin sequence works...maybe it was the 1 byte allocation error's doing.
Thanks to everybody now I feel I can at least START making some assembly programs in 32 bit!:D
Mind if I ask some last questions about x86 architecture and instructions in general?
1)What's the difference betweeen lea, offset and address?They do the same thing to me...
2)Is there a way to refer to upper 16 bits of extended registers?Like AX for lower 16 bits.
3)I heard that, respect 8086, they improved the MUL operation...now it should work like this: MUL AX,BX (AX=AX*BX),true?
4)Both addresses and data are 32-bit long and x86 is basically CISC right?So there are instruction which take more space than others.
Hi,
1) LEA is an opcode or instruction. It is executed by the
processor. OFFSET or address are assembler directives.
They are evaluated by the assembler, not the processor.
2) No, not directly. you can move the contents of a
32-bit register like EAX to access the upper 16 bits directly.
Look at the instructions BSWAP or the rotate instructions
ROL and ROR.
3) That might be the IMUL instruction you are thinking
about. IMUL got extended versions 8086 => 80386.
MUL BX does something like AX:DX = AX * BX.
4) Yes, insructions can range from one byte to around
15 bytes long. The shortest perform fixed operations.
longer instructions include immediate data and instruction
prefixes such as REP, LOCK, and segment overrides for
instance.
HTH,
Steve N.
as to the 1-byte buffer...
you should always allocate 1 byte more than needed :P
the StdIn routine needs a place for a terminator
if you tell it you have 1 byte, it is full when you start
besides the instructions Steve mentioned, i have had occassion to use another method to access the upper 16 bits
if i want to zero extend or sign extend the upper 16 bits of a register, without destroying the original contents.....
push eax
movzx edx,word ptr [esp+2]
pop eax
push eax
movsx edx,word ptr [esp+2]
pop eax
it may not be particularly fast, but neither is BSWAP :bg
these code sequences do not alter any flags - also handy
if you do this....
mov edx,eax
shr edx,16
the flags are altered, and the result is always zero extended
Thanks much ^^
i have wanted something like this for a while
so, i took a break from my other project and wrote this routine
you can filter numerics only, alpha only, no spaces, and combinations
i use crt__kbhit and crt__getch
in the spirit of fun, i use WriteFile in the routine instead of the print macro :P
i do use the macros in the test code, though.....
Console Input Test: sdfsdfSDFDF,.... 234242
Length EAX: 25
Buffer Size ECX: 255
Buffer [EDX]: sdfsdfSDFDF,.... 234242
Spaces Allowed:
No Filtering: sdfsdfsdSDFD..... 234
Numeric Only: 345345345 353534
Alpha Only: sfsdfsdf sdfsdfSDFS sdf
Alpha-Numeric Only: sdfsddSDFD34234 234234
Spaces Not Allowed:
No Spaces: sdfsdf3242423....
Numeric Only: 34234234
Alpha Only: sdfdfsdSDFSD
Alpha-Numeric Only: dfsdfsd234234SDFSDF3234
this one supports backspace
but it does not allow line editing like arrow keys or insert mode/overwrite
it does allow tab, but i will also make backtab work and add the line editing stuff later
Hi,
An addendum to Dave's code in reply #32.
MOV EDX,EAX ; Make working copy..
SAR EDX,16 ; Move high word to low word,
; sign extended, flags affected.
The PUSH/access/POP stuff was new to me at least, thanks.
Cheers,
Steve N.
ah yes - should have thought of that, Steve :U