📄 date.asm
字号:
.moloop: mov dl, 7 shld edx, ebx, 2 ror ebx, 2 inc ecx sub eax, edx jge .moloop add eax, edx inc eax add edi, byte tmfmt.dy stosd xchg eax, ecx stosd;; The program retrieves from the stack the day of the year, the;; number of days since the Epoch, and the day of the week at the;; start of the Epoch, respectively. These are used to calculate the;; day of the week of January 1st of the current year. pop eax pop ebx sub eax, esi add eax, ebx mov bl, 7 cdq div ebx mov ecx, edx;; Using this, the program now determines the current week of the year;; according to three different measurements. The first uses Sunday as;; the start of the week, and a partial week at the beginning of the;; year is considered to be week zero. The second is the same, except;; that it uses Monday as the start of the week. xor eax, eax cmpxchg ecx, ebx lea eax, [esi + ecx] cdq div ebx stosd dec ecx jnz .mondaynot1st mov cl, bl.mondaynot1st: lea eax, [esi + ecx] cdq div ebx stosd;; Finally, the ISO-8601 week number uses Monday as the start of the;; week, and requires every week counted to be the full seven days. A;; partial week at the end of the year of less than four days is;; counted as week 1 of the following year; likewise, a partial week;; at the start of the year of less than four days is counted as week;; 52 or 53 of the previous year. In order to cover all possibilities,;; the program must examine the current day of the week, and whether;; the current year and/or the previous year was a leap year. Outside;; of these special cases, the ISO-8601 week number will either be;; equal to or one more than the value previously calculated. mov ebx, [byte edi + tmfmt.yr - tmfmt.wi] mov dl, 3 and dl, bl sub ecx, byte 4 adc al, 0 jnz .fullweek dec ebx mov al, 52 or ecx, ecx jz .add1stweek dec ecx jnz .wifound dec edx jnz .wifound.add1stweek: inc eax.fullweek: cmp al, 53 jnz .wifound cmp dl, 1 mov edx, esi sbb dl, 104 cmp dl, [byte edi + tmfmt.wd - tmfmt.wi] jle .wifound mov al, 1 inc ebx.wifound: stosd xchg eax, ebx stosd inc esi xchg eax, esi stosd;; All representable values have now been calculated. edi is changed;; to point to the output buffer. The program then proceeds to render;; the format string into buf by calling ftime. lea ebx, [byte edi - tmfmt.ce] mov esi, [byte ebx + fmt - tm] lea edi, [byte ebx + buf - tm] push edi call ftime.loop;; A newline is appended, the string is output to stdout, and the;; program exits. mov al, 10 stosb pop ecx mov edx, edi sub edx, ecx xor ebx, ebx lea eax, [byte ebx + 4] inc ebx int 0x80 xor eax, eax xchg eax, ebx int 0x80;; ftime formats the current time according to a format specification.;;;; input:;; ebx = pointer to the tm structure;; esi = pointer to the format string (relative to ebp, unless the;; function is entered at ftime.loop);; edi = output buffer;;;; output:;; edi = the position immediately following the output string;; eax, ecx, edx, and esi are alteredftime: add esi, ebp jmp short .loop;; Whenever a % character is encountered in the format string, the;; program scans for the character immediately following in the;; fmtchars array. If it is not found, the % is treated like any other;; character and copied into outbuf verbatim. The program returns when;; a NUL byte is found..nofmt: mov byte [edi], '%' inc edi.literal: stosb.loop: lodsb or al, al jz return cmp al, '%' jnz .literal cmp byte [esi], 0 jz .literal lodsb push edi mov edi, ebp push byte fmtcharcount pop ecx repnz scasb pop edi jnz .nofmt;; If the character is found, the value in ecx is used as an offset;; into three arrays. The fmtfuns array indicates which function in;; the funclist array to call in order to render the value. The;; fmtargs array indicates which field in tmfmt to load into eax;; before calling the function. Finally the fmtpars array provides a;; value, stored in both esi and edx, that is specific to the function;; called. push esi movzx eax, byte [byte ebp + fmtargs - fmtchars + ecx] mov eax, [ebx + eax] movzx esi, byte [byte ebp + fmtpars - fmtchars + ecx] mov edx, esi mov cl, [byte ebp + fmtfuns - fmtchars + ecx];; The chosen function is called and ftime continues on to the next;; character in the format string. call [byte ebp + funclist - fmtchars + ecx] pop esi jmp short .loop;; ftimelocale calls ftime for a format specification stored in the;; LC_TIME file.;;;; input:;; ebx = pointer to the tm structure;; edx = offset of the index of the format in the LC_TIME file;; edi = output buffer;;;; output:;; edi = the position immediately following the output string;; eax, ecx, edx, and esi are alteredftimelocale: mov esi, [byte ebx + localedata - tm] add esi, [esi + edx] jmp short ftime.loop;; itoa renders a number in decimal ASCII.;;;; input:;; eax = the number to render;; dl & 0F = the minimum width to display;; dl & F0 = the character to pad with on the leftitoa:;; First, the number is rendered as decimal ASCII in reverse, in a;; private buffer, using successive divisions by 10. lea esi, [byte ebx + itoabuf - tm + 16] push esi push edx push byte 10 pop ecx.loop: cdq div ecx add dl, '0' dec esi mov [esi], dl or eax, eax jnz .loop;; If the string created is shorter than the size given in the low;; nybble in edx, extra characters are first written to edi to pad out;; the field to the minimum required length. Then the number is copied;; from the private buffer and the function returns. pop eax mov cl, 0x0F and cl, al add ecx, esi sub ecx, [esp] jle .nopadding and al, 0xF0 rep stosb.nopadding: pop ecx sub ecx, esi rep movsbreturn: ret;; putlocalstr selects a string from a list stored in the LC_TIME file;; and copies it to an output buffer.;;;; input:;; eax = index of the string to copy;; edx = offset of the list of indexes in the LC_TIME fileputlocalestr: mov esi, [byte ebx + localedata - tm] add edx, esi add esi, [edx + eax*4].loop: lodsb stosb or al, al jnz .loop dec edi ret;; putstr simply copies a string from the tmfmt structure to an output;; buffer.putstr: add esi, ebx.loop: lodsb stosb or al, al jnz .loop dec edi ret;; putchar copies a single character to the output buffer.putchar: xchg eax, edx stosb ret;; read-only data;; The byte array of indexes into funclist, given the function for;; each format character.fmtfuns: db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; s S M H k d e m Y C db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; I l u w U W V G j y db 4, 4, 4, 4, 4, 4 ; a A h b B p db 8, 8, 8 ; c x X db 12, 12, 12 ; r D T db 16, 16 ; z Z db 20, 20, 20 ; t n %;; The byte array of offsets into tmfmt, indicating which field to use;; for each format. Formats after %p do not use a tmfmt field, and so;; the values for those formats are omitted.fmtargs: db tmfmt.ct, tmfmt.sc, tmfmt.mn, tmfmt.hr, tmfmt.hr db tmfmt.dy, tmfmt.dy, tmfmt.mo, tmfmt.yr, tmfmt.ce db tmfmt.hm, tmfmt.hm, tmfmt.w1, tmfmt.wd, tmfmt.ws db tmfmt.wm, tmfmt.wi, tmfmt.yi, tmfmt.yd, tmfmt.cy db tmfmt.wd, tmfmt.wd, tmfmt.mo, tmfmt.mo, tmfmt.mo db tmfmt.mr;; The default format displayed when none is supplied by the user.defaultfmt: db '%a %b %d %T %Z %Y';; The byte array of function-specific data for each format. This;; value is loaded in to edx and esi before calling the function. The;; values in the first two rows are for itoa, and provide a minimum;; field width and a padding character (either space or '0'). The;; values in the next two rows are for ftimelocale, and give an offset;; into the words memory to an array of pointers to strings. The fifth;; row, for ftimelocale, contains offsets relative to ebp to format;; strings. The sixth row, for putlocalestr, contains offsets relative;; to tmfmt to constant strings. The final row, for putchar, specifies;; literal characters.fmtpars: db 0, 0x32, 0x32, 0x32, 0x22, 0x32, 0x22, 0x32, 0, 0 db 0x32, 0x22, 0, 0, 0x32, 0x32, 0x32, 0, 0x33, 0x32 db 0x08, 0x24, 0x3C, 0x3C, 0x6C, 0xA0 db 0xA8, 0xAC, 0xB0 db percentr - fmtchars db percentD - fmtchars, percentT - fmtchars db tmfmt.zi, tmfmt.tz db 9, 10;; The complete list of format characters, in reverse from the;; corresponding values used in the three preceding byte arrays.fmtchars: db '%ntZzTDrXxcpBbhAayjGVWUwulICYmedkHMSs'fmtcharcount equ $ - fmtchars;; The list of different functions called to render a format.funclist: dd itoa, putlocalestr, ftimelocale, ftime, putstr, putchar;; The (incomplete) pathname of the localization file.lctimeprefix: db '/usr/share/locale/'lctimeprefixlen equ $ - lctimeprefixlctimesuffix equ $ - 1 db 'LC_TIME';; The format used to render the %D, %T, and %r formats.percentD: db '%m/%d/%y', 0percentT: db '%H:%M:%S', 0percentr: db '%I:%M:%S %p', 0;; The pathname of the time zone file.tzfilename: db '/etc/localtime', 0;; The "C" locale data.clocale equ $ - 8%define O(p) ((p) - origin) - (clocale - $$) dd O(ca0), O(ca1), O(ca2), O(ca3), O(ca4), O(ca5), O(ca6) dd O(cA0), O(cA1), O(cA2), O(cA3), O(cA4), O(cA5), O(cA6) dd O(cb00), O(cb01), O(cb02), O(cb03), O(cb04), O(cb05) dd O(cb06), O(cb07), O(cb08), O(cb09), O(cb10), O(cb11) dd O(cB00), O(cB01), O(cB02), O(cB03), O(cB04), O(cB05) dd O(cB06), O(cB07), O(cB08), O(cB09), O(cB10), O(cB11) dd O(cp0), O(cp1), O(cpc), O(percentD), O(percentT)cA0: db 'Sunday', 0cA1: db 'Monday', 0cA2: db 'Tuesday', 0cA3: db 'Wednesday', 0cA4: db 'Thursday', 0cA5: db 'Friday', 0cA6: db 'Saturday', 0cB00: db 'January', 0cB01: db 'February', 0cB02: db 'March', 0cB03: db 'April', 0cB04: db 'May', 0cB05: db 'June', 0cB06: db 'July', 0cB07: db 'August', 0cB08: db 'September', 0cB09: db 'October', 0cB10: db 'November', 0cB11: db 'December', 0cp0: db 'AM', 0cp1: db 'PM', 0cpc: db '%a %b %e %T %Y'filesize equ $ - $$ABSOLUTE origin + filesizeresb 1ALIGNB 4;; The remainder of the "C" locale data, generated at runtime.ca0: resb 4ca1: resb 4ca2: resb 4ca3: resb 4ca4: resb 4ca5: resb 4ca6: resb 4cb00: resb 4cb01: resb 4cb02: resb 4cb03: resb 4cb04: resb 4cb05: resb 4cb06: resb 4cb07: resb 4cb08: resb 4cb09: resb 4cb10: resb 4cb11: resb 4;; The tmfmt structure.tm: resb tmfmt_size;; The pointer to the top-level format string.fmt: resd 1;; The pointer to the localization file's contents.localedata: resd 1;; itoa's private temporary buffer.itoabuf: resb 16;; The output buffer that the formatting string is rendered into.buf: resb 8192memsize equ $ - origin
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -