NCurses Countdown to New Years Day
For those less graphically inclined, I also wrote a different version of the app experimenting with the ncurses TUI library (text based library), used for interactive text console apps. Not as exciting, but I wanted to learn another aspect of programming, by starting at the basics.
#include <ncurses.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
int main() {
initscr();
curs_set(0);
int max_x, max_y;
getmaxyx(stdscr, max_y, max_x);
struct tm nyd = { 0 }; /* inits struct members to 0 */
nyd.tm_year = 2025-1900;
nyd.tm_mday = 1;
time_t nyd_time = mktime(&nyd);
while (true) {
time_t diff = difftime(nyd_time, time(NULL));
char buf[80];
snprintf(buf, 80, "%3d %17s", (int) diff/86400, "days");
mvprintw(max_y/2-2, (max_x-strlen(buf))/2, "%s", buf);
snprintf(buf, 80, "%3d %17s", (int) (diff % 86400) / 3600, "hours");
mvprintw(max_y/2-1, (max_x-strlen(buf))/2, "%s", buf);
snprintf(buf, 80, "%3d %17s", (int) (diff % 3600) / 60, "minutes" );
mvprintw(max_y/2, (max_x-strlen(buf))/2, "%s", buf);
snprintf(buf, 80, "%3d %17s", (int) diff % 60, "seconds");
mvprintw(max_y/2+1, (max_x-strlen(buf))/2, "%s", buf);
attron(A_BOLD);
strncpy(buf, "New Years Day 2025!", 80);
mvprintw(max_y/2+3, (max_x-strlen(buf))/2, "%s", buf);
attroff(A_BOLD);
refresh();
sleep(1);
}
endwin();
return 0;
}

As I’ve been sick with the COVID, I also have been carefully studying the x86 Assembler code generated by the compiler. It’s quite fascinating.
0000000000401206 <main>:
#include <ncurses.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
int main() {
401206: 55 push %rbp
401207: 48 89 e5 mov %rsp,%rbp
40120a: 53 push %rbx
40120b: 48 81 ec a8 00 00 00 sub $0xa8,%rsp
initscr();
401212: e8 79 fe ff ff call 401090 <initscr@plt>
curs_set(0);
401217: bf 00 00 00 00 mov $0x0,%edi
40121c: e8 cf fe ff ff call 4010f0 <curs_set@plt>
int max_x, max_y;
getmaxyx(stdscr, max_y, max_x);
401221: 48 8b 05 58 2e 00 00 mov 0x2e58(%rip),%rax # 404080 <stdscr@@Base>
401228: 48 89 c7 mov %rax,%rdi
40122b: e8 20 fe ff ff call 401050 <getmaxy@plt>
401230: 89 45 ec mov %eax,-0x14(%rbp)
401233: 48 8b 05 46 2e 00 00 mov 0x2e46(%rip),%rax # 404080 <stdscr@@Base>
40123a: 48 89 c7 mov %rax,%rdi
40123d: e8 9e fe ff ff call 4010e0 <getmaxx@plt>
401242: 89 45 e8 mov %eax,-0x18(%rbp)
struct tm nyd = { 0 }; /* inits struct members to 0 */
401245: 66 0f ef c0 pxor %xmm0,%xmm0
401249: 0f 29 45 a0 movaps %xmm0,-0x60(%rbp)
40124d: 0f 29 45 b0 movaps %xmm0,-0x50(%rbp)
401251: 0f 29 45 c0 movaps %xmm0,-0x40(%rbp)
401255: 66 0f d6 45 d0 movq %xmm0,-0x30(%rbp)
nyd.tm_year = 2025-1900;
40125a: c7 45 b4 7d 00 00 00 movl $0x7d,-0x4c(%rbp)
nyd.tm_mday = 1;
401261: c7 45 ac 01 00 00 00 movl $0x1,-0x54(%rbp)
time_t nyd_time = mktime(&nyd);
401268: 48 8d 45 a0 lea -0x60(%rbp),%rax
40126c: 48 89 c7 mov %rax,%rdi
40126f: e8 5c fe ff ff call 4010d0 <mktime@plt>
401274: 48 89 45 e0 mov %rax,-0x20(%rbp)
while (true) {
time_t diff = difftime(nyd_time, time(NULL));
401278: bf 00 00 00 00 mov $0x0,%edi
40127d: e8 3e fe ff ff call 4010c0 <time@plt>
401282: 48 89 c2 mov %rax,%rdx
401285: 48 8b 45 e0 mov -0x20(%rbp),%rax
401289: 48 89 d6 mov %rdx,%rsi
40128c: 48 89 c7 mov %rax,%rdi
40128f: e8 ec fd ff ff call 401080 <difftime@plt>
401294: f2 48 0f 2c c0 cvttsd2si %xmm0,%rax
401299: 48 89 45 d8 mov %rax,-0x28(%rbp)
char buf[80];
snprintf(buf, 80, "%3d %17s", (int) diff/86400, "days");
40129d: 48 8b 45 d8 mov -0x28(%rbp),%rax
4012a1: 48 63 d0 movslq %eax,%rdx
4012a4: 48 69 d2 07 45 2e c2 imul $0xffffffffc22e4507,%rdx,%rdx
4012ab: 48 c1 ea 20 shr $0x20,%rdx
4012af: 01 c2 add %eax,%edx
4012b1: c1 fa 10 sar $0x10,%edx
4012b4: c1 f8 1f sar $0x1f,%eax
4012b7: 29 c2 sub %eax,%edx
4012b9: 48 8d 85 50 ff ff ff lea -0xb0(%rbp),%rax
4012c0: 41 b8 10 20 40 00 mov $0x402010,%r8d
4012c6: 89 d1 mov %edx,%ecx
4012c8: ba 15 20 40 00 mov $0x402015,%edx
4012cd: be 50 00 00 00 mov $0x50,%esi
4012d2: 48 89 c7 mov %rax,%rdi
4012d5: b8 00 00 00 00 mov $0x0,%eax
4012da: e8 c1 fd ff ff call 4010a0 <snprintf@plt>
mvprintw(max_y/2-2, (max_x-strlen(buf))/2, "%s", buf);
4012df: 8b 45 e8 mov -0x18(%rbp),%eax
4012e2: 48 63 d8 movslq %eax,%rbx
4012e5: 48 8d 85 50 ff ff ff lea -0xb0(%rbp),%rax
4012ec: 48 89 c7 mov %rax,%rdi
4012ef: e8 6c fd ff ff call 401060 <strlen@plt>
4012f4: 48 29 c3 sub %rax,%rbx
4012f7: 48 89 da mov %rbx,%rdx
4012fa: 48 89 d0 mov %rdx,%rax
4012fd: 48 d1 e8 shr $1,%rax
401300: 89 c6 mov %eax,%esi
401302: 8b 45 ec mov -0x14(%rbp),%eax
401305: 89 c2 mov %eax,%edx
401307: c1 ea 1f shr $0x1f,%edx
40130a: 01 d0 add %edx,%eax
40130c: d1 f8 sar $1,%eax
40130e: 8d 78 fe lea -0x2(%rax),%edi
401311: 48 8d 85 50 ff ff ff lea -0xb0(%rbp),%rax
401318: 48 89 c1 mov %rax,%rcx
40131b: ba 1e 20 40 00 mov $0x40201e,%edx
401320: b8 00 00 00 00 mov $0x0,%eax
401325: e8 e6 fd ff ff call 401110 <mvprintw@plt>
snprintf(buf, 80, "%3d %17s", (int) (diff % 86400) / 3600, "hours");
40132a: 48 8b 4d d8 mov -0x28(%rbp),%rcx
40132e: 48 ba 57 29 51 ce a0 movabs $0x1845c8a0ce512957,%rdx
401335: c8 45 18
401338: 48 89 c8 mov %rcx,%rax
40133b: 48 f7 ea imul %rdx
40133e: 48 89 d0 mov %rdx,%rax
401341: 48 c1 f8 0d sar $0xd,%rax
401345: 48 89 ca mov %rcx,%rdx
401348: 48 c1 fa 3f sar $0x3f,%rdx
40134c: 48 29 d0 sub %rdx,%rax
40134f: 48 69 d0 80 51 01 00 imul $0x15180,%rax,%rdx
401356: 48 89 c8 mov %rcx,%rax
401359: 48 29 d0 sub %rdx,%rax
40135c: 48 63 d0 movslq %eax,%rdx
40135f: 48 69 d2 c5 b3 a2 91 imul $0xffffffff91a2b3c5,%rdx,%rdx
401366: 48 c1 ea 20 shr $0x20,%rdx
40136a: 01 c2 add %eax,%edx
40136c: c1 fa 0b sar $0xb,%edx
40136f: c1 f8 1f sar $0x1f,%eax
401372: 29 c2 sub %eax,%edx
401374: 48 8d 85 50 ff ff ff lea -0xb0(%rbp),%rax
40137b: 41 b8 21 20 40 00 mov $0x402021,%r8d
401381: 89 d1 mov %edx,%ecx
401383: ba 15 20 40 00 mov $0x402015,%edx
401388: be 50 00 00 00 mov $0x50,%esi
40138d: 48 89 c7 mov %rax,%rdi
401390: b8 00 00 00 00 mov $0x0,%eax
401395: e8 06 fd ff ff call 4010a0 <snprintf@plt>
mvprintw(max_y/2-1, (max_x-strlen(buf))/2, "%s", buf);
40139a: 8b 45 e8 mov -0x18(%rbp),%eax
40139d: 48 63 d8 movslq %eax,%rbx
4013a0: 48 8d 85 50 ff ff ff lea -0xb0(%rbp),%rax
4013a7: 48 89 c7 mov %rax,%rdi
4013aa: e8 b1 fc ff ff call 401060 <strlen@plt>
4013af: 48 29 c3 sub %rax,%rbx
4013b2: 48 89 da mov %rbx,%rdx
4013b5: 48 89 d0 mov %rdx,%rax
4013b8: 48 d1 e8 shr $1,%rax
4013bb: 89 c6 mov %eax,%esi
4013bd: 8b 45 ec mov -0x14(%rbp),%eax
4013c0: 89 c2 mov %eax,%edx
4013c2: c1 ea 1f shr $0x1f,%edx
4013c5: 01 d0 add %edx,%eax
4013c7: d1 f8 sar $1,%eax
4013c9: 8d 78 ff lea -0x1(%rax),%edi
4013cc: 48 8d 85 50 ff ff ff lea -0xb0(%rbp),%rax
4013d3: 48 89 c1 mov %rax,%rcx
4013d6: ba 1e 20 40 00 mov $0x40201e,%edx
4013db: b8 00 00 00 00 mov $0x0,%eax
4013e0: e8 2b fd ff ff call 401110 <mvprintw@plt>
snprintf(buf, 80, "%3d %17s", (int) (diff % 3600) / 60, "minutes" );
4013e5: 48 8b 4d d8 mov -0x28(%rbp),%rcx
4013e9: 48 ba 05 7c f3 6a e2 movabs $0x48d159e26af37c05,%rdx
4013f0: 59 d1 48
4013f3: 48 89 c8 mov %rcx,%rax
4013f6: 48 f7 ea imul %rdx
4013f9: 48 89 d0 mov %rdx,%rax
4013fc: 48 c1 f8 0a sar $0xa,%rax
401400: 48 89 ca mov %rcx,%rdx
401403: 48 c1 fa 3f sar $0x3f,%rdx
401407: 48 29 d0 sub %rdx,%rax
40140a: 48 69 d0 10 0e 00 00 imul $0xe10,%rax,%rdx
401411: 48 89 c8 mov %rcx,%rax
401414: 48 29 d0 sub %rdx,%rax
401417: 48 63 d0 movslq %eax,%rdx
40141a: 48 69 d2 89 88 88 88 imul $0xffffffff88888889,%rdx,%rdx
401421: 48 c1 ea 20 shr $0x20,%rdx
401425: 01 c2 add %eax,%edx
401427: c1 fa 05 sar $0x5,%edx
40142a: c1 f8 1f sar $0x1f,%eax
40142d: 29 c2 sub %eax,%edx
40142f: 48 8d 85 50 ff ff ff lea -0xb0(%rbp),%rax
401436: 41 b8 27 20 40 00 mov $0x402027,%r8d
40143c: 89 d1 mov %edx,%ecx
40143e: ba 15 20 40 00 mov $0x402015,%edx
401443: be 50 00 00 00 mov $0x50,%esi
401448: 48 89 c7 mov %rax,%rdi
40144b: b8 00 00 00 00 mov $0x0,%eax
401450: e8 4b fc ff ff call 4010a0 <snprintf@plt>
mvprintw(max_y/2, (max_x-strlen(buf))/2, "%s", buf);
401455: 8b 45 e8 mov -0x18(%rbp),%eax
401458: 48 63 d8 movslq %eax,%rbx
40145b: 48 8d 85 50 ff ff ff lea -0xb0(%rbp),%rax
401462: 48 89 c7 mov %rax,%rdi
401465: e8 f6 fb ff ff call 401060 <strlen@plt>
40146a: 48 29 c3 sub %rax,%rbx
40146d: 48 89 da mov %rbx,%rdx
401470: 48 89 d0 mov %rdx,%rax
401473: 48 d1 e8 shr $1,%rax
401476: 89 c6 mov %eax,%esi
401478: 8b 45 ec mov -0x14(%rbp),%eax
40147b: 89 c2 mov %eax,%edx
40147d: c1 ea 1f shr $0x1f,%edx
401480: 01 d0 add %edx,%eax
401482: d1 f8 sar $1,%eax
401484: 89 c7 mov %eax,%edi
401486: 48 8d 85 50 ff ff ff lea -0xb0(%rbp),%rax
40148d: 48 89 c1 mov %rax,%rcx
401490: ba 1e 20 40 00 mov $0x40201e,%edx
401495: b8 00 00 00 00 mov $0x0,%eax
40149a: e8 71 fc ff ff call 401110 <mvprintw@plt>
snprintf(buf, 80, "%3d %17s", (int) diff % 60, "seconds");
40149f: 48 8b 45 d8 mov -0x28(%rbp),%rax
4014a3: 89 c2 mov %eax,%edx
4014a5: 48 63 c2 movslq %edx,%rax
4014a8: 48 69 c0 89 88 88 88 imul $0xffffffff88888889,%rax,%rax
4014af: 48 c1 e8 20 shr $0x20,%rax
4014b3: 01 d0 add %edx,%eax
4014b5: c1 f8 05 sar $0x5,%eax
4014b8: 89 d1 mov %edx,%ecx
4014ba: c1 f9 1f sar $0x1f,%ecx
4014bd: 29 c8 sub %ecx,%eax
4014bf: 6b c8 3c imul $0x3c,%eax,%ecx
4014c2: 89 d0 mov %edx,%eax
4014c4: 29 c8 sub %ecx,%eax
4014c6: 48 8d bd 50 ff ff ff lea -0xb0(%rbp),%rdi
4014cd: 41 b8 2f 20 40 00 mov $0x40202f,%r8d
4014d3: 89 c1 mov %eax,%ecx
4014d5: ba 15 20 40 00 mov $0x402015,%edx
4014da: be 50 00 00 00 mov $0x50,%esi
4014df: b8 00 00 00 00 mov $0x0,%eax
4014e4: e8 b7 fb ff ff call 4010a0 <snprintf@plt>
mvprintw(max_y/2+1, (max_x-strlen(buf))/2, "%s", buf);
4014e9: 8b 45 e8 mov -0x18(%rbp),%eax
4014ec: 48 63 d8 movslq %eax,%rbx
4014ef: 48 8d 85 50 ff ff ff lea -0xb0(%rbp),%rax
4014f6: 48 89 c7 mov %rax,%rdi
4014f9: e8 62 fb ff ff call 401060 <strlen@plt>
4014fe: 48 29 c3 sub %rax,%rbx
401501: 48 89 da mov %rbx,%rdx
401504: 48 89 d0 mov %rdx,%rax
401507: 48 d1 e8 shr $1,%rax
40150a: 89 c6 mov %eax,%esi
40150c: 8b 45 ec mov -0x14(%rbp),%eax
40150f: 89 c2 mov %eax,%edx
401511: c1 ea 1f shr $0x1f,%edx
401514: 01 d0 add %edx,%eax
401516: d1 f8 sar $1,%eax
401518: 8d 78 01 lea 0x1(%rax),%edi
40151b: 48 8d 85 50 ff ff ff lea -0xb0(%rbp),%rax
401522: 48 89 c1 mov %rax,%rcx
401525: ba 1e 20 40 00 mov $0x40201e,%edx
40152a: b8 00 00 00 00 mov $0x0,%eax
40152f: e8 dc fb ff ff call 401110 <mvprintw@plt>
attron(A_BOLD);
401534: 48 8b 05 45 2b 00 00 mov 0x2b45(%rip),%rax # 404080 <stdscr@@Base>
40153b: ba 00 00 00 00 mov $0x0,%edx
401540: be 00 00 20 00 mov $0x200000,%esi
401545: 48 89 c7 mov %rax,%rdi
401548: e8 f3 fa ff ff call 401040 <wattr_on@plt>
strncpy(buf, "New Years Day 2025!", 80);
40154d: 48 8d 85 50 ff ff ff lea -0xb0(%rbp),%rax
401554: ba 50 00 00 00 mov $0x50,%edx
401559: be 37 20 40 00 mov $0x402037,%esi
40155e: 48 89 c7 mov %rax,%rdi
401561: e8 ca fa ff ff call 401030 <strncpy@plt>
mvprintw(max_y/2+3, (max_x-strlen(buf))/2, "%s", buf);
401566: 8b 45 e8 mov -0x18(%rbp),%eax
401569: 48 63 d8 movslq %eax,%rbx
40156c: 48 8d 85 50 ff ff ff lea -0xb0(%rbp),%rax
401573: 48 89 c7 mov %rax,%rdi
401576: e8 e5 fa ff ff call 401060 <strlen@plt>
40157b: 48 29 c3 sub %rax,%rbx
40157e: 48 89 da mov %rbx,%rdx
401581: 48 89 d0 mov %rdx,%rax
401584: 48 d1 e8 shr $1,%rax
401587: 89 c6 mov %eax,%esi
401589: 8b 45 ec mov -0x14(%rbp),%eax
40158c: 89 c2 mov %eax,%edx
40158e: c1 ea 1f shr $0x1f,%edx
401591: 01 d0 add %edx,%eax
401593: d1 f8 sar $1,%eax
401595: 8d 78 03 lea 0x3(%rax),%edi
401598: 48 8d 85 50 ff ff ff lea -0xb0(%rbp),%rax
40159f: 48 89 c1 mov %rax,%rcx
4015a2: ba 1e 20 40 00 mov $0x40201e,%edx
4015a7: b8 00 00 00 00 mov $0x0,%eax
4015ac: e8 5f fb ff ff call 401110 <mvprintw@plt>
attroff(A_BOLD);
4015b1: 48 8b 05 c8 2a 00 00 mov 0x2ac8(%rip),%rax # 404080 <stdscr@@Base>
4015b8: ba 00 00 00 00 mov $0x0,%edx
4015bd: be 00 00 20 00 mov $0x200000,%esi
4015c2: 48 89 c7 mov %rax,%rdi
4015c5: e8 e6 fa ff ff call 4010b0 <wattr_off@plt>
refresh();
4015ca: 48 8b 05 af 2a 00 00 mov 0x2aaf(%rip),%rax # 404080 <stdscr@@Base>
4015d1: 48 89 c7 mov %rax,%rdi
4015d4: e8 97 fa ff ff call 401070 <wrefresh@plt>
sleep(1);
4015d9: bf 01 00 00 00 mov $0x1,%edi
4015de: e8 1d fb ff ff call 401100 <sleep@plt>
while (true) {
4015e3: 90 nop
4015e4: e9 8f fc ff ff jmp 401278 <main+0x72>


















