home *** CD-ROM | disk | FTP | other *** search
- 3/50: Assembly Langauge Programming
- Name: Lazerith #1
- Date: Mon Dec 12 20:33:46 1988
-
- Okay, gents, here's the deal. I'm going to begin a series of posts on the
- hows and whys of assembly langauge programming. Now, because I've got so many
- open projects right now I'll generally be slow to respond, so don't lose track
- of what I've already said, because I do not wish to repeat it too often.
-
- Here's what you have to have:
- Turbo Assembler 1.0 by Borland -OR- Microsoft version 5.10
- (I prefer Microsoft and will use it as my default langauge.)
- Enough free disk space (or floppy disks) to hold the assembler AND about
- two hundred thousand free bytes or MUCH MORE.
- 8087 will not be necessary for now, and I'll be starting with 8088/8086
- CPUs, so IBM users are the only one's likely to benefit.
- 80286 and 80386 are completely compatible and will be individually
- explored later.
- IBM CGA (or better) is preferred, because I know most of you will be more
- interested in graphics than anything else, HOWEVER, the first
- project will be strictly text.
- DOS 3.30 is preferred, although it will be a long time before the DOS
- version will make a difference.
-
- Here's the project:
- We will begin by collectively writting a program I will call DataComm (if
- anyone knows of a project already called this, then I need to hear about
- it soon!) It will be a modem program specifically designed for use with
- MBBS (Which is our future BBS written in both OS/2 and DOS). Eventually
- you'll all have completed copies about the same time the new BBS is ready.
-
- Ok, the next post and any following will be titled "DataComm - Lesson 1", etc.
- Please E-mail me if your interested and I'll keep it going. Otherwise, I'll
- can the whole idea. Thanks,
-
- Lazerith
-
-
- 4/50: DataComm - Lesson 1: "Basic Skeleton"
- ||||> Permanent Message
- Name: Lazerith #1
- Date: Mon Dec 12 20:56:38 1988
-
- The basic structure of all of my assembly language projects is the same. In
- assembly, one quickly learns to be consistant. To fail to do so is to insure
- Never Ending Project from Hell and Everlasting Work! (NEPHEW). Therefore this
- is the basic structure of ALL assembly language I'll show you:
-
- .Model Small <- The .Model directive specifies the default style of
- your code in Masm 5.10. A "SMALL" indicates that
- you expect your code to all reside within 1 block
- of 64k memory and that each of you code segments
- will themselves take up only 64k. (Information on
- segments will follow).
-
- .8086 <- Tells assembly to code ONLY for 8086 (Unnecessary)
-
- .data <- Tells assembler that an initialized data segment
- follows.
-
- txtCOPYR db "Copyright (C) 1988 - By the Möebius Group"
-
- Defines a location called "txtCOPYR" which will
- contain the string "Copyright...Group"
-
- .code <- Tells assembler that a code segment follows
-
- Main Proc Far <- Tells assembler that a procedure called "Main"
- follows which is in a "Far" segment (later).
- push ds <- Pushes the value of register DS on to stack
- (again, I'll explain these later).
- mov ax,0 <- Moves a zero into register AX.
- push ax <- Pushes a zero (in AX) onto stack.
-
- ; Program starts here
- nop <- Does nothing "No OPeration"
-
- ; Program ends here
- ret <- Return to previous routine (DOS)
-
- Main Endp <- Tells assembler that this is the end of "Main"
-
- .stack <- Tells assembler to make a stack and put it here
-
- End Main <- Tells assembler that this is the end of the file
- and that execution should begin with the routine
- called "Main"
-
- Now, enter the yellow words into the file exactly as is and run it. Don't ask
- questions, I'll explain everything in time. This should work as is.
-
- The commands are "MASM DataComm.asm;" followed by "LINK DataComm;" This
- should work, if not, let me know.
-
- Lazerith
-
-
-
- Read:(1-50,^4),? :
-
- 9/50: ASSEMBLY
- Name: White Knight #124
- Date: Wed Dec 21 10:31:05 1988
-
-
- I have a few questions. Some of them may sound dumb, but please bear
- through with me. They are:
-
- 1. How do I know if my CPU is 8088/8086 or Other?
-
- 2. What is Masm 5.10?
-
- 3. What is the difference between Move and Push?
-
- 4. Could I d/l MicroSoft 5.10 and Brief?
-
- I would appreciate any help. This is a great sub and I hope Lazerith
- continues in it.
-
- Later.
-
-
-
- Read:(1-50,^9),? :
-
- 10/50: Answers
- ||||> Permanent Message
- Name: Lazerith #1
- Date: Wed Dec 21 15:15:17 1988
-
- 1. How can I tell what CPU I have?
- Easiest way is to run Norton's SI.EXE (System Information) or similar
- program. As to 8086 vs 8088, I don't think there's any way to tell except
- to look at the serial number on the chip.
-
- 2. What is MASM 5.10?
- That's the name of Microsoft's Macro Assembler version 5.10, the latest and
- greatest assembler available (from Microsoft). This latest version adds a
- whole series of simplifications for quicker programming.
-
- 3. What is Move vs. Push?
- In assembler a MOV instruction (Move) copies a value from one place to
- another - usually between registers and memory. It's very general purpose
- and can be used to copy from anywhere to anywhere. PUSH on the other hand
- is a very SPECIALIZED type of move. It copies the value "onto the stack."
- The stack is a specialized area of memory used by the cpu to remember
- things that go on between your various subroutines and programs. For
- instance, when you call, say, a Print routine, the cpu must remember where
- you called from (in order to return there). Also the stack is often used
- to pass parameters. In our example, you could push the string to be
- written onto the stack, to be read by the next subroutine.
- The stack operates like (the classic example) a stack of plates at a
- cafeteria. That is, as you push plates onto the stack, each new plate is
- at the top. When you call to pull then off the stack, you receive them in
- the LAST PUSHED FIRST POPPED order (better known as LAST IN FIRST OUT or
- LIFO). The command in assembler to recover the last pushed is "POP".
-
- Lazerith
-
-
-
- 12/50: Help...
- Name: Dr. Poison #46
- Date: Fri Dec 23 17:59:19 1988
-
- I am writing a program using Turbo Pascal 4.0 and I am looking for a way to
- determine what character is located at a specific position on the screen.
-
- For example, I would like a way to figure out what character is at position
- 15,3; which should return some sort of ascii equivalent at fifteen units
- across and three units down (or something similar).
-
- Any help would be greatly apreciated.
-
- Dr. Poison
-
-
- 13/50: ...
- Name: Def Jim #54
- Date: Sat Dec 24 13:29:40 1988
-
- There's two basic ways to do it.
-
- You can directly check screen memory to get the value. This involves
- computing the address in screen memory where you want to check and then simply
- reading it. You can accomplish this through the mem[] array of Turbo Pascal
- (if it still exists past TP 3.0). The only drawback to this method is that
- the computation formula will change depending if you have a CGA, a MCA, a EGA,
- or what have you. These all arrange their screen memory differently.
-
- The second way gets around the problems with different screen types. You use
- a particular INT 10H function to get the contents of the screen. I don't have
- any books here at home for it, but I think you have to set the cursor position
- to the location you want (using INT 10H) and then read the contents at the
- cursor position (using INT 10H). This method is the 'portable' one working
- across all display types. I'm sure someone will post the details on this
- method.
-
-
- 14/50: READING the screen.
- Name: Lazerith #1
- Date: Sat Dec 24 14:18:05 1988
-
- In assembly langauge the ONLY efficient way to it is to use the Int 10h
- function to read the characters off the screen. This routine figures out
- which mode your in and on which card and reads it as appropriate. IT EVEN
- READS OFF OF GRAPHICS SCREENS.
-
- Now Pascal VERY probably has the same routine, but I don't have the chance to
- go check now. So in a little bit I'll either post an INLINE function (that
- is, using assembly INSIDE dos) or the appropriate pascal routine.
-
- -Lazerith
-
-
-
- Read:(1-50,^14),? :
-
- 15/50: Thanks,
- Name: Dr. Poison #46
- Date: Sat Dec 24 23:28:30 1988
-
- Please elaborate on INT 10h when you get a chance.
-
- Dr. Poison
-
-
-
- Read:(1-50,^15),? :
-
- 16/50: Reading the Screen using BIOS
- Name: Gryps Rex #2
- Date: Sun Dec 25 23:02:35 1988
-
- there are several BIOS functions that allow a programmer to read from the
- screen. They are:
-
- function 3: read cursor position
-
- AH = 3
- BH = video page number (0-7)
-
- function 8: read attribute/character at cursor position
-
- AH = 8
- BH = video page number (0-7)
- return:
- AL = character read
- AH = attribute of character (in alphga modes only)
-
- (IBM BIOS Tech Ref Apr87)
-
- -Gryps Rex
-
-
-
- 17/50: That
- Name: Megaton Man #61
- Date: Sun Dec 25 23:20:16 1988
-
-
-
- in Turbo Pascal 3.0 they have a procedure MsDOS (var);
-
- In turbo Pascal 4.0 it dont have it...
-
- I was wondering how to do Assembly INterrupt or Dos Calls in TP...
-
- Teach me how to do INLINE in tp...
-
- meg
-
-
- 18/50: DOS/BIOS Interrupts
- Name: Gryps Rex #2
- Date: Mon Dec 26 10:51:08 1988
-
- You CAN use the INTR() procedure in Turbo Pascal 4.0/5.0 and it has the
- following syntax:
-
- Intr( IntNo : byte; var Regs : Registers )
-
- example:
-
- { set the cursor position using BIOS }
- procedure locate(row, column : integer)
- var
- regs : registers;
- begin
- regs.ax = $200;
- regs.bx = 0;
- regs.dx = (row * 256) + column;
- Intr($10,regs)
- end; { locate }
-
- to access the Registers type, you must include the Dos unit in the uses
- statement at the top of your code (i.e. Uses Crt, Dos; )
-
-
- -Gryps Rex
-
-
-
- 19/50: DataComm - Lesson 2: "Out1"
- ||||> Permanent Message
- Name: Lazerith #1
- Date: Mon Dec 26 17:48:34 1988
-
- Ok, if you're not keeping up with this feedback!
-
- The most important (and usually first) routine is always the "Out1" routine
- which will output 1 character to the screen. Later on, we'll make this into a
- wonderfully complicated routine, but for now, it'll just be DOS.
-
- Immediately ahead of "Main Proc Far" insert:
-
- Out1 Proc Near <-Indicates a "Near" routine (Within 64k)
-
- push dx <-Store DX, because we're screwing with it.
- push ax <-Store AX, ditto
- mov dl,al ; dl=Character to Output (Passed in AL)
- mov ah,6 ; ah="DOS: Direct I/O"
- int 21h ; Call DOS service AH (6) Outputs to Screen
- pop ax <-Restores AX
- pop ax <-Restores DX (Note the reverse order)
- ret <-Return to caller
-
- Out1 Endp <-End of procedure
-
- Inside Main (after "mov ds,ax") add:
-
- mov al,"H" ; al="H"
- call Out1 ; Output "H"
- mov al,"e" ; al="e"
- call Out1 ; Output "e"
- mov al,"l" ; al="l"
- call Out1 ; Output "l"
- call Out1 ; Output "l"
- mov al,"o" ; al="o"
- call Out1 ; Output "o"
- mov al,0Dh ; al=Carriage Return
- call Out1 ; Output CR
- mov al,0Ah ; al=Linefeed
- call Out1 ; Output LF
-
- File it, Compile it, Run it.
-
- Lazerith
-
-
-
- 20/50: DataComm - OOPS!
- ||||> Permanent Message
- Name: Lazerith #1
- Date: Mon Dec 26 18:12:03 1988
-
- Uh, rather than inserting the second stuff after "mov ds,ax" (which isn't in
- the code anywhere ... heh); replace the line "nop" with the code...
-
- To keep things straight, the whole asm file is now in the TEXT dload section!
-
- -Lazerith
-
-
-
- 21/50: A Question bout 'C' and WWIV
- Name: Jolly Green Giant #5
- Date: Wed Dec 28 11:51:32 1988
-
-
- If someone istalls one of the mods called the FROM mod how can you make it
- so you change it in the UEDIT instead of just viewing it?
-
-
-
-
- Read:(1-50,^21),? :
-
- 22/50: ...
- Name: Def Jim #54
- Date: Wed Dec 28 23:22:41 1988
-
- I assume "we're" going to be moving past OUT1 and have a OUTSTR function
- posted, right?
-
-
-
- Read:(1-50,^22),? :
-
- 23/50: DataComm - Lesson 3: "Out$" (aka OutStr)
- ||||> Permanent Message
- Name: Lazerith #1
- Date: Thu Dec 29 03:39:03 1988
-
- As Def Jim predicted, calling Out1 with every letter in your messages is
- extremely inefficient, so we'll need a string handling routine. There are
- three popular methods of string handling: Asciiz, Highbit, and Count.
- Asciiz: Strings are terminated by a null (ascii 00h) like this:
- "This is an asciiz string",0
- This method is unquestionably the most flexible allowing 65535
- characters in a string and allow 255 (all except 00) as characters.
-
- Highbit: Strings are terminated by the last character having the highbit set
- like this:
- "This is a highbit strin","g"+128
- This method is common among programs with space restrictions because
- it saves one byte per string. Strings can be 65536 characters long
- like in asciiz, but are limited to characters 00-7F (0-127).
-
- Count: Strings are preceded by a count like this:
- 24,"This is a highbit string"
- This method allows for FAST string manipulation (like centering,
- windowing, etc. It also allows all 256 characters to be in the
- string. The major limitation, however, is that strings can only be
- as long as the count will allow (here we've used bytes which would
- limit our strings to 255 characters in length).
- Dos: Oh yeah, then there's the way DOS does it:
- "This is a dos string$"
- It is the same basic method as asciiz except that some moron
- somewhere decided to use a displayable character ("$") as a
- terminating character. It's just fine it you never have to use
- a dollar-sign... (Here that Lotus?)
-
- Naturally, we'll be using Asciiz. This is because, A) we don't have a space
- limitation, B) it allows us to display the range of characters 01-FE (FF is
- undisplayable thanks to a limitation of our Out1 routine handed down from DOS,
- but is not a problem because both 00 and FF display as spaces anyway), and C)
- it is not very complicated (or indeed very slow) to count the length of our
- strings using 8086 string functions.
-
- The following post will include the routine, if you're falling behind, tell me.
-
- -Lazerith
-
-
- 24/50: DataComm - Lesson 3: "Out$"
- ||||> Permanent Message
- Name: Lazerith #1
- Date: Thu Dec 29 04:07:59 1988
-
- Remove all the code insert previously between the ";code begins here" and
- ";code ends here" and replace it with:
-
- lea si,txtCOPYRIGHT ; ds:si>"Copyright..."
- call Out$
-
- And AFTER Out1 and BEFORE Main add this procedure:
-
- Out$ Proc Near
-
- push si
- push ax
- @@: lodsb ; al=character from string
- or al,al ; Is character end-of-line?
- jz @f ; If so, exit
- call Out1 ; Display character
- jmp short @b ; Loop thru string
- @@: pop ax
- pop si
- ret
-
- Out$ Endp
-
- Explanations of all the new commands will follow this post.
-
- -Lazerith
-
-
- 25/50: DataComm - Lesson 3: Out$ ----- Commentary
- ||||> Permanent Message
- Name: Lazerith #1
- Date: Thu Dec 29 04:15:08 1988
-
- A lot of new commands have popped up I need to explain:
-
- push Tells the CPU to push the word onto the stack to be popped off later.
- pop Recovers a previously pushed word into target register.
-
- @@: Under Masm 5.10, this is a local label to which the next two refer.
- jmp @b References the previous ("back") @@ label.
- jmp @f References the next ("forward") @@ label.
- (These instructions take up no symbol space by always using the same label.)
-
- lodsb A 8086 command the Loads from DS:SI into AL and increments SI.
- or al,al A neat trick. By "or'ing" a reg with itself, sets ZF if reg is zero.
- jmp SHORT label
- The short tells the processor that the jump is within 127 bytes.
-
- I can explain further any questions you have. Indeed, I'm being intentionally
- obscure so I know if any of this is helping!
-
- -Lazerith
-
-
-
- 26/50: @@:
- Name: Megaton Man #61
- Date: Fri Dec 30 15:57:00 1988
-
-
- @@: dont work with Turbo Assembler right? Cause I tried it.
- The rest.... well.... review to me... But keep going.... Very interesting!
-
- Oh, How can you change Colors in Assembly!
- wait wait!!!! GRYPS!!
-
- When you showed the INTR(xxx) for TP 4.0 adn 5.0 what about DOS FUNCTIONS!
-
- You only showed BIOS Interrupts!
-
- Meg
-
-
-
- Read:(1-50,^26),? :
-
- 27/50: DOS Interrupts ...
- Name: Gryps Rex #2
- Date: Fri Dec 30 16:08:14 1988
-
- Basically they follow the same approach with the exception that the interrupt
- number is 21 hex (33 dec). Use of the OFS() and SEG() functions are permitted
- when using registers. Example:
-
- var regs : registers;
-
- begin
- regs.ax = $1a00;
- regs.bx = ofs(data);
- regs.es = seg(data);
- intr($21,regs)
-
- and so forth...
-
-
- -Gryps Rex
-
-
-
- Read:(1-50,^27),? :
-
- 28/50: Also ...
- Name: Gryps Rex #2
- Date: Fri Dec 30 16:15:45 1988
-
- Just checking the manual, page 448, regarding the MsDos function. The
- interrupt number is not required in this case.
-
- var regs : registers;
-
- begin
- regs.ax := $1A00;
- regs.bx := ofs(data);
- regs.es := seg(data);
- msdos(regs);
- end;
-
- same as above.
-
-
- -Gryps Rex
-
-
-
- Read:(1-50,^28),? :
-
- 29/50: Procedure Locate
- Name: Dr. Poison #46
- Date: Fri Dec 30 20:32:35 1988
-
- The procedure Locate works fine, but for those of us who aren't very good at
- assembly, how would I find what character/atrribute is at that location?
- (Using Turbo Pascal 4.0).
-
- Dr. Poison
-
-
-
- 32/50: Turbo Tutor
- Name: Gryps Rex #2
- Date: Sat Dec 31 01:25:26 1988
-
- program readscreen;
-
- uses crt, dos;
-
- var
- screen_segment : word;
-
- function ReadCharAttrAtCursor : word;
- var
- regs : registers;
- begin
- regs.ax := $0800;
- regs.bx := $0000;
- intr($10,regs);
- ReadCharAttrAtCursor := regs.ax;
- end;
-
- function FasterRead : word;
- var
- regs : registers;
- begin
- regs.ax := $0300;
- regs.bx := $0000; { this is the video page, in lo byte }
- intr($10,regs); { read the current cursor position }
- FasterRead := mem[screen_segment:(lo(regs.dx)*2+hi(regs.dx)*160)];
- end;
-
- var
- regs : registers;
- begin
- intr($11,regs);
- if (regs.ax and $30) then screen_segment := $B000
- else screen_segment := $B800;
- .
- .
- writeln('Character/attribute at 10,10 is: ',FasterRead);
- .
- .
- end.
-
- or something like that, but the 'FasterRead' is faster.
-
- -Gryps Rex
-
-
-
- 34/50: ...
- Name: Def Jim #54
- Date: Sat Dec 31 16:48:37 1988
-
- Some routines and services from other operating systems store the strings
- delimted by C/Rs. The ASCIIZ method is the preferred method considering the
- fact that you probably want to write the routine to handle arguments from your
- HLL C program. ASCIIZ is the method used in C/Unix. The len+string method is
- used in BASIC and TP.
-
- I didn't read the code, but are you using BIOS functions for the I/O, or are
- you going straight to the port?
-
-
-
- Read:(1-50,^37),? :
-
-
-
- 44/50: VGA test
- Name: Gryps Rex #2
- Date: Mon Jan 09 23:59:13 1989
-
- from the C:\> prompt type the following:
-
- debug <CR>
- a
- mov ax,13
- int 10
- <CR>
- p=100
- p
-
- now, if nothing happens, then you don't have TRUE VGA.
-
-
- 46/50: Assembling MASM 5.10 code with TASM ...
- Name: Gryps Rex #2
- Date: Wed Jan 11 15:57:28 1989
-
- tasm /jMASM51 /jQUIRKS [options] filename
-
- this enables the Turbo Assembler to assemble the code that you use with
- Microsoft Macro Assembler 5.10
-
-
- -Gryps Rex
-
-
- 47/50: Um, a Question.
- Name: Io Lisp #113
- Date: Tue Jan 17 14:54:39 1989
-
-
- In Assembly, how do you display Graphics ? I.e., how would you put a
- single dot on the screen at location 1,1 ?
-
- ═╦═╔═╗ ╔ ═╦═╔═╔═╗
- ═╩═╚═╝ ╚═══╩═╝ ║═╝
-
-
-
- 48/50: Okay.
- Name: Lazerith #1
- Date: Wed Jan 18 11:08:30 1989
-
- To perform graphics, understand the screen first:
-
- In AlphaNumeric mode (That would be modes 0-3...) Data stored at B800:0000
- thru B800:1000 (approximately) is used to display characters (and no graphics)
- on the screen, like this:
-
- B800:0000
- 41 07 42 07 43 07 44 07 45 07
- ^ ^ ^ ^ ^
- "A" "B" "C" "D" "E"
-
- The "07" represents "White Characters on a Black Background".
-
- In a Graphics mode, data stored at B800:0000 now represents pixel information.
- In mode 6 (Black and White 640x200) the pixel information is like this:
-
- 47h = 01000111b = " . ..." pixels (white on black).
- 6Ch = 01101100b = " .. .. " p
- 98h = 10011000b = ". .. " p
-
- As you can see (I hope) every bit in the hex number equals a bit on the
- screen. To put it more simply: In either graphics or alphanumeric mode, the
- display interprets the data stored at B800:0000 to form either characters or
- graphics.
-
- In some modes the base paragraph is not B800, but A000 or B000 or something
- like that.
- In some modes every other pixel might be color information like:
- 00b = Black (or Background)
- 01b = Color 1
- 10b = Color 2
- 11b = White (or Color 3)
- Etc...
-
- More?
- -Lazerith
-
-
-
-
- 49/50: I'm hoping this isn't very long,
- Name: Io Lisp #113
- Date: Wed Jan 18 16:42:59 1989
-
-
- But how do you change screen modes then?
-
- The Beginner, IoLisp
-
-
-
-
- Read:(1-50,^49),? :
-
- 50/50: Video Modes
- Name: Lazerith #1
- Date: Wed Jan 18 18:57:35 1989
-
- Video Modes are numbered by IBM and can be engaged by BIOS. They are:
-
- 0 - Alpha/Numeric 40x25 Black & White
- 1 - Alpha/Numeric 40x25 Color
- 2 - Alpha/Numeric 80x25 Black & White
- 3 - Alpha/Numeric 80x25 Color
- 4 - Graphics 320x200 4-Color
- 5 - Graphics 320x200 4-Black & White
- 6 - Graphics 640x200 2-Black & White
- 7 - Monochrome Alpha/Numeric 80x25
- 13 - Graphics 320x200 16-Color
- 14 - Graphics 640x200 16-Color
- 15 - Graphics 640x350 2-Black & White
- 16 - Graphics 640x350 16-Color
- 17 - Graphics 640x480 2-Color
- 18 - Graphics 640x480 16-Color
- 19 - Graphics 320x200 256-Color
-
- The number of modes available to you is directly dependant on which video card
- you have. For instance CGA only allows you to use modes 0 thru 6.
-
- To engage the mode use BIOS call 10h (<- That's 16 in decimal...) like this:
-
- mov al,VideoMode ; al=Video Mode number
- xor ah,ah ; ah=BIOS Service 00
- int 10h ; Call BIOS to set mode.
-
- It's that easy.
-
- -Lazerith
-
-
-
-