Hello. I'm a 'fairly' experienced hobbyist C/++/# coder looking to expand my knowledge a bit more. I saw some pretty cool tiny little COM-based demos yesterday and was inspired to play around a little with 8086 assembly. After a bit of research, I chose MASM as my assembler.
tl;dr: I'm using MASM 6.11 on Dosbox and experimenting with Tiny Memory Model.
I'm having an issue using .data with tiny model. I know it should be possible because if I play around with exact memory addresses I can get the right address. However, because it (apparently) is being stored after the code, I can't really rely on that (not to mention it's hackish and unreliable.)
.model tiny
.data
msg db "Hello, World!$",0
.code
start:
org 100h
mov ah, 09h
lea dx, msg
int 21h
ret
end start
I feel like there's plenty of room for issues, but I wasn't able to figure it out on my own.
Thanks for reading.
for tiny model programs, all code and data must reside in a single segment, as well as the stack space
i.e., all code and data are in the code segment (which is also the PSP segment)
when the program is loaded, CS, DS, ES, and SS all have the same segment value
you can move things around to other segments after load, however
the SP register will normally contain 0FFFEh, so that the stack is at the end of the segment
i haven't played with .COM's much under the newer assemblers
but, give this a try...
.MODEL Tiny
.CODE
ORG 100h
_main PROC NEAR
mov dx,offset msg
mov ah,9
int 21h
mov ax,4C00h
int 21h
_main ENDP
msg db "Hello, World!",0Dh,0Ah,24h
END _main
also....
here is a little batch utility that will execute 16-bit code as a .COM program from the command line :bg
http://www.masm32.com/board/index.php?topic=13032.msg101106#msg101106
Thanks for the timely response. You're right, and I should've guessed there were no sections considering COM is just raw instructions.
This code works fine.
Placing the start label immediately above the org 100h puts the label at offset 0 in its segment, and the org 100h then causes the assembler to add 100h zero bytes between the start label and the first instruction. Since the loader loads the program into memory starting at offset 100h, at run time everything in the program is at a higher address than it should be, by 100h bytes. The program executes the zero bytes as a series of 80h ADD [BX+SI], AL instructions, harmlessly since BX and SI are both zeroed, before it executes the actual code. The solution is to place the start label immediately below the org 100h:
.code
org 100h
start:
at PSP:0000 is a terminate (INT 20h), so the program will exit immediately :P
the loader also pushes a 0 at SS:SP, so a RETN executes the same code
Quote from: dedndave on July 02, 2011, 11:48:08 AM
at PSP:0000 is a terminate (INT 20h), so the program will exit immediately
It would if the start address were at PSP:0000, but for a .COM file the start address is PSP:0100
i see what you are saying, Michael :P
what is worse - all the offsets (like the "msg" string) will be off by 100h
I'm glad to be hearing all of this, since it was a bit unclear in my head, and reading this stuff is solidifying some concepts, but are there any other resources you'd recommend for this? I'm in the process of reading manuals and playing with code right now. Pretty much anything would probably help at this point; this is my first real attempt to learn 8086 assembly language.
Since there's so little about DOS COM files, and so much more about bootloaders, would it be better to start out toying with bootloader tutorials? I know I'd lose the MS-DOS API if I did that, but that doesn't bother me. I don't know anything about DOS programming in the first place.
this is all obsolete stuff - lol
it really depends on what you wish to learn/accomplish
there is no 32-bit equivalent of .COM programs
if you just want to write programs, learn 32-bit windows
if you want to write bootloaders, 16-bit code is necessary, only enough to load code and get to protected mode
Ralf Brown's Interrupt List has a section that explains the PSP
that is about all the documentation there is about .COM programs
initially, MS had no intention of users writing .COM programs
it was intended as a mechanism for loading COMMAND.COM and some DOS external commands
Quote from: nmn on July 02, 2011, 01:18:36 PM
Since there's so little about DOS COM files, and so much more about bootloaders, would it be better to start out toying with bootloader tutorials? I know I'd lose the MS-DOS API if I did that, but that doesn't bother me. I don't know anything about DOS programming in the first place.
Hi,
That depends on what you want to accomplish. DOS has
a file system and BIOS does not. So if you want to save any
results from your program, it is a lot easier in a DOS environment.
It also has the DEBUG program. Which can show what is actually
happening, rather than what you think should be happening.
If you want a reference on DOS, I have used the following
books. "Microsoft MS-DOS Programmer's Reference Version 5",
ISBN 1-55615-329-5. Version 6 made some corrections.
"Advanced MS-DOS" by Ray Duncan, ISBN 0-914845-77-2.
(Maybe available on the Internet?) "Undocumented DOS
Second Edition" by Andrew Shulman and others, ISBN
0-201-63287-X.
If you want to learn assembly language, try a text book.
16-bit "Structured Assembler Language for IBM Microcomputers" by
Alton R. Kindred, Oxford University Press, 1991, ISBN: 0-19-517296-5.
And Art of Assembler (?) by Randy Hyde available at his site
both 16 and 32-bit versions, though in his own format assembly
language.
Regards,
Steve N.
P.S. As Dave says 16-bit is considered obsolete by most.
So tell us what you want to accomplish if what we are telling
you is wrongish.
SRN
Okay - I'll clarify my intentions.
Quote from: dedndave on July 02, 2011, 01:33:56 PM
this is all obsolete stuff - lol
Quote from: FORTRANS on July 02, 2011, 01:45:05 PM
P.S. As Dave says 16-bit is considered obsolete by most.
So tell us what you want to accomplish if what we are telling
you is wrongish.
That's a fair and good point. As I stated above, my main inspiration was the demoscene and its tiny COM demos, but also an interest in coding outside of a formal operating system. It's not that I'll do much with it other than play around, but.. I don't know, I suppose you'd understand as well as I do at this point. I'm sure you get this a lot, after all.
Quote from: dedndave on July 02, 2011, 01:33:56 PM
it really depends on what you wish to learn/accomplish
there is no 32-bit equivalent of .COM programs
Yes, and based on reading I can understand why there's no equivalent. Obviously PE-COFF is superior to COM, by design.
Quote from: dedndave on July 02, 2011, 01:33:56 PM
if you just want to write programs, learn 32-bit windows
if you want to write bootloaders, 16-bit code is necessary, only enough to load code and get to protected mode
I could learn assembly with 32-bit Windows first, or Linux/Mac OS X for that matter (though I guess that throws Masm out the window,) but I kind of decided to go cold turkey here and try to learn some new stuff.
Quote from: FORTRANS on July 02, 2011, 01:45:05 PM
That depends on what you want to accomplish. DOS has
a file system and BIOS does not. So if you want to save any
results from your program, it is a lot easier in a DOS environment.
It also has the DEBUG program. Which can show what is actually
happening, rather than what you think should be happening.
I'm not bothered by the lack of a filesystem, really. Something like FAT with no extensions doesn't sound too intimidating... It's more a matter of getting up-to-par with assembly coding first. It's (obviously) different from coding on programming languages. On that note, I'm sure once I'm in protected mode I can get some C code to run that doesn't use the standard libraries, but I'd rather avoid it if possible for now.
If I were to jump outside of DOS, is there an effective way to debug code? I'd probably start out in Qemu or another emulator (any recommendations? I don't remember seeing any debugging tools in any of the VMs I used...)
Quote from: FORTRANS on July 02, 2011, 01:45:05 PM
If you want a reference on DOS, I have used the following
books. "Microsoft MS-DOS Programmer's Reference Version 5",
ISBN 1-55615-329-5. Version 6 made some corrections.
"Advanced MS-DOS" by Ray Duncan, ISBN 0-914845-77-2.
(Maybe available on the Internet?) "Undocumented DOS
Second Edition" by Andrew Shulman and others, ISBN
0-201-63287-X.
If you want to learn assembly language, try a text book.
16-bit "Structured Assembler Language for IBM Microcomputers" by
Alton R. Kindred, Oxford University Press, 1991, ISBN: 0-19-517296-5.
And Art of Assembler (?) by Randy Hyde available at his site
both 16 and 32-bit versions, though in his own format assembly
language.
That might be helpful. When it comes down to it, I might just skip DOS altogether and start on the lowest level. It can't be much worse considering I have no assembly or DOS experience to begin with.
Thanks for your help.
well - we have all done the same thing :P
at least, Michael, Steve, and I have - lol
we are "old guys", and we learned a lot by playing with code, sometimes in DEBUG
back then, DOS on an 8088 was the machine of the day
what you learned by going through that process was applicable to then modern code
nowdays, that is a limiting approach
better to start out with a few console mode 32-bit trivials, and maybe Iczelions tutorial to make your first GUI app
Olly debugger is a good choice for 32-bit code, although there are a few others
http://www.ollydbg.de/
I do understand that this is not applicable to most code. That's not really discouraging.
Are you suggesting I'd be better off at starting with 32-bit assembly regardless of what else I want to play with? If that's the case, I'll just stick to that for now.
yah
the stuff you learn will be more usable on future projects
there is much to learn to write effective 16-bit code
it will be a lot of relatively wasted time
part of it is easy to explain
the stuff about segmented addressing is unnecessary
system services via BIOS and DOS interrupts - also a waste of time
part of it is not so easy to explain
when you learn 16-bit code, you actually develop "habits" that hurt you in the 32-bit world
and, you miss out on many instructions and instruction extensions that are available
there is a lot more to learn for 32-bit code
the windows API is daunting
the extended instruction sets (like SSE) - also daunting
the list goes on and on
but - at least the stuff you learn is sometihng you can use
Alright, I'm going to do as you say then. I'm fairly familiar with Win32 programming in C.
Since this thread is going off-topic, I assume I should keep it brief. Now that I'm switching to 32-bit assembly, though, are there any good docs I can grab for a quick reference? I'm downloading and installing the MASM distribution from this site now, so I'll find out what documentation it comes with. I can imagine where I'm going to fail at is writing good, optimized and safe code, so that's my primary concern.
edit:
Quote
the windows API is daunting
the extended instruction sets (like SSE) - also daunting
the list goes on and on
but - at least the stuff you learn is sometihng you can use
I'm sorry if I was being unclear earlier. I'm already familiar with low level programming as far as C goes, so the API is no problem at all.
if that's the case, then you are in pretty good shape
16-bit code may be viewed as a "fun little exercise" :P
there are a variety of sources to help you learn assembler
one i like is Randy Hyde's older version of AoA
http://www.arl.wustl.edu/~lockwood/class/cs306/books/artofasm/toc.html
it isn't completely up to date, but it provides a lot of the basics you will need
in the masm32 package, the examples, help, and tutorial folders have a lot of great info :U
Thanks. I think I'm off to a good start. With a bit of messing around, I got this to compile and run:
.386
.model flat, stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib
include \masm32\include\user32.inc
includelib \masm32\lib\user32.lib
.data
Message db "Success.$"
MsgTitle db "Hello MASM32!$"
.code
start:
push NULL
push offset Message
push offset MsgTitle
push MB_OK
call MessageBoxA
push 0
call ExitProcess
end start
I don't want to drag this thread on, but is this in the right direction?
looks good, except your parameters are reverse order :P
in assembler, we have INC files - similar to H files in C
one that will save you some typing is \masm32\include\masm32rt.inc
also - MASM supports an internal macro called INVOKE
it will push the parms for you and make the call
it also does a little type-checking to see if the parms are dwords, at least
and that you have the correct number of parms...
INCLUDE \masm32\include\masm32rt.inc
.DATA
Message db "Success.",0
MsgTitle db "Hello MASM32!",0
.CODE
_main PROC
INVOKE MessageBox,NULL,offset Message,offset MsgTitle,MB_OK
INVOKE ExitProcess,0
_main ENDP
END _main
MessageBox is an alias for MessageBoxA
most ASCII functions have such aliases to make the code a little easier on the eye
only if you require the unicode equivalent do you need to specify MessageBoxW
Oh, that's useful. I should be paying more attention, I already saw invoke before. I'll be messing with this today, thanks for all of your help.
oh - one more thing....
in win32, strings are often terminated with nulls rather than the old DOS '$'
Yeah, I did fix that, I just posted old code somehow.