22
Assembly Language Requirement Submitted by: Pierre Paul Balanon

Assembly language

  • Upload
    bryle12

  • View
    115

  • Download
    1

Embed Size (px)

Citation preview

Page 1: Assembly language

Assembly LanguageRequirement

Submitted by:

Pierre Paul Balanon

Page 2: Assembly language

#1

Chips

; calling convention:

;

; int chips( void );

;

; returns:

;

; tucked away neatly in your AX....

;

; you get back 8x if an 8088/8086

; 18x if an 80186/80188

; 28x if an 80286

; 38x if an 80386

; 20x for a NEC V20/V30

; AND

; xx0 if NO NDP is found

; xx1 if an 8087

; xx2 if an 80287

; xx3 for an 80387

;

; OR.....

;

Page 3: Assembly language

; >>> A return of 280 means you got an 80286 machine with no NDP, <<<

; >>> 383 means you have an 80386/80387 rig to work with, and a <<<

; >>> return of 81 sez that you have 8088/8086 CPU with an 8087. <<<

; >>> A 200 tells you that you got an NEC V20/V30 without an NDP. <<<

; >>> ETC., Etc., etc. <<<

;

; NOTE:

;

; There are lotsa ways of handling the way this function returns

; it's data. For my purposes, I have elected this one because

; it requires only int arithmetic on the caller's end to extract

; all the info I need from the return value. I think that I'm

; well enough 'commented' in the following code so that you will

; be able to tinker and Putz until you find the best return tech-

; nique for Ur purposes without having to reinvent the wheel.

;

; >>>> Please see TEST.C, enclosed in this .ARC. <<<<

;

; REFERENCES:

;

; _chips is made up of two PROC's, cpu_type and ndp_type.

;

; cpu_type is based on uncopyrighted, published logic by

; Clif (that's the way he spells it) Purkiser of Intel -

Page 4: Assembly language

; Santa Clara.

;

; ndp_type is adopted from Ted Forgeron's article in PC

; Tech Journal, Aug '87 p43.

;

; In the event of subsequent republication of this function,

; please carry forward reference to these two gentlemen as

; original authors.

;

.MODEL SMALL

.CODE

PUBLIC _chips

_chips PROC

control dw 0 ; control word needed for the NDP test

push BP ; save where Ur at

mov BP,SP ; going in.....

push DI

push SI

push CX ; not really needed for MSC but kinda

; nice to do cuz someone else might

Page 5: Assembly language

; want to use the function and we do

; use CX later on

call cpu_type ; find out what kinda CPU you got and

; and save it in DX for future reference

call ndp_type ; check for math coprocessor (NDP) type

; and hold that result in AX

add AX,DX ; add the two results together and hold

; 'em in AX for Ur return to the caller

pop CX ; put things back the way that you

pop SI ; found 'em when you started this

pop DI ; little drill off.....

pop BP

; AND

ret ; go back to where you came from....

; ( ===> the calling program )

; with Ur results sittin' in AX !!

_chips endp

cpu_type PROC

Page 6: Assembly language

pushf ; pump Ur flags register onto the stack

xor DX,DX ; blow out Ur DX and AX to start off

xor AX,AX ; with a clean slate

push AX ; put AX on the stack

popf ; bring it back in Ur flags

pushf ; try to set bits 12 thru 15 to a zero

pop AX ; get back Ur flags word in AX

and AX, 0f000h ; if bits 12 thru 15 are set then you got

cmp AX, 0f000h ; an Intel 8018x or a 808x or maybe even

jz dig ; a NEC V20/V30 ??? - gotta look more...

; OTHERWISE....

; Here's the BIG one.... 'tells the difference between an 80286 and

; an 80386 !!

mov AX, 07000h ; try to set FLAG bits 12 thru 14

; - NT, IOPL

push AX ; put it onto the stack

popf ; and try to pump 07000H into Ur flags

pushf ; push Ur flags, again

pop AX ; and bring back AX for a compare

and AX,07000h ; if Ur bits 12 thru 14 are set

jnz got386 ; then Ur workin' with an 80386

mov DX, 0280 ; save 280 in DX cuz it's an 80286

Page 7: Assembly language

jmp SHORT CPUbye ; and bail out

got386: mov DX, 0380 ; save 380 in DX cuz it's an Intel 80386

jmp SHORT CPUbye ; and bail out

; here's we try to figger out whether it's an 80188/80186, an 8088/8086

; or an NEC V20/V30 - 'couple of slick tricks from Clif Purkiser.....

dig: mov AX, 0ffffh ; load up AX

mov CL, 33 ; HERE's the FIRST TRICK.... this will

; shift everything 33 times if it's

; 8088/8086, or once for a 80188/80186!

shl AX, CL ; on a shift of 33, all bits get zeroed

jz digmor ; out so if anything is left ON it's

; gotta be an 80188/80186

mov DX,0180 ; save 180 in DX cuz it's an 80188/80186

jmp SHORT CPUbye ; and bail out

digmor: xor AL,AL ; clean out AL to set ZF

mov AL,40h ; ANOTHER TRICK.... mul on an NEC duz NOT

mul AL ; effect the zero flag BUT on an Intel

jz gotNEC ; 8088/8086, the zero flag gets thrown

mov DX,0080 ; 80 into DX cuz it's an Intel 8088/8086

jmp SHORT CPUbye ; and bail out

Page 8: Assembly language

gotNEC: mov DX,0200 ; it's an NEC V20/V30 so save 200 in DX

CPUbye: popf ; putchur flags back to where they were

ret ; and go back to where you came from

; (i.e., ===> _chips) with the CPU type

; tucked away in DX for future reference

cpu_type endp

; Check for an NDP.

;

; >>>>NOTE: If you are using an MASM version < 5.0, don't forget to

; use the /R option or you will bomb cuz of the coprocessor instruc-

; tions. /R is not needed for version 5.0.<<<<<<<<<<<<<<<<<<<<<<<<<

ndp_type PROC

do_we: fninit ; try to initialize the NDP

mov byte ptr control+1,0 ; clear memory byte

fnstcw control ; put control word in memory

mov AH,byte ptr control+1 ; iff AH is 03h, you got

cmp AH,03h ; an NDP on board !!

je chk_87 ; found somethin', keep goin'

xor AX,AX ; clean out AX to show a zero

Page 9: Assembly language

jmp SHORT NDPbye ; return (i.e., no NDP)

; 'got an 8087 ??

chk_87: and control,NOT 0080h ; turn ON interrupts (IEM = 0)

fldcw control ; load control word

fdisi ; turn OFF interrupts (IEM = 1)

fstcw control ; store control word

test control,0080h ; iff IEM=1, 8087

jz chk287 ; 'guess not! March on....

mov AX,0001 ; set up for a 1 return to

jmp SHORT NDPbye ; show an 8087 is on board

; if not.... would you believe an 80287 maybe ??

chk287: finit ; set default infinity mode

fld1 ; make infinity

fldz ; by dividing

fdiv ; 1 by zero !!

fld st ; now make a

fchs ; negative infinity

fcompp ; compare Ur two infinities

fstsw control ; iff, for 8087 or 80287

fwait ; sit tight 'til status word is put away

Page 10: Assembly language

mov AX,control ; getchur control word

sahf ; putchur AH into flags

jnz got387 ; NO GOOD.... march on !!

mov AX,0002 ; gotta be a 80287 cuz we already tested

jmp SHORT NDPbye ; for an 8087

; We KNOW that there is an NDP on board otherwise we would have bailed

; out after 'do_we'. It isn't an 8087 or an 80287 or we wouldn't have

; gotten this far. It's gotta be an 80387 !!

got387: mov AX,0003 ; call it an 80387 and return 3

NDPbye: ret ; and go back where you came from

; (i.e., ===> _chips) carrying the NDP

; type in Ur AX register

ndp_type endp

_text ends

End

Page 11: Assembly language

#2

Game Port

; GAMEPORT.ASM

;

.MODEL TINY

.DATA

yes DB 13,10,"Game port is installed.",13,10,"$"

no DB 13,10,"Game port is not installed.",13,10,"$"

.CODE

ORG 100h

start: mov al, 1 ;value to write to port

mov dx, 201h ;port number

out dx, al ;write to port

mov cx, 0F00h ;# of loops

port_loop:

Page 12: Assembly language

in al, dx ;read from port

and al, 0Fh ;if jstick present, then AL should be

cmp al, 0Fh ; 0Fh after ANDing with 0Fh.

je jstick_exists

loop port_loop

mov dx, OFFSET no ;gameport not installed

jmp SHORT done

jstick_exists:

mov dx, OFFSET yes ;gameport installed

done: mov ah, 9h

int 21h

mov ax, 4c00h

int 21h

END start

Page 13: Assembly language

#3

Clock

CGROUP GROUP VECTOR,CODESEG

VECTOR SEGMENT AT 0H

DB 6CH DUP(?) ;FILLER

TIME_LO DW ? ;DOS TIME

TIME_HI DW ? ;DOS TIME

VEC_IP DW ;CLOCK UPDATE VECTOR IP

VEC_CS DW ;CLOCK UPDATE VECTOR CS

VECTOR ENDS

CODESEG SEGMENT PARA

ASSUME CS:CODESEG,DS:CGROUP

ORG 100H

CLK PROC FAR

JMP SETUP ;ATTACH TO DOS

INTRPT LABEL DWORD

INT_IP DW 0 ;OLD UPDATE VECTOR IP

INT_CS DW 0 ;OLD UPDATE VECROR CS

TICKS DW 0 ;TICK COUNTER

SCR_OFF DB 0,0 ;SCREEN OFFSET IN BUFFER

Page 14: Assembly language

CRT_PORT DW 0 ;SCREEN STATUS PORT

flag db 0

TIME DB 8 DUP(':',0BH) ;TIME SAVE AREA

CLK_INT LABEL NEAR

PUSH AX ;SAVE REGISTERS

PUSH CX

PUSH DI

PUSH SI

PUSH DS

PUSH ES

PUSHF ; AND FLAGS

CALL CS:[INTRPT] ;DO OLD UPDATE INTERRUPT

MOV CX,0040H ;GET SEGMENT OF DOS TABLE

MOV DS,CX ;PUT IN DS

MOV CX,CS:TICKS ;GET TICK COUNT

INC CX ;INCREMENT IT

CMP CX,20 ;01F4H ;HAS A MINUTE GONE BY?

JB NO_MINUTE ;NO, MOVE ON

CALL UPDATE ;YES, UPDATE CLOCK AND

MOV CX,0 ; RESET TICK COUNTER

NO_MINUTE:

MOV CS:TICKS,CX ;SAVE UPDATED TICK COUNT

MOV CX,0B000H ;GET VIDEO SEGMENT

MOV ES,CX ;PUT IN ES

Page 15: Assembly language

MOV DX,CS:CRT_PORT ;GET CRT STATUS PORT ADDR

MOV DI,WORD PTR CS:SCR_OFF ;GET SCREEN BUFFER OFFSET

LEA SI,CS:TIME ;GET DOS TIME

MOV CX,16 ;SET UP TO MOVE 10 BYTES

CLI ;DISABLE OTHER INTERRUPTS

WAIT1: IN AL,DX ;READ CRT STATUS

TEST AL,1 ;CHECK FOR VERTICAL RETRACE

JNZ WAIT1 ;WAIT FOR RETRACE LOW

MOV AH,CS:[SI] ;GET FIRST BYTE TO MOVE

WAIT2: IN AL,DX ;GET CRT STATUS

TEST AL,1 ;CHECK FOR VERTICAL RETRACE

JZ WAIT2 ;WAIT FOR RETRACE HIGH

MOV ES:[DI],AH ;MOVE BYTE TO SCREEN

INC DI ;INCREMENT INDEX

INC SI

LOOP WAIT1 ;MOVE NEXT BYTE

STI ;ENABLE INTERRUPTS

POP ES ;RESTORE REGISTERS

POP DS

POP SI

POP DI

POP CX

POP AX

IRET ;RETURN FROM INTERRUPT

Page 16: Assembly language

CLK ENDP

UPDATE PROC NEAR

PUSH AX ;SAVE REGISTERS

PUSH BX

PUSH CX

PUSH DX

PUSH DS

MOV AX,0040H ;GET ADDRESS OF DOS TABLE

MOV DS,AX ;PUT IN DS

MOV AX,TIME_HI ;GET HIGH BYTE OF DOS TIME

mov flag,0 ;am flag

HOUR: CMP AX,0CH ;CONVERT TO HOURS

JLE H1

mov flag,1 ;set to pm

SUB AX,0CH

JMP HOUR

H1: AAM ;CONVERT TO ASCII

ADD AX,3030H

LEA BX,CS:TIME ;GET ADDRESS OF TIME AREA

MOV CS:[BX],AH ;SAVE HOURS FIRST DIGIT

MOV CS:[BX+2],AL ;SAVE HOURS SECOND DIGIT

MOV AX,TIME_LO ;GET DOS TIME LOW BYTE

MOV CX,8H ;CONVERT TO MINUTES

SHR AX,CL

Page 17: Assembly language

MOV DX,3CH

MUL DL

SHR AX,CL

AAM ;CONVERT TO ASCII

ADD AX,3030H

MOV CS:[BX+6],AH ;SAVE MINUTES FIRST DIGIT

MOV CS:[BX+8],AL ;SAVE MINUTES SECOND DIGIT

mov byte ptr cs:[bx+12],'a'

cmp flag,0 ;is it am?

jz goahead

mov byte ptr cs:[bx+12],'p'

goahead:

mov byte ptr cs:[bx+14],'m'

POP DS ;RESTORE REGISTERS

POP DX

POP CX

POP BX

POP AX

RET

UPDATE ENDP

SETUP: MOV AX,0 ;GET ADDRESS OF VECTOR TABLE

MOV DS,AX ;PUT IN DS

CLI ;DISABLE FURTHER INTERRUPTS

MOV AX,[VEC_IP] ;GET ADDRESS OF OLD UPDATE IP

Page 18: Assembly language

MOV CS:[INT_IP],AX ;SAVE IT

MOV AX,[VEC_CS] ;GET ADDRESS OF OLD UPDATE CS

MOV CS:[INT_CS],AX ;SAVE IT

MOV VEC_IP,OFFSET CLK_INT ;PUT ADDRESS OF CLK IN VECTOR IP

MOV VEC_CS,CS ;PUT CS OF CLK IN VECTOR CS

STI ;ENABLE INTERRUPTS

MOV AH,0FH ;READ VIDEO STATUS

INT 10H

SUB AH,8 ;SUBTRACT 8 CHAR TIME FROM NCOLS

SHL AH,1 ;MULTIPLY BY 2 FOR ATTRIBUTE

MOV CS:SCR_OFF,AH ;SAVE SCREEN TIME LOCATION

MOV WORD PTR CS:CRT_PORT,03BAH ;SAVE MONO STATUS PORT ADDR

TEST AL,4 ;CHECK FOR COLOR MONITOR

JNZ MONO ;IF MONO, MOVE ON

ADD WORD PTR CS:SCR_OFF,8000H ;ADD COLOR OFFSET TO TIME OFFSET

MOV WORD PTR CS:CRT_PORT,03DAH ;SAVE COLOR STATUS PORT ADDR

MONO: CALL UPDATE ;DO FIRST UPDATE & PRINT TIME

MOV DX,OFFSET SETUP ;GET END ADDRESS OF NEW INTERRUPT

INT 27H ;TERMINATE AND REMAIN RESIDENT

DB 117 DUP(0) ;FILLER

CODESEG ENDS

END CLK