Class of December 14, 1996



Topics of the day:
	Recursive Functions
	Disk i/o
	Linking C++ and Assembler
	Linking C and Assembler


Recursive Functions
-------------------
P. 240 shows a recursive routine.

main proc
	mov cx, 5
	mov ax, 0
	call sum
  L1:	mov ax, 4C00h
	int 21h
main endp

sum proc
	or cx, cx   ; sets the flags register. When cx is finally zero,
			; jumps to L2
	jz L2		; is cx 0?
	add ax, cx  ; not zero, add cx to ax, making ax 5, next 9, next
			; 12, 14, 15
	dec cx	; cx = 4, then 3, 2, 1, 0
	call sum	; stack L1, L2, L2, L2, L2, L2
  L2:	ret		; this statement is executed 6 times until finally
			; the L1 is popped off the stack.
sum endp

P. 241 contains a more complicated example, demonstrating factorial.

endless proc 
	...
	call endless 
	ret
endless endp

Eventually causes a stack overflow and the machine hangs.

IMPORTANT: Recursive procedures must have something to terminate them!

Procedures that recurse many, many times, but will eventually end, may require a larger stack.


Multibyte arithmetic
--------------------
P. 183 and 184 show Multi-word Add.

in .data, op1 and op2.

When you look at ds:0000, you will see (this is op1 and op2 with all their
bytes reversed)
	(op1)	     (op2)
	06A4 B2A2  0087 1080 	
at ds:0008, you will see
	062B C322 0100 0000 ; after execution

before execution, ds:0008 contains only 0's.

Multiword_add proc (p. 184)
	first, ax gets the low-order byte of the doubleword -- it
	appears at the left end (because the bytes are reversed in memory!)
					    
mov ax, [si]	;         ax = A406
adc ax, [di]	; di points to 8700, ax = B 
			;     	   ----
			; ax =	   2B06	; the extra 1 goes into the carry
pushf			; save flags on stack
mov [bx], ax	; puts 062b into place pointed to by bx
	; now point everything to next word.

next add with carry gives us: A2B2
					8010
carry flag from last time	   1
					----
					22C3	; extra 1 is carried!
C322 is stored at bx's new location.

adc word ptr [bx], 0 ; add in any leftover carry
	puts an 0001 into bx's newest location

now, 062B C322 0100 0000



; say you wanted to move ah into di.  Can't do it because ah is only 8
; bytes, so you save ax, zero-out al, then move the entire ax into di.
push ax
xor al, al ; same result as: and ax, FF00h (which is slower)
	; an instruction that uses only registers is faster than an
	; an instruction that uses memory or an immediate operand.
mov di, ax
pop ax

; This whole business of course, would give you 3000 if you had 30 in
; ah, which might yeild different results than expected -- possibly
; you would need to shift ah to the right so that you would get 0030...


Linking C++ and assembler
-------------------------
In the 2-page example handed out, it is necessary to use the command-line compiler to link the C and assembler programs!

With TurboC++, enter tcc instead of bcc.

Of particular interest in the C++ code example is
char * TestString="Line1\nLine2\nLine3";
extern "C" unsigned int LineCount(char * StringToCount,
  unsigned int * CharacterCountPtr); /* C knows how we're going to 
      call it, and where to find it (externally) */

in the assembler code:
PUBLIC _LineCount	; allows the procedure _LineCount 
			; to be seen from outside

in C++:
  LCount = LineCount(TestString, &CCount);
	/* sends in 2 addresses to the assembler function */

C++			assembler 
--------------	--------------
LineCount		_LineCount

push bp		; we don't really know why this is saved and the
			; other registers aren't

			; sp has the return address from C++ program and
			; the 2 pointers we passed.
mov bp, sp		; save stack pointer in bp -- not good style to
			; work directly with stack pointer.

push si

mov si,[bp+4]	; pointer to TestString (return address takes up the
			; first 4 bytes of the stack.)

&CCount		[bp+6]

LCount		ax



File I/O
--------

@ platter in a hdd has its own read/write head

@ sector has a sector address; formatting a diskette writes the address of each sector in its proper starting place.

Latency is how long you have to wait for the sector for pass under the
read/write head.

The boot sector is found starting at track 0, sector 0...?
Part of the FAT is also stored there.

2 methods of accessing disk:
	dos calls
	bios

File structure is designated by the o/s. Without doing something special, you can't read a diskette written by a different o/s.

Chapter 11 talks about the organization of a disk in detail.
3.5" diskette/1.44 mb (varies for other sizes)
Sector contents
0	 boot record
1-18	 FAT
19-32	 root directory
33-2879	data area (includes subdirs)

Starting on p. 330, it shows data about DOS.
Directories - root holds links to all the other directories.

You can see this information in debug

c:\test\>dir a:
	new.wk1
	new.fmt
	count.asm
	callct.cpp
	callct.exe
c:\test\>debug
	l	100 0 13 2 ; read into memory location, drive a,
			; starting at sector 13, reading 2 sectors in.
	d	100 200 ; display the 1st 200 bytes 


The final will be mostly like the last quiz with some material discussed today.