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.