RosettaCodeData/Task/Calendar---for-REAL-programmers/X86-Assembly/calendar---for-real-programmers.x86
2023-07-01 13:44:08 -04:00

187 lines
5.4 KiB
Text

.MODEL TINY
.CODE
.486
ORG 100H ;.COM FILES START HERE
YEAR EQU 1969 ;DISPLAY CALENDAR FOR SPECIFIED YEAR
START: MOV CX, 61 ;SPACE(61); TEXT(0, "[SNOOPY]"); CRLF(0)
CALL SPACE
MOV DX, OFFSET SNOOPY
CALL TEXT
MOV CL, 63 ;SPACE(63); INTOUT(0, YEAR); CRLF(0); CRLF(0)
CALL SPACE
MOV AX, YEAR
CALL INTOUT
CALL CRLF
CALL CRLF
MOV DI, 1 ;FOR MONTH:= 1 TO 12 DO DI=MONTH
L22: XOR SI, SI ; FOR COL:= 0 TO 6-1 DO SI=COL
L23: MOV CL, 5 ; SPACE(5)
CALL SPACE
MOV DX, DI ; TEXT(0, MONAME(MONTH+COL-1)); SPACE(7);
DEC DX ; DX:= (MONTH+COL-1)*10+MONAME
ADD DX, SI
IMUL DX, 10
ADD DX, OFFSET MONAME
CALL TEXT
MOV CL, 7
CALL SPACE
CMP SI, 5 ; IF COL<5 THEN SPACE(1);
JGE L24
MOV CL, 1
CALL SPACE
INC SI
JMP L23
L24: CALL CRLF
MOV SI, 6 ; FOR COL:= 0 TO 6-1 DO
L25: MOV DX, OFFSET SUMO ; TEXT(0, "SU MO TU WE TH FR SA");
CALL TEXT
DEC SI ; IF COL<5 THEN SPACE(2);
JE L27
MOV CL, 2
CALL SPACE
JMP L25
L27: CALL CRLF
XOR SI, SI ;FOR COL:= 0 TO 6-1 DO
L28: MOV BX, DI ;DAY OF FIRST SUNDAY OF MONTH (CAN BE NEGATIVE)
ADD BX, SI ;DAY(COL):= 1 - WEEKDAY(YEAR, MONTH+COL, 1);
MOV BP, YEAR
;DAY OF WEEK FOR FIRST DAY OF THE MONTH (0=SUN 1=MON..6=SAT)
CMP BL, 2 ;IF MONTH<=2 THEN
JG L3
ADD BL, 12 ; MONTH:= MONTH+12;
DEC BP ; YEAR:= YEAR-1;
L3:
;REM((1-1 + (MONTH+1)*26/10 + YEAR + YEAR/4 + YEAR/100*6 + YEAR/400)/7)
INC BX ;MONTH
IMUL AX, BX, 26
MOV CL, 10
CWD
IDIV CX
MOV BX, AX
MOV AX, BP ;YEAR
ADD BX, AX
SHR AX, 2
ADD BX, AX
MOV CL, 25
CWD
IDIV CX
IMUL DX, AX, 6 ;YEAR/100*6
ADD BX, DX
SHR AX, 2 ;YEAR/400
ADD AX, BX
MOV CL, 7
CWD
IDIV CX
NEG DX
INC DX
MOV [SI+DAY], DL ;COL+DAY
INC SI
CMP SI, 5
JLE L28
MOV BP, 6 ;FOR LINE:= 0 TO 6-1 DO BP=LINE
L29: XOR SI, SI ; FOR COL:= 0 TO 6-1 DO SI=COL
L30: MOV BX, DI ; DAYMAX:= DAYS(MONTH+COL);
MOV BL, [BX+SI+DAYS]
;IF MONTH+COL=2 & (REM(YEAR/4)=0 & REM(YEAR/100)#0 ! REM(YEAR/400)=0) THEN
MOV AX, DI ;MONTH
ADD AX, SI
CMP AL, 2
JNE L32
MOV AX, YEAR
TEST AL, 03H
JNE L32
MOV CL,100
CWD
IDIV CX
TEST DX, DX
JNE L31
TEST AL, 03H
JNE L32
L31: INC BX ;IF FEBRUARY AND LEAP YEAR THEN ADD A DAY
L32:
MOV DX, 7 ;FOR WEEKDAY:= 0 TO 7-1 DO
L33: MOVZX AX, [SI+DAY] ; IF DAY(COL)>=1 & DAY(COL)<=DAYMAX THEN
CMP AL, 1
JL L34
CMP AL, BL
JG L34
CALL INTOUT ; INTOUT(0, DAY(COL));
CMP AL, 10 ; IF DAY(COL)<10 THEN SPACE(1); LEFT JUSTIFY
JGE L36
MOV CL, 1
CALL SPACE
JMP L36
L34: MOV CL, 2 ; ELSE SPACE(2);
CALL SPACE ; SUPPRESS OUT OF RANGE DAYS
L36: MOV CL, 1 ; SPACE(1);
CALL SPACE
INC BYTE PTR [SI+DAY] ; DAY(COL):= DAY(COL)+1;
DEC DX ;NEXT WEEKDAY
JNE L33
CMP SI, 5 ;IF COL<5 THEN SPACE(1);
JGE L37
MOV CL, 1
CALL SPACE
INC SI
JMP L30
L37: CALL CRLF
DEC BP ;NEXT LINE DOWN
JNE L29
CALL CRLF
ADD DI, 6 ;NEXT 6 MONTHS
CMP DI, 12
JLE L22
RET
;DISPLAY POSITIVE INTEGER IN AX
INTOUT: PUSHA
MOV BX, 10
XOR CX, CX
NO10: CWD
IDIV BX
PUSH DX
INC CX
TEST AX, AX
JNE NO10
NO20: MOV AH, 02H
POP DX
ADD DL, '0'
INT 21H
LOOP NO20
POPA
RET
;DISPLAY CX SPACE CHARACTERS
SPACE: PUSHA
SP10: MOV AH, 02H
MOV DL, 20H
INT 21H
LOOP SP10
POPA
RET
;START A NEW LINE
CRLF: MOV DX, OFFSET LCRLF
;DISPLAY STRING AT DX
TEXT: MOV AH, 09H
INT 21H
RET
SNOOPY DB "[SNOOPY]"
LCRLF DB 0DH, 0AH, '$'
MONAME DB " JANUARY $ FEBRUARY$ MARCH $ APRIL $ MAY $ JUNE $"
DB " JULY $ AUGUST $SEPTEMBER$ OCTOBER$ NOVEMBER$ DECEMBER$"
SUMO DB "SU MO TU WE TH FR SA$"
DAYS DB 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
DAY DB ?, ?, ?, ?, ?, ?
END START