I am trying to write a program that displays the day of the week for any day, month and year entered for any year between 1901 and 2099. I got through what i thought would be the hard part, but now I have been trying to get the output right for an hour. I want it to say something like "March 25, 1982 was a Tuesday" or whatever it was, but I can't seem to get the contents of the array read. I am having trouble because I need to load it into DI to display, but my array is a byte array. I tried to make it a word array, but I get a message saying it is not supported by my CPU.
;===================================================================
EXTERN GETDEC$:FAR
EXTERN NEWLINE:FAR
EXTERN PUTSTRNG:FAR
EXTERN PUTDEC$:FAR
EXTERN PUTSTRNG:FAR
;===================================================================
INCLUDE PCMAC.INC
.MODEL SMALL
.586
.STACK 512
.DATA
GETMONTH DB 'Enter the month number '
GETDAY DB 'Enter the day '
GETYEAR DB 'Enter the year '
ERRORMESSAGE DB 'Invalid! Please re-enter '
DAYSINMONTHS DW 31,28,31,30,31,30,31,31,30,31,30,31
MONTHSOFFSET DB 0,3,3,6,1,4,6,2,5,0,3,5
MONTH DW ?
DAY DW ?
YEAR DW ?
DIFYEARS Dw 0
DAYS DW 0
X DB 0
MONTHS DB 'January '
DB 'February '
DB 'March '
DB 'April '
DB 'May '
DB 'June '
DB 'July '
DB 'August '
DB 'September '
DB 'October '
DB 'November '
DB 'December '
DAYSOFWEEK DB 'Tuesday Wednesday Thursday Friday Saturday Sunday Monday '
;---------------------------------
.CODE
ARREX PROC
MOV AX,DGROUP ;SET DS-REGISTER TO POINT TO
MOV DS,AX ;DATA SEGMENT
MOV ES,AX ;AND ES ALS
...................
;====this is the problem area
MOV AX, MONTH
MOV BX, 10
IMUL BX
MOV DI, OFFSET MONTHS + AH
ADD DI, AX
MOV CX, 10
CALL PUTSTRNG
.EXIT
MOV AX, 4C00H
INT 21H
ARREX ENDP
END ARREX
MOV DI, OFFSET MONTHS
ADD DI, AX
Your month strings are 11 bytes instead of the 10 bytes that your code appears to expect. After I corrected that I had to comment out the JG ERROR after the days in month check to get past the check (it seems to always fail). And after I replaced:
MOV DI, OFFSET MONTHS + AH
With:
MOV DI, OFFSET MONTHS
Then the code would display the correct month, but when I added code to display the day of the week the value was off. Your leap year check appears to be working, but I don't understand the JNE ERROR. A leap year check will allow you to know whether February has 28 or 29 days, or whether the year has 365 or 366 days, but leap year or not there is no error. In the days in month check you are using IMUL to multiple by 2. For multiplying by a power of 2 it's better to use a SHL.
The only problem I have now is with the check for the day entered exceeding the number of days in the month (designated 'days in month check'.) I can't see why it isn't working:
;===================================================================
EXTERN GETDEC$:FAR
EXTERN NEWLINE:FAR
EXTERN PUTSTRNG:FAR
EXTERN PUTDEC$:FAR
EXTERN PUTSTRNG:FAR
;===================================================================
INCLUDE PCMAC.INC
.MODEL SMALL
.586
.STACK 512
.DATA
GETMONTH DB 'Enter the month number '
GETDAY DB 'Enter the day '
GETYEAR DB 'Enter the year '
ERRORMESSAGE DB 'Invalid! Please re-enter '
DAYSINMONTHS DW 31,28,31,30,31,30,31,31,30,31,30,31
DAYSINLEAPMONTHS DW 31,29,31,30,31,30,31,31,30,31,30,31
MONTHSOFFSET DB 0,3,3,6,1,4,6,2,5,0,3,5
LEAPMONTHSOFFSET DB 0,3,4,0,2,5,0,3,6,1,4,6
MONTH DW ?
DAY DW ?
YEAR DW ?
DIFYEARS Dw 0
DAYS DW 0
X DB 0
MONTHS DB 'January February March April May June July August September October November December '
DAYSOFWEEK DB 'Tuesday Wednesday Thursday Friday Saturday Sunday Monday '
SPACES DB ' '
WAS DB 'was a '
;---------------------------------
.CODE
ARREX PROC
MOV AX,DGROUP ;SET DS-REGISTER TO POINT TO
MOV DS,AX ;DATA SEGMENT
MOV ES,AX ;AND ES ALSO
;---------input
JMP BEGIN
ERROR:
MOV DI, OFFSET ERRORMESSAGE
MOV CX, SIZEOF ERRORMESSAGE
CALL NEWLINE
CALL PUTSTRNG
CALL NEWLINE
BEGIN:
MOV DI, OFFSET GETMONTH
MOV CX, SIZEOF GETMONTH
CALL NEWLINE
CALL PUTSTRNG
CALL GETDEC$ ;get month number
CMP AX, 13
JGE ERROR
DEC AX
MOV MONTH, AX
MOV DI, OFFSET GETYEAR ; GET YEAR
MOV CX, SIZEOF GETYEAR
CALL NEWLINE
CALL PUTSTRNG
CALL GETDEC$
CMP AX, 3000
JGE ERROR
CMP AX, 1900
JLE ERROR
MOV YEAR, AX
MOV DI, OFFSET GETDAY
MOV CX, SIZEOF GETDAY
CALL NEWLINE
CALL PUTSTRNG
CALL GETDEC$
MOV DAY, AX
MOV AX, MONTH
SHL AX, 1
MOV BX, [DAYSINMONTHS + AX]; DAYS IN MONTH CHECK
MOV AX, DAY
CMP AX, BX
JG ERROR
In 16-bit code, when using 16-bit registers to specify indirect memory operands you are restricted to using a base register (BX or BP), an index register (DI or SI), or one of each. These statements violate that restriction:
MOV BX, [DAYSINLEAPMONTHS +AX]
MOV BX, [DAYSINMONTHS + AX]
I'm not sure why ML is not catching the error. It will catch the error for the following two equivalent syntaxes:
MOV BX, [AX + DAYSINMONTHS]
MOV BX, DAYSINMONTHS [AX]
And return error A2031: must be index or base register
To fix the problem, you can either change the indirect memory operands to use a 16-bit base or index register, or you can use a 32-bit register, in which case any of the 8 general-purpose registers will work.
I see! It is working now. I had no idea. Not only no error message, but no mention of that in the chapter on arrays in my textbook.
Thanks everyone!
Hi Veronica,
did you try to display 29th in leap year ?
for example: Feb.29th 1980 ... i had trouble with that ...
Hi-
I had 2 arrays of days in months, 1 for normal and 1 for leap years. Then I made a leap year check first to dictate which arrays to use.
Quote from: BogdanOntanu on November 10, 2009, 07:20:10 AM
MOV DI, OFFSET MONTHS
ADD DI, AX
i make it so
LEA DI,MONTHS
ADD DI,AX
Quote from: veronicak5678 on November 11, 2009, 05:50:30 AM
I see! It is working now. I had no idea. Not only no error message, but no mention of that in the chapter on arrays in my textbook.
Thanks everyone!
I have idea for you:
Add array of string offsets and your code will free from length of string:
m1 byte 'jan...',0
m2 byte 'feb..',0
...
mofstbl label word
m1ofs word m1
m2ofs word m2
...
lea SI,mofstbl
mov BX,index_of_month
shl BX,1
mov bx,[SI+BX] ; now bx is ofs of month name string