News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

ARRAYS

Started by veronicak5678, November 10, 2009, 04:36:27 AM

Previous topic - Next topic

veronicak5678

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


BogdanOntanu


MOV DI, OFFSET MONTHS
ADD DI, AX
Ambition is a lame excuse for the ones not brave enough to be lazy.
http://www.oby.ro

MichaelW

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.
eschew obfuscation

veronicak5678

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


MichaelW

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.

eschew obfuscation

veronicak5678

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!

ilian007

Hi Veronica,

did you try to display 29th in leap year ?

for example:  Feb.29th 1980 ... i had trouble with that ...

veronicak5678

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.

Rockphorr

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

Strike while the iron is hot - Бей утюгом, пока он горячий

Rockphorr

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

Strike while the iron is hot - Бей утюгом, пока он горячий