Subject: Re: Doing graphics + hardware I/O + misc Date: Sat, 8 Mar 2003 23:04:40 -0000 From: "Beth" Reply-To: "Beth" Organization: ntl Cablemodem News Service Newsgroups: alt.lang.asm References: 1 CyberLegend wrote: > Hello group, Hi Individual, > I have progressed in my learning of ASM that I have come to the point > where I have another set of questions: > > (1) I'm currently doing textual drawing (#s of diffirent colours). I > understand it is easy enough to turn these procedures into graphical > (pixel-based) ones, just I do not know how to innitialize a graphics > mode. I suppose I have a VGA card and I would need nothing more than say > 800x600, 320x200 will do. How to I switch to a graphics screenmode? The best VGA can offer is either 320x200 in 256 colours (best colour depth) or 640x480x16 (best resolution)...if you want anything more impressive than that, then you'll need SVGA...which is where things get a lot more complicated because SVGA isn't standardised like VGA is (different cards work in different ways)...although, if you've got an SVGA card that supports VESA (very likely these days but some of the first older SVGA cards don't have the support) then you can use VESA's VBE to access SVGA modes... But for ordinary VGA modes, switching to them is incredibly simple...load AH with zero and AL with a "mode number" and then call INT 10h...if you download "Ralf Brown's Interrupt List" (http://www-2.cs.cmu.edu/afs/cs/user/ralf/pub/WWW/files.html) then you can find a table listed under INT 10h with the vital statistics of each of the video modes...Ralf's list is a big download but worth making because it's a comprehensive list of _all_ interrupts under DOS (plus one or two extras, like a list of hardware port I/O addresses :)...various functions under INT 10h are where the BIOS keeps the video routines (in much the same way that DOS keeps all its routines under INT 21h :)...you can browse the list and just experiment with the video functions as you like then...a very useful list indeed :)... Also under INT 10h (where AX=4Fxx in the list), you'll find the VESA SVGA extensions...these are a little more complicated to use but allow you to use SVGA modes in a "device-independent" way (if you were to program the hardware directly without these VBE routines, it would get complicated fast as all SVGA cards work in different ways)...if you download the VBE specification (Acrobat PDF file) from VESA (http://www.vesa.org/vbelink.html), then that has all the details about the VBE routines... The VGA modes, though, are pretty easy to use...if you switch to mode 13h (13h being the video mode number for the 320x200x256 mode :) then this is a really easy mode to learn...the video memory starts at segment A000h and is a just a series of bytes (1 byte per pixel...follows the same "reading order" as text modes do...that is, starting in the top left, going right across each "scanline", moving down the screen :)...each byte is simply which one of the 256 colours in the palette you want at that pixel...so, to plot a white pixel in the middle of the screen, you write 15 (which is white in the standard palette :) following this formula: Address = A000:0000 + ( y * 320 ) + x...taking x=159 and y=99 as the "middle" (there actually isn't a "middle" pixel because the numbers are even ;) then that means writing a 15 to A000:7C5F...voila! We have our white pixel in the middle of the screen... ----------- 8< ------------ mov ax, 0013h ; change to video mode 13h int 10h mov ax, 0A000h ; make ES point to the start of video memory mov es, ax mov bx, (Y * 320) + X ; use formula to get address mov es:[bx], Colour ; write pixel ----------- 8< ------------ You can change the colours in the palette to any 256 of the 16 million or so that's available by using port I/O with the VGA card (you might need to read the stuff later about port I/O first here :)...send a byte specifying what colour you want to change to port 3C8h then send three bytes to port 3C9h specifying the red then green then blue components of the colour...for example: ------------ 8< ----------- mov dx, 3C8h mov al, 15 ; Colour in palette (0-255) out dx, al mov dx, 3C9h mov al, 127 ; Amount of red (0-255) out dx, al mov al, 0 ; Amount of green (0-255) out dx, al mov al, 255 ; Amount of blue (0-255) out dx, al ------------ >8 ----------- Should change colour 15 to a nice violet colour...and that should be all you need to plot pretty pictures in mode 13h...for animation, it's also useful to know that bit 8 of I/O port 3DAh holds the "vertical blank" status (the vertical blank, if you don't know, is the period of time when the ray gun drawing the picture is moving from the bottom right back up to the top left...this is the perfect time to blast your graphics to video memory because it's not currently drawing the screen...at other times, you could get a so-called "tear" (as in rip, not as in crying ;) effect because you're changing the video memory as it's being drawn (so, for example, the ray gun only catches the bottom half of a rectangle you draw on the first pass because it was already half-way down the screen when you started drawing it :)...although, these effects only last for one refresh (it'll pick the rectangle up properly on its next pass :) so worrying about this is only really important for smooth, flicker-free animation as you won't really notice the effect with simple static graphics...also, waiting for the vertical blank is a simple way to synchronise your routines to the refresh rate of the screen (the "cheap and nasty" way to keep a game at roughly the same speed, whatever machine it's run on...as the refresh rate goes at the speed of the monitor and not the speed of the machine :)... If you'd prefer the 640x480x16 VGA mode then that's a little more complicated because you have to use "bitplanes" for that mode...it's a bit long-winded so I'll come back to that in another post, if you are at all interested...just ask and I'll attempt to explain...but "bitplanes" just aren't used any more for video, that it's only worth explaining it if you specifically want to know about them... > (2) I've orientated lots of my old Basic programs to use hardware ports > directly (speed) and now on ASM I suppose, since it is a low level > lanugage, the same could be done equaly easily (as with Basic's INP and > OUT). I would like to send a series of bits to hardware port 60h > (internal speaker), how do I do that? I would also like to read keyboard > scan codes from port 61h (or is it 63h?), how do I do that? There's two instructions - IN and OUT - which you use for direct port I/O...you use them in exactly the same way you used them with BASIC...with both instructions, there's two forms...a "general" form that uses DX to specify the port number and an "immediate" form where you can put the port number directly into the instruction...the "immediate" version, though, only uses a byte for the port number so it can only be used with the first 256 ports (but it uses less instructions and doesn't use up DX so it might be handy sometimes :)...the data to be sent OUT or to be read IN goes via the AL or AX or EAX register (port I/O address space works in much the same way as memory...it's byte-addressable but you can write to two or four contiguous ports using AX or EAX for 16 and 32 bit reads / writes)... The example above about changing the colour palette shows some code that writes to the VGA registers using port I/O...and - why not? - here's some code that instead uses IN to poll for the VGA's vertical blank (so it both demonstrates IN and demonstrates the vertical blank stuff at the same time :)... ---------- 8< ------------ mov dx, 3DAh Poll4NotVBlnk: in al, dx test al, 8 jnz Poll4NotVBlnk Poll4VBlnk: in al, dx test al, 8 jz Poll4VBlnk ---------- >8 ------------ Note that the above code does something important; It checks both for the vertical blank but, also, it checks for when we're not in the vertical blank...this is a good thing to do with modern machines as they can go so fast that it's easily possible to hit the vertical blank, write all your graphics and for it to _still_ be in the same vertical blank...so we check that the bit goes off as well as goes on to make sure we're doing our graphics in a different vertical blank for each frame...it's such a simple thing to forget that it's worth mentioning...or, otherwise, it's possible for an animation to appear "not quite right" as it writes more than one frame in the same vertical blank (effectively skipping over frames when there's not much to be drawn)... > (3) It was curious to find ASM makes .Com files which are just as .Com > as Command.com. Actually, COMMAND.COM is no longer a .COM file...well, obviously, it is in name because it ends with ".COM" - and, yes, earlier in its life it really was a true .COM file - but, these days, it's actually an ordinary DOS "MZ" executable...one assumes Microsoft kept the name as "COMMAND.COM" for compatibility or something...this works okay - despite the file having the wrong extension - because DOS actually pays no attention to the file extension in working out if something is a .COM or not...all DOS does is look for "MZ" as the first two bytes of the file (which is why I call ordinary DOS executables "MZ" after their file signature :)...if it's there, then it's a DOS "EXE" executable...if it's not there, DOS just assumes that it's a .COM file...the file extension is completely ignored by DOS's internal loader and you could have any extension you like there (although, the command shell, on the other hand, _does_ pay attention to file extensions, I think, so you could only really do this programmatically, calling DOS's "LOAD EXEC" interrupt from another program to load it in)... > A simple setting in Config.sys will allow me to use my > own command interpreter. What do I need to put in my ASM code to make > such a command interpreter? I am trying to create a boot floppy for a > diskless 80486 to make it a communications terminal for my null-modem > and I would like to avoid the requirement of having (or having to load) > a command.com on/from floppy. Not looked at the exact details or attempted anything like this myself...but if you disassembled a boot sector on a DOS disk then you could see what steps DOS does to load things up...with the modern Windows OSes, the files "MSDOS.SYS" and "IO.SYS" and such are now empty files and serve no purpose but "backwards compatibility"...which suggests that the modern COMMAND.COM contains _everything_ inside it...in which case, you'd have to replace the whole thing (all of DOS) with your own "COMMAND.COM"...with older versions of DOS, though, I'd guess it would be possible - if you could find out or work out how they interact - to just replace COMMAND.COM with your own interpreter but load MSDOS.SYS and IO.SYS yourself manually so that you don't need to replace all of DOS...but you can't do that anymore with newer versions as MSDOS.SYS and IO.SYS no longer seem to contain anything useful (they are literally empty "placeholder" files)... Someone who knows more about the exact internals of DOS might be able to shed some better light on this than me, though...I'm only guessing here... Beth :) Subject: Re: Doing graphics + hardware I/O + misc Date: Sun, 9 Mar 2003 01:44:56 +1000 From: "Ben Peddell" Organization: Telstra BigPond Internet Services (http://www.bigpond.com) Newsgroups: alt.lang.asm References: 1 CyberLegend aka Jure Sah wrote in message news:3E69D0F2.A6982B5D@guest.arnes.si... > Hello group, > > I have progressed in my learning of ASM that I have come to the point > where I have another set of questions: > > (1) I'm currently doing textual drawing (#s of diffirent colours). I > understand it is easy enough to turn these procedures into graphical > (pixel-based) ones, just I do not know how to innitialize a graphics > mode. I suppose I have a VGA card and I would need nothing more than say > 800x600, 320x200 will do. How to I switch to a graphics screenmode? > Use Interrupt 10h For example, to switch to SCREEN 13 (320x200x256): MOV AX, 0013h INT 10h As you might know, the frame buffer for such a mode is at segment A000. If you want a screen mode less than or equal to 640x400, then you'll need ModeX (which is using planar mode for a packed-pixel display mode). If you want a screen mode greater than that, you'll definitely need VESA. > (2) I've orientated lots of my old Basic programs to use hardware ports > directly (speed) and now on ASM I suppose, since it is a low level > lanugage, the same could be done equaly easily (as with Basic's INP and > OUT). I would like to send a series of bits to hardware port 60h > (internal speaker), how do I do that? I would also like to read keyboard > scan codes from port 61h (or is it 63h?), how do I do that? > OK. First, the speaker is switched on and off by setting or resetting bits 0 and 1 of port 61h. The keyboard scancode can be had by IN AL, 60h Any hardware port between 00h and FFh can be INP()'d by IN AL, portno and OUTed by OUT portno, AL There's also the possibility of Integer (word) and Long Integer (dword) INs and OUTs: IN AX, portno ; for word IN EAX, portno ; for dword OUT portno, AX ; for word OUT portno, EAX ; for dword If you want to IN or OUT a port above FFh, or you want to be able to determine the port number at runtime, then the port number is put into DX and you do one of the following: IN AL, DX ; for byte input IN AX, DX ; for word input IN EAX, DX ; for dword input OUT DX, AL ; for byte output OUT DX, AX ; for word output OUT DX, EAX ; for dword output There are also string (direct from port to memory) INs and OUTs. The port number is in DX, the source of OUTs is pointed to by DS:SI, and the destination of INs is pointed to by ES:DI: INSB ; for byte string input INSW ; for word string input INSD ; for dword string input OUTSB ; for byte string output OUTSW ; for word string output OUTSD ; for dword string output > (3) It was curious to find ASM makes .Com files which are just as .Com > as Command.com. A simple setting in Config.sys will allow me to use my > own command interpreter. What do I need to put in my ASM code to make > such a command interpreter? I am trying to create a boot floppy for a > diskless 80486 to make it a communications terminal for my null-modem > and I would like to avoid the requirement of having (or having to load) > a command.com on/from floppy. That's advanced assembly stuff, probably not for a beginner like yourself.