Class of November 9, 1996


Discussion of code handout.
The code in the handout does the upper right-hand corner of the 
display in a black line with a blue background. You will have to 
change the code so that the background is the same as the rest of
the screen (black).
-------------------- the handout (with extra comments) -------------------
title template.asm
.model small
.stack 100h
.data
x db 20
x1 db 20
y1 db 10
ul db 0dah ; upper left		 é
ur db 0bfh ; upper right	ù
ll db 0c0h ; lower left		 ë
lr db 0d9h ; lower right 	û
lhine db 0c4h ; horizontal line ¾
vl db 0b3h ; vertical line	½

.code
main proc
	mov ax, @data
	mov ds, ax
	call sercursorpos		; puts cursor at x=20, y=10
		; could instead move into dh and dl coordinates
		; for cursor position -- this would probably
		; be better design. Shown as it is so you can
		; see the complete sequence required to set the
		; cursor's position.
	call writeline		
	call setcursorpos
	mov al, ul 	; upper left 
	call displchar
		; now we have upper left corner and top line.

vertline: 	
	mov cx, 10		; line will be 10 characters high
	inc y1		; start at next line, otherwise we'd write
				; over upper left corner character

l1:	call setcursorpos		; will move the cursor to new position
					; indicated by x1 (unchanged) and y1: 20, 11
	mov al, vl		; set character to display -- vert. line
	call displchar	; display the character
	inc y1		; down to next line
	loop l1		
	; here you would add code to reset x1 and y1 to original values
	; then set x1 to the righthand side and make another
	; vertical line in the right side.
	
	mov ax, 4c00h
	int 21h

setcursorpos proc
	mov ah, 2
	mov dh, y1	; row 10 'y'
	mov dl, x1	; col 20 'x'
		; upper left corner is 0, 0
	mov bh, 0	; video page 0
	int 10h	; bios call which is a different kind of a call
		; than a dos call. See notes below
	ret
setcursorpos endp

displchar proc
	push cx
	mov ah, 09h
	mov bh, 0		
	mov bl, 10h
	mov cx, 1		; only display the character once!
	int 10h
	pop cx
	ret
displchar endp

writeline proc
	mov ah, 9 ; write char and attribute
	mov al, 0c4h ; write a line (ascii long dash) ; could've used hline
	mov bh, 0 ; video page 0
	mov bl, 10h ; blue background, black char	
		; sets blinking/nonblink, background, foreground
	mov cx, 30 ; write 30 long dashes starting where cursor is set
		; number in cx causes bios call to loop
	int 10h ; call bios
	ret
writeline endp

-------------------------------------------------------------------

Works by :
	putting cursor in upper left corner
	write horizontal line
	move back to the starting place
	put in corner character
	put in vertical line characters
	(displays black line in blue background)

Bios calls:

	There are 3 levels on which you can do input/output:
	- dos calls (slowest, simplest)
	- bios calls (faster)
	- direct (fastest, most complex) - used for most graphics and
	complex video, like Windows.

See page 126

The 10h bios call	 sets

first byte:
	1st bit sets blink/nonblink: 0 indicates nonblink
	bits 2-4 indicate background color: 001 means blue
					red would be 100
	bits 4-8 indicate foreground color
therefore 10h gives you non-blinking blue background (1h=0001b)
with black characters (0h = 0000b)
90h would give you blinking blue background with black characters

You could store the height and width in variables so that
the box could be of a particular size in a particular location.              

See the assignment entitled "seventh laboratory assignment" for
additional tasks to add the labels and input lines. 

-------------------------------------------------------------------

You could change the background color of the entire screen by calling
0bh (see pages 127 and 577).
-------------------------------------------------------------------

We could have a quiz next week.
The final (which is open book) is December 21st; there will be some 
review on December 14th, which is the last day of class.

-------------------------------------------------------------------
Disassemblers will show you the assembler of compiled source
code; you can usually find advertisements for them in the back
pages of Dr. Dobbs, many of which will also put in variable names
and some comments. 

It is very hard to disassemble PC code by visually inspecting it
because the instructions are of variable length.

-------------------------------------------------------------------
Page 113: Nested procedure calls

main proc
000A	call sub1	 ; stack gets copy of return address
000C	mov ax...
main endp

sub1 proc
0050 call sub2	; stack gets copy of return address, already has 000C
			; now also has 0052
	...
	ret
sub1 endp

sub2 proc
0060 call sub3	; stack is now 000C 0052 0062
	...
	ret
sub2 endp

sub3 proc
  	...
	ret
sub3 endp
These are referred to as nested procedure calls.

Each time you return, another address is popped off to get you
back. Should the stack reference be messed up by not having the
appropriate # of pushes & pops, you would not go all the way or 
enough of the way back to where you came from.

-------------------------------------------------------------------
2 kinds of interrupts:
Machine interrupt -- Takes priority over most other things.
  There are 2 kinds of machine interrupts.
	Maskable -- you can delay paying attention to it later.
		STI -- enable interrupt
		CLI -- disable interrupt
	Non-maskable (NMI - non-maskable interrupt) -- A special pin
		on the CPU creates this
Software interrupt -- Int ### -- not really an interrupt -- it's 
a particular kind of subroutine call

When an interrupt occurs, the CPU clears the IF to prevent all other
interrupts from interfering with the ISR. The IF is the Interrupt 
Flag (Flags register); the ISR is the Interrupt Service Routine.

Int n -- called a synchronous interrupt, it accesses the Interrupt
	Vector Table (IVT). The n Tells CPU which entry to locate 
	in the IVT.
The Interrupt Handler (a DOS or BIOS function) begins execution
and finishes when the IRET instruction ("interrupt return") is 
reached. This causes the program to resume at the next instruction
in the original calling program.

There are a number of Interrupt Service Routines:
	INT 10h -- video services
	INT 16h -- keyboard services
	INT 17h -- printer 
	INT 1Ch -- timer
	INT 21h -- DOS

Make sure to read all this material in the book. Try out some
of the code to see experience the way it works.

-------------------------------------------------------------------
Local labels (this is not in the book!)
Requires LOCALS in your code segment.
For example:

.code
...
LOCALS
@@10:  INC AX
	 CMP AX, 10
	 JNE @@10		; goes line of code above that says INC AX
THERE: CMP AX, 20
	 JNE @@10		; sends you 2 lines down to line after XOR CX, CX
	 XOR CX, CX
@@10:  ...

Same label in 2 places. Each time you have a new occurrance of the
same label, the previous one loses its definition.

Local labels are distinguished by the two @ followed by up to 255
other characters (special setting for variable length required if
more than 31 characters long.

-------------------------------------------------------------------
Redirecting Input/Output

C:\> prg1 > prn
Invokes prg1.exe, redirecting output to printer.
C:\> prg1 < A:\INFILE
Redirects input to come from a:\infile instead of keyboard.
C:\> prg1 < A:\INFILE > PRN
Redirect both input & output at once.

C:\> prg1 < A:\INFILE > A:\OUTFILE

Read material & code about INT 21h 

-------------------------------------------------------------------
Flags are set by instructions such as ADD, SUB, INT, LOOP.
Most commonly, you would set flags by using CMP.
For example
	CMP AX, MEM
	JNE ; if AX <> MEM then do the jump

CMP has some special register that gets the value of AX-MEM. Does 
subtraction without affecting either operand; result is thrown away
and flags are set. 

CMP Compare instruction sets the flags as follows:
If destination < Source, CF (Carry Flag) = 1
If destination = source, ZF (Zero flag) = 1
if destination > source, CF (Carry Flag) = 0, ZF (Zero flag) = 0


JZ ; will jump if ZF = 1.
JE ; will jump if CMP dest, source ; if dest, source are equal
JNZ ; zero flag = 0
JNE ; 

JA ; if dest > source		 	; same as JNBE
JNBE ; not below and not equal	; same as JA

Can use these instructions after any instruction that sets the
flag register.

Read all about these in chapter 6.

-------------------------------------------------------------------
Pascal code:  sum := 0;
		  for i := 1 to 10 do
		    inc(sum,i);

In assembler, this could be done with a LOOP or JMP instruction.
; let i be in register BX
; let sum be in register AX
	XOR AX, AX		; sum := 0 (set AX (sum) to 0).
	MOV BX, 1		; set BX (i) to 1.
for:	CMP BX, 10		; check for limit of for loop
	JGE outofloop	; jump if BX greater than or equal to 10
				; (exit loop if finished)
		; BX not >= 10
	ADD AX, BX		; Inc(sum, i) (Increment loop counter i)
	INC BX		
	JMP for		; Loop  (repeat loop)
outofloop:  ...



Pascal loop types		C
for				for
while..do			while
repeat..until		do.. while


Pascal code:
while (i < n) do begin
  Inc(sum, i);
  Inc(i)
end;

in assembler: ; using memory "just for fun"

	MOV AX, i
test:	CMP AX, n
	JL while
	JMP out
while: ADD SUM, AX
	INC AX
	JMP test
out:	...