Beruflich Dokumente
Kultur Dokumente
; fibo.asm
; assemble using nasm:
; nasm -o fibo.com -f bin fibo.asm
;
;****************************************************************************
; Alterable Constant
;****************************************************************************
; You can adjust this upward but the upper limit is around 150000 terms.
; the limitation is due to the fact that we can only address 64K of memory
; in a DOS com file, and the program is about 211 bytes long and the
; address space starts at 100h. So that leaves roughly 65000 bytes to
; be shared by the two terms (num1 and num2 at the end of this file). Since
; they're of equal size, that's about 32500 bytes each, and the 150000th
; term of the Fibonacci sequence is 31349 digits long.
;
maxTerms
equ 15000
;****************************************************************************
; Number digits to use. This is based on a little bit of tricky math.
; One way to calculate F(n) (i.e. the nth term of the Fibonacci seeries)
; is to use the equation int(phi^n/sqrt(5)) where ^ means exponentiation
; and phi = (1 + sqrt(5))/2, the "golden number" which is a constant about
; equal to 1.618. To get the number of decimal digits, we just take the
; base ten log of this number. We can very easily see how to get the
; base phi log of F(n) -- it's just n*lp(phi)+lp(sqrt(5)), where lp means
; a base phi log. To get the base ten log of this we just divide by the
; base ten log of phi. If we work through all that math, we get:
;
; digits = terms * log(phi) + log(sqrt(5))/log(phi)
;
; the constants below are slightly high to assure that we always have
; enough room. As mentioned above the 150000th term has 31349 digits,
; but this formula gives 31351. Not too much waste there, but I'd be
; a little concerned about the stack!
;
digits
equ (maxTerms*209+1673)/1000
org
100h
;****************************************************************************
;****************************************************************************
main:
; initializes the two numbers and the counter. Note that this assumes
; that the counter and num1 and num2 areas are contiguous!
;
mov
ax,'00'
mov
di,counter
mov
cx,digits+cntDigits/2
cld
rep
stosw
inc
ax
mov
mov
mov
jmp
.bottom
.top
; add num1 to num2
mov
di,num1+digits-1
mov
si,num2+digits-1
mov
cx,digits
call
mov
bp,num2
call
PrintLine
dec
dword [term]
jz
.done
;
;
; decrement loop counter
di,num2+digits-1
mov
si,num1+digits-1
mov
cx,digits
call
.bottom
mov
bp,num1
call
PrintLine
dec
dword [term]
jnz
.top
call
CRLF
mov
ax,4c00h
; terminate
int
21h
;
; decrement loop counter
.done
;****************************************************************************
;
; PrintLine
; prints a single line of output containing one term of the
; Fibonacci sequence. The first few lines look like this:
;
; Fibonacci(1): 1
; Fibonacci(2): 1
; Fibonacci(3): 2
; Fibonacci(4): 3
;
; INPUT:
; OUTPUT:
dx,eol
mov
cx,msg1len+eollen ;
call
PrintString
mov
di,counter
; print counter
mov
cx,cntDigits ;
call
PrintNumericString
call
IncrementCount
mov
dx,msg2
; print msg2
mov
cx,msg2len ;
call
PrintString
mov
di,bp
mov
cx,digits
;****************************************************************************
;
; PrintNumericString
; prints the numeric string at DS:DI, suppressing leading zeroes
; max length is CX
;
; INPUT:
; OUTPUT:
al,'0'
cld
repe
scasb
mov
dx,di
dec
dx
inc
cx
;****************************************************************************
;
; PrintString
; prints the string at DS:DX with length CX to stdout
;
; INPUT:
; OUTPUT:
; DESTROYED: ax, bx
;
;****************************************************************************
PrintString:
mov
mov
int
ret
bx, 1
; write to stdout
ah, 040h
21h
;****************************************************************************
;
; AddNumbers
; add number 2 at ds:si to number 1 at es:di of width cx
;
;
; INPUT:
; OUTPUT:
CF set on overflow
clc
pushf
.top
mov
ax,0f0fh
and
al,[si]
and
ah,[di]
popf
adc
aaa
; convert to BCD
pushf
add
al,'0'
stosb
dec
si
loop
.top
popf
ret
;****************************************************************************
;
; IncrementCount
; increments a multidigit term counter by one
;
; INPUT:
none
; OUTPUT:
CF set on overflow
cx,cntDigits ;
mov
di,counter+cntDigits-1
std
stc
pushf
.top
mov
ax,000fh
and
al,[di]
popf
adc
aaa
; convert to BCD
pushf
add
al,'0'
stosb
loop
.top
popf
ret
;****************************************************************************
;
; CRLF
; prints carriage return, line feed pair to stdout
;
; INPUT:
none
; OUTPUT:
dx,eol
mov
cx,eollen
jmp
PrintString
;****************************************************************************
; static data
;****************************************************************************
eol
db 13,10
msg1 db 'Fibonacci('
msg1len
equ $ - msg1
equ $ - msg2
;****************************************************************************
; initialized data
;****************************************************************************
term dd maxTerms
;****************************************************************************
; unallocated data
;
; A better way to do this would be to actually ask for a memory
; allocation and use that memory space, but this is a DOS COM file
; and so we are given the entire 64K of space. Technically, this
; could fail since we *might* be running on a machine which doesn't
; have 64K free. If you're running on such a memory poor machine,
Alarm
100h
; interrupt address
whozat
equ 1234h
; signature
; color attribute
assume cs:cseg,ds:cseg,ss:nothing,es:nothing
jmp p150
; start-up code
jumpval dd 0
signature dw whozat
; program signature
state db 0
wait
dw 18
hour dw 0
atime dw 0ffffh
acount
dw 0
atone db 5
aleng dw 8080h
dhours
dw 0
; display hours
db ':'
dmins dw 0
; display minutes
db ':'
dsecs dw 0
; display seconds
db '-'
ampmdb 0
db 'm'
db 0
; end of stack
holdsp
dw 0
; original sp
holdssdw 0
; original ss
p000:
; interrupt code
push ax
; save registers
push ds
pushf
push cs
pop ds
mov ax,wait
dec ax
jz p010
; make ds=cs
; check wait time
; zero?
; yes - 1 second has elapsed
mov wait,ax
jmp p080
; return
p010: cli
mov ax,ss
; disable interrupts
; save stack
mov holdss,ax
mov holdsp,sp
mov ax,ds
mov ss,ax
; allow interrupts
push bx
push cx
push dx
push es
push si
push di
push bp
mov ax,18
mov wait,ax
mov al,state
; are we disabled?
cmp al,'-'
jnz p015
; no
jmp p070
; read time
int 1ah
mov ax,dx
; low part
mov dx,cx
; high part
mov cl,4
shl dx,cl
; multiply by 16
mov bx,ax
mov cl,12
shr bx,cl
add dx,bx
; now in upper
mov cl,4
shl ax,cl
; multiply by 16
mov bx,mfactor
div bx
; compute minutes
; minutes in ax, remainder in dx
cmp ax,atime
jnz p020
; no
call p100
push ax
mov ax,acount
dec ax
; down by 1
mov acount,ax
cmp ax,0
; is it zero?
jnz p018
; no - keep alarm on
mov ax,0ffffh
mov atime,ax
p018: pop ax
; save remainder
mov bx,60
; compute hours
xor dx,dx
; zero it
div bx
mov dmins,dx
; save minutes
cmp ax,0
; midnight?
jnz p030
; no
mov ax,12
; yes
jmp p040a
; set am
; before noon?
jb p040a
; yes - set am
jz p040p
; noon - set pm
sub ax,12
p040p:
mov bl,'p'
jmp p040x
p040a:
mov bl,'a'
p040x:
mov ampm,bl
aam
; fix up hour
cmp ax,hour
jz p060
; no
mov hour,ax
call p120
xchg ah,al
mov dhours,ax
mov ax,dmins
; get minutes
aam
add ax,3030h
; convert to ascii
xchg ah,al
mov dmins,ax
mov ax,dsecs
xor dx,dx
mov bx,60
mul bx
mov bx,mfactor
div bx
; seconds in ax
aam
add ax,3030h
xchg ah,al
mov dsecs,ax
xor ax,ax
mov es,ax
mov ax,es:[410h]
and al,30h
cmp al,30h
; color?
mov ax,0b000h
jz p061
; assume mono
; its mono
mov ax,0b800h
mov es,ax
; point to monitor
mov bh,color
; color in bh
; point to time
mov di,138
; row 1, col 69
cld
mov cx,11
; loop count
p063: in al,dx
test al,1
; is it low?
jnz p063
; no - wait
cli
; no interrupts
p064: in al,dx
test al,1
; is it high?
jz p064
; no - wait
mov ax,bx
stosw
sti
; interrupts back on
inc si
loop p062
; done?
p070: pop bp
; restore registers
pop di
pop si
pop es
pop dx
pop cx
pop bx
cli
; no interrupts
mov ax,holdss
mov ss,ax
mov sp,holdsp
sti
; allow interrupts
p080: popf
pop ds
pop ax
jmp cs:[jumpval]
call p120
push cx
mov cx,20000
p105: loop p105
; wait around
pop cx
call p120
push cx
mov cx,20000
p106: loop p106
; wait around
pop cx
call p120
ret
p100 endp
push ax
push cx
mov al,182
out 43h,al
mov al,0
out 42h,al
mov al,atone
out 42h,al
; low part
; get alarm tone
; high part
in al,61h
push ax
or al,3
out 61h,al
mov cx,aleng
p125: loop p125
pop ax
out 61h,al
pop cx
; turn speaker on
; get loop count
; wait around
; restore original port value
; turn speaker off
pop ax
ret
p120 endp
p150:
; print copyright
mov ax,0
mov es,ax
; segment 0
; is it this program?
cmp cx,whozat
jnz p160
; no - install it
call p200
int 20h
; terminate
; segment 0
mov ax,ds
; get current ds
mov es:[di],ax
mov bx,es:[di]
; get timer ip
mov ax,es:[di+2]
; and cs
mov [si],bx
; save prior ip
mov [si+2],ax
mov bx,offset p000
mov ax,ds
; and cs
cli
; clear interrupts
mov es:[di],bx
mov es:[di+2],ax
sti
; set interrupts
push ds
pop es
call p200
; terminate
mov ax,0
mov di,0ffffh
; init hours
mov bh,0
mov ch,0
mov dh,0
; : counter
; get length
jcxz p210
; it's zero
p203: inc si
mov bl,[si]
cmp bl,'-'
jnz p204
; no
mov es:[state],bl
push dx
mov dx,offset msg3
call p220
pop dx
jmp p206
; print msg
cmp bl,':'
; colon?
jnz p205
; no
inc dh
cmp dh,2
; second colon?
jz p206
push cx
push dx
mov cx,60
mul cx
; multiply current ax by 60
pop dx
pop cx
mov di,ax
; save hours
mov ax,0
jmp p206
p205: cmp bl,'0'
jb p206
; too low
cmp bl,'9'
ja p206
sub bl,'0'
push cx
push dx
mov cx,10
mul cx
add ax,bx
pop dx
pop cx
p206: loop p203
; done yet?
cmp di,0ffffh
jz p210
; no
add ax,di
; add hours
cmp ax,24*60
jb p209
; ok
call p220
jmp p210
call p220
p210: ret
p200 endp
; print message
push ax
mov ah,9
int 21h
pop ax
ret
p220 endp
alarm endp
cseg ends
end
alarm
ah,
1h
//keyboard
//
21h
//
MOV c, al
character
is
//copy character from alto c
input
character
subprogram
input
in
al
stored
ah,
1h
//
INT
MOV
21h
dl,
MOV
INT 21h
ah,
2h
// display character in dl
keyboard
//read
//copy
al
input
character
character
//character
subprogram
into
to
output
al
dl
subprogram
100h
MOV
LEA
AL, VAR1
BX,
VAR1
MOV
MOV
BYTE
PTR
AL, VAR1
//
check
value
//get
of
[BX],
44h
//
//check value
RET
VAR1
VAR1
address
modify
of VAR1
by
moving it
of
VAR1
the
contents
by moving it
to
the
in
AL.
BX.
of
VAR1.
to the AL.
DB
22h
END
Write a Program For Displaying The String Using Library Functions
include
ORG
emu8086.inc
//Macro
PRINT
GOTOXY
PUTC
PUTC
RET
END
declaration
100h
Hello
10,
65
//
65
//return
//directive to stop the compiler.
World!
5
is
to
an
ASCII
the
code
operating
for
A
B
system.
Addition
ORG0000h
MOV DX, #07H
END
Multiplication
ORG0000h
MOV DX, #04H
END
Subtraction
ORG 0000h
MOV DX, #02H
END
Division
ORG 0000h
MOV DX, #08H
Example programs
A program shown below takes the character in 'A' register, transmits it, delays for transmission time, and returns to the calling
program. Timer-1 is used to set the baud rate, which is 1200 baud in this program
The delay for one character transmission (in Mode 1 i.e.10 bits) is
10/2400
Or, 8.33 milliseconds
0.00833
Hence
software
delay
of
10ms
Timer-1 generates a baud rate close to 1200. Using a 12MHz crystal, the reload value is
seconds
is
used.
This
gives
rise
SMOD is programmed to be 0.
to
an
actual
baud
rate
of
1202.
The loop "MILSEC" generates a delay of about 1 x 10-3 sec. This gets executed 10 times for a total delay of 10 x 10-3 sec or 10ms
In 8051, when a character is transmitted, SBUF register becomes empty and this generates a serial port interrupt (TI). TI and RI
both point to the vector location 0023H in the program memory. An interrupt service routine can be written at 0023H to send the nex
character.
A program is written here to transmit a character say 'A' continuously based on interrupt. The microcontroller uses a clock of 12MHz
with a baud rate of 1202. The program is executed following a hardware reset.
When a character is received, if receive mode is enabled, RI flag is set. This leads to the interruption of the main program and the
processor goes to the interrupt vector location, i.e. 0023H for serial port. The interrupt service routine at 0023H gets executed to
read the character so that the next character can be received. The following program receives a character on interrupt basis and
outputs the character to port-1, possibly for a display.
The crystal frequency is12MHz and baud rate is set at 1202 baud.