Class of October 26, 1996


The end of Chapter 3

You can't POP into CS or IP.
INC and DEC do not affect the carry flag (No Carry is indicated after 
these operations.)
ADD and SUB affect all the flags. Is signed arithmetic required? If signed 
arithmetic is required, you have to pay attention to the sign flag; if it is 
not required, you still have to worry about the overflow flag. The overflow 
flag means that you have lost precision (you got the wrong answer) -- 
think of this as you having "flow into sign position, and no flow out" or 
"flow out of sign position and no flow in" -- the sign bit changed 
in a way that will change the number.

For example, if you try to add the following hexidecimal numbers: 8000 + 
8000, you get 0. These are the largest negative numbers you can have -- in 
binary, they are 1000 0000 0000 0000. 

At this point, he did some examples of positive and negative binary numbers. 
(Omitted here.)

To show the true value of a negative hexidecimal number, such 
as -000A, you must take the 16's compliment like this:
	10000
	-000A
     --------
	 FFF6
or, the easier way: show as binary, take twos compliment, then translate
back to hexidecimal
	-000A = 00001010
		  11110101 (flip all bits)
			   1 (add one)
		 ----------
		  11110110 = F6

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

Chapter 4

Remember when inputting from the keyboard, the numbers that go into
the AL register are ASCII, so if you typed in 123, AL would get 31,
32 and 33.

Now he reviews ASCII and hexidecimal vs. decimal.

When a BIOS or DOS call is needed, find the function in a "table"
(which interrupt (int)) and what to put in register.
After the function executes, look at registers or screen for result.

P. 121 shows the DOS call to 0Ch, which clears the input buffer and 
invokes the input function. (This to be used in problem 5 on the quiz.)

MOV AH, 0Ch
MOV AL, 1
INT 21h
MOV char, AL

;The above code reads in one ascii value from the keyboard and stores
;it in the variable called char. (DOS looks at AH and AL to figure out 
;what to do.)

AND char, 01011111 b ; y = 79h (0111 1001), Y = 59h (0101 1001)
	; AND 01011111
	;     10001001
	;    ----------
    	;     01011001

	; Will change a lower case y to an uppercase Y; if already
	; uppercase, remains unchanged. Makes it not case-sensitive.

CMP char, 'Y' ; did the user type a Y?
JNE output_message ; Go to output_message if user didn't type Y (if
	; Zero flag isn't = 1

output_message: ; Print something like "You didn't type Y"

We use 0Ch because it is a good idea to clear the input buffer first, 
in case there is a spurious character waiting there.

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

The INTEL is a CISC (Complex Instructino Set Code), whereas the
Sun and Motorola 601, 602 and 603 chips are RISC (Reduced Instruction
Set Code). RISC machines are not capable of performing as many
complex functions as the CISC. For example, they don't have LOOP
instructions or string function; because of this, it was thought
that they would be much faster; however the INTEL has managed to
keep up with this. In RISC machines, each instruction requires less
microcode to execute. They also have more registers in the CPU.

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

The assembly process is essentially a 2 pass operation:
(1) Finds values of symbols, does some translation to hex code.
(2) Completes translation, creates .obj module, and possibly .lst
  and .map.

Assembler has many commands, pseudo operations and mnemonics.
A command is a directive to the assembler, for example:
	.data
	.code
	main
Mnemonics are real operaions or instructions, for example:
	mov
	add
	jmp
	cmp
A pseudo-op is not a machine operation, instead they help to 
prepare of your proram
	dw
	db
	equ
	=		

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

You might want to think about making a batch file to assemble
and link your program:

HIS VERSION:
	@echo off
	cls
	TASM /zi /l %1
	IF ERRORLEVEL 1 GOTO END
	TLINK /v %1
	IF ERRORLEVEL 1 GOTO END
	TD %1
	:END

MY VERSION:

	TASM /zi /l %1
	TLINK /v %1

(I don't use the echo off, because I like to see the output, since
I usually make some stupid syntax errors, which may take several
tries to rectify before it assembles correctly. tlink won't work
if tasm fails, and will give one line of error message. I don't call 
TD from the batch, I run it off a desktop shortcut or in a separate 
DOS box, so I can see the history of the last couple of things I 
compiled in the original DOS window. All a matter of personal 
preference (and whether or not you have control over the setup of
your PC. May as well mention that I use the Delphi editor, since I 
work with it all day long, it is very convenient for me, and is far 
superior to EDIT, which stinks. So, I have 3 windows open, one dos
box where I call my batch file, one where I run td, and another
where I have Delphi running.))

save as cp.bat
then call it by, for example:
	cp myprog

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

If you say 
	A = 37
then wherever A is seen in your program, it is replaced with a 37.
You can reassign it later if you like. It is not unlike a #DEFINE
in C or a $DEFINE in Delphi.
NOT the same as saying
	A db 37
which creates a variable, initialized with the value of 37.

You could say
	A equ 37
which is almost the same as A = 37, but does not allow the value of
the symbol (A, in this case) to be changed.

You can also use equ like a compiler macro:
	address equ offset

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

Arithmetic operatior precedence
	()
	+ - (unary)
	*
	/
	mod
	+
	-
	boolean (AND OR NOT XOR)

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

OFFSET
PTR
LABEL

.data
	blist db 10,20,30,40
	wlist dw 1000,2000,3000


mov di, offset blist	; di points to the first element of blist
mov bx, offset blist+1	; points to second element of blist 

mov al, [di]		; AL is 10. Indirect addressing.
mov ah, [bx]		; AH is 20.
mov ax, bx			; AX is 1.

(Long review of addressing omitted. My suggestion: go back to your
C notes or textbook and review the difference betweeen & and *, or
to your Pascal textbook and review the difference between @ and ^.)

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

; function
call_me proc
  push ax
  push bx
  ; stuff
  mov cx, 2
  mov bx, 3
  ; more stuff
  pop bx
  pop ax
  ret
call_me endp

invoke the function by:
	call call_me ; pushes location counter into stack
	ret	; uses stack to supply return address

if the function is in the middle of your other code, you 
have to issue a jump to the first line of code after the
procedure. for example:
  mov di, offset a
  jmp around
  ; function code here
  around: ; the rest of the code 

Important: you must have the same # of pops as pushes in
the function or you won't go back to the proper place
in your code.

Suppose you had to read a character:
  input proc
    mov ah, 0Ch
    mov al, 1
    int 21h
    ret
  input endp