Question

I have been tasked with writing a NASM program that gets the day of the week for the first day of the next month. As an example: If today is June 4, then the program should say something like:

July 1st is a Thursday.

I am using the mktime function as well as a few other time/date functions. Here is my code:

extern time
extern localtime
extern exit
extern printf
extern mktime
extern ctime

global main

section .data

sSun: db "Sunday", 0
sMon: db "Monday", 0
sTue: db "Tuesday", 0
sWed: db "Wednesday", 0
sThu: db "Thursday", 0
sFri: db "Friday", 0
sSat: db "Saturday", 0

format_1: db "%d", 10, 0
string: db "%s", 10, 0

section .bss
timestamp: resd 1
tmstruct: resd 1

section .text
main:
pusha

push dword 0       ; fetch the timestamp
call time
add esp, 4
mov [timestamp], eax

push timestamp
call localtime
add esp, 4

;change the localtime struct to indicate first day of next month.

;seconds, minutes, hours, day of month from 1.
mov [eax], dword 0
mov [eax + 4], dword 0
mov [eax + 8], dword 0
mov [eax + 12], dword 1
;get month # from 0, to ecx.
mov ecx, [eax + 16]
cmp ecx, 11
jne notDecember

;its december. Set date to January of next year.
mov [eax + 16], dword 0
mov ecx, [eax + 20]
inc ecx
mov [eax + 20], ecx
jmp convertDate

notDecember:

;its not december, just move up the month by 1.
mov ecx, [eax + 16]
inc ecx
mov [eax + 16], ecx

convertDate:
mov [tmstruct], eax

;make a timestamp
;push tmstruct <-- Wrong
push dword [tmstruct] ; <-- Right
call mktime
add esp, 4

;move timestamp
mov [timestamp], eax

;make a new tm struct
push timestamp
call localtime
add esp, 4

;now we have the correct date, check the day of the week
mov ecx, [eax + 24]
push ecx ;<--- preserve this value or c function calls will trash it!

;do a ctime call
;push dword eax <-- Wrong
push timestamp ; <-- Right
call ctime
add esp, 4
push dword eax
push string
call printf
add esp, 8

pop ecx ;<--- pop preserved value!
push dword ecx
call dayOfWeek

popa
call exit


dayOfWeek:

cmp [esp + 4], dword 0
je pSun

cmp [esp + 4], dword 1
je pMon

cmp [esp + 4], dword 2
je pTue

cmp [esp + 4], dword 3
je pWed

cmp [esp + 4], dword 4
je pThu

cmp [esp + 4], dword 5
je pFri

cmp [esp + 4], dword 6
je pSat

push dword esp
push format_1
call printf
add esp, 8
push format_1
jmp endDow



pSun:
push sSun
jmp endDow

pMon:
push sMon
jmp endDow

pTue:
push sTue
jmp endDow

pWed:
push sWed
jmp endDow

pThu:
push sThu
jmp endDow

pFri:
push sFri
jmp endDow

pSat:
push sSat
jmp endDow

endDow:
push string
call printf
add esp, 8
ret 4

Basically, i am told that "The mktime function ignores the specified contents of the structure members tm_wday and tm_yday..." (from localtime tm struct) "....and recomputes them from the other information in the broken-down time structure."

Seeing this as the case, my plan was to create a tm structure for the current time, and simply modify all its elements to point to the first second of the first day of the next month, then use mktime on that. However, you will see that the program outputs the "hijacked" struct as "Wed Dec 31 18:00:59 1969", but then i even print out the day of the week from THAT and i get sunday. What have i done to go so wrong here?

Was it helpful?

Solution 2

It seems i made a mistake in passing a value. Also, some of the c function calls seem to want to trash my values in the registers! Changes needed to run the code properly are commented with arrows.

OTHER TIPS

Ok, I took the C Sample mktime and modified it to do what you want:

extern printf, time, mktime, exit, localtime, scanf,strftime
global main
;~ int    tm_sec   Seconds [0,60]. 
;~ int    tm_min   Minutes [0,59]. 
;~ int    tm_hour  Hour [0,23]. 
;~ int    tm_mday  Day of month [1,31]. 
;~ int    tm_mon   Month of year [0,11]. 
;~ int    tm_year  Years since 1900. 
;~ int    tm_wday  Day of week [0,6] (Sunday =0). 
;~ int    tm_yday  Day of year [0,365]. 
;~ int    tm_isdst Daylight Savings flag. 

%define tm_sec 0
%define tm_min 4
%define tm_hour 8
%define tm_mday 12
%define tm_mon 16
%define tm_year 20
%define tm_wday 24
%define tm_yday 28
%define tm_isdst 32


section .bss
timeinfo    resd    1
rawtime     resd    1
lpszBuffer  resb    80

section .data
fmtdate     db  "%B %d %Y", 0

Sun         db  "Sunday", 0
Mon         db  "Monday", 0
Tue         db  "Tuesday", 0
Wed         db  "Wednsday", 0
Thu         db  "Thursday", 0
Fri         db  "Friday", 0
Sat         db  "Saturday", 0
WeekDay     dd  Sun, Mon, Tue, Wed, Thu, Fri, Sat

szThatDay   db  "%s is a %s", 10, 0

section .text
main: 

    ;~ Get todays date
    push    rawtime
    call    time 
    add     esp, 4 * 1

    push    rawtime
    call    localtime
    add     esp, 4 * 1

    mov     dword [timeinfo], eax

    ;~ Get current month and add one
    mov     edx, dword [eax + tm_mon] 
    inc     edx 
    ;~ move updated month back to structure 
    mov     dword [eax + tm_mon], edx

    ;~ set day to the first
    mov     dword [eax + tm_mday], 1 

    push    dword [timeinfo]
    call    mktime
    add     esp, 4 * 1

    push    dword [timeinfo]
    push    fmtdate
    push    80
    push    lpszBuffer
    call    strftime
    add     esp, 4 * 4

    mov     eax, dword [timeinfo]
    mov     eax, dword [eax + tm_wday]
    mov     ecx, dword [WeekDay + 4 * eax]
    push    ecx
    push    lpszBuffer
    push    szThatDay 
    call    printf
    add     esp, 4 * 3

    call    exit

Then to test, I displayed current date and ran the program which then showed the day of the week the 1st is of next month. I then changed the system clock and reran the test 2 more times. Test also worked under Windows.

enter image description here

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top