📄 date.asm
字号:
;; date.asm: Copyright (C) 2001 by Brian Raiter, under the GNU General;; Public License. No warranty.;;;; Usage: date [-u] [=UTIME] [+FORMAT];;;; +FORMAT provides a format string to use to display the time. The;; special sequences recognized are:;;;; %a %A %b %B %c %C %d %D %e %G %h %H %I %j %k %l %m %M %n %p %r;; %s %S %t %T %u %U %V %w %W %x %X %y %Y %z %Z %%;;;; See date(1) and strftime(3) for the complete description of what;; each of these sequences displays.;;;; The -u option indicates that the time should be displayed in UTC,;; instead of the local time zone.;;;; =UTIME is a non-standard extension. It specifies a Unix time,;; given as the number of seconds since the start of 1970 UTC, to;; display instead of the current time.;;;; If the LANG environment variable is not set, or does not name an;; available locale, the internal "C" locale data is used instead.BITS 32;; The collection of values associated with the calendric;; representation of a time.STRUC tmfmt.ct: resd 1 ; C time (seconds since the Epoch).sc: resd 1 ; seconds.mn: resd 1 ; minutes.hr: resd 1 ; hours.yr: resd 1 ; year.hm: resd 1 ; hour of the meridian (1-12).mr: resd 1 ; meridian (0 for AM).wd: resd 1 ; day of the week (Sunday=0, Saturday=6).w1: resd 1 ; day of the week (Monday=1, Sunday=7).dy: resd 1 ; day of the month.mo: resd 1 ; month (one-based).ws: resd 1 ; week of the year (Sunday-based).wm: resd 1 ; week of the year (Monday-based).wi: resd 1 ; week of the year according to ISO 8601:1988.yi: resd 1 ; year for the week according to ISO 8601:1988.yd: resd 1 ; day of the year.ce: resd 1 ; century (zero-based).cy: resd 1 ; year of the century.zo: resd 1 ; time zone offset.zi: resb 6 ; time zone identifier.tz: resb 10 ; time zone nameENDSTRUC%define origin 0x08048000;; The ELF header and program segement table. org originehdr: ; Elf32_Ehdr db 0x7F, "ELF", 1, 1, 1 ; e_ident times 9 db 0 dw 2 ; e_type dw 3 ; e_machine dd 1 ; e_version dd _start ; e_entry dd phdr - $$ ; e_phoff dd 0 ; e_shoff dd 0 ; e_flags dw ehdrsize ; e_ehsize dw phdrsize ; e_phentsizephdr: ; Elf32_Phdr dw 1 ; e_phnum ; p_type dw 0 ; e_shentsize dw 0 ; e_shnum ; p_offset dw 0 ; e_shstrndxehdrsize equ $ - ehdr dd $$ ; p_vaddr dd $$ ; p_paddr dd filesize ; p_filesz dd memsize ; p_memsz dd 7 ; p_flags dd 0x1000 ; p_alignphdrsize equ $ - phdr;; mmapfile takes a filename and returns a read-only pointer to its;; contents.;;;; input:;; ebx = pointer to NUL-terminated filename;;;; output:;; eax = pointer to file's contents;; sign flag is set if an error occurred;; ebx and ecx are alteredmmapfile:;; After opening the file, the fstat system call is used to obtain the;; size of the file. buf is used to hold the returned stat structure. xor ecx, ecx lea eax, [byte ecx + 5] int 0x80 or eax, eax js .return xchg eax, ebx lea eax, [byte ecx + 108] lea ecx, [byte edi + buf - tm] int 0x80;; An mmap structure is filled out and handed off to the system call,;; and the function returns. xor eax, eax mov [byte ecx + 32], ebx lea ebx, [byte ecx + 16] mov [ebx], eax mov [byte ebx + 20], eax inc eax mov [byte ebx + 8], eax mov [byte ebx + 12], eax mov al, 90 int 0x80 or eax, eax.return: ret%macro pause 0 pushf pusha xor ebx, ebx lea ecx, [byte esp + 12] lea edx, [byte ebx + 1] lea eax, [byte ebx + 3] int 0x80 popa popf%endmacro;; The program proper begins here._start:;; The program begins by filling in the missing "C" locale;; information. It takes advantage of the fact that all the short;; names of the weeks and months are just the first three characters;; of the long names. The start of the week names are copied first,;; and then the program skips over to the month names. mov esi, clocale + (8 + 7 * 4) mov edi, ca0 xor ecx, ecx.shortformloop: mov ebx, [esi + ecx*4] mov eax, [esi - (8 + 7 * 4) + ebx - 1] shr eax, 8 stosd inc ecx cmp ecx, byte 7 jnz .skip add ecx, byte 12.skip: cmp ecx, byte 31 jnz .shortformloop xor ecx, ecx;;;;; edi is initialized to point to the start of the .bss section. ebp;; is pointed at the read-only data in the .text section, centered on;; the list of format characters. It will retain this value throughout;; the program. mov ebp, fmtchars mov edi, tm;; Call gettimeofday(), storing the current time in the .ct field. mov ebx, edi lea eax, [byte ecx + 78] int 0x80;; The default format string is stashed in ecx, and the command-line;; arguments are examined. lea ecx, [byte ebp + defaultfmt - fmtchars] pop esi pop esi;; An argument beginning with a + provides a display format string. If;; no such argument is present, the built-in formats is used. The;; presence of a -u option indicates that the time should be displayed;; for UTC instead of local time. An argument beginning with = provides;; a C time to use instead of the current time..argvloop: pop esi or esi, esi jz .argvloopend lodsb cmp al, '+' jnz .notfmt mov ecx, esi jmp short .argvloop.notfmt: cmp al, '=' jnz .nottime xor eax, eax cdq.atoiloop: lea edx, [edx*4 + edx] lea edx, [edx*2 + eax] lodsb sub al, '0' jc .atoidone cmp al, 10 jc .atoiloop.atoidone: mov [edi], edx jmp short .argvloop.nottime: cmp al, '-' jnz .argvloop.optloop: lodsb or al, al jz .argvloop cmp al, 'u' jnz .optloop mov dword [byte edi + tmfmt.tz], 'UTC' jmp short .optloop.argvloopend: mov [byte edi + fmt - tm], ecx;; The program stores a pointer to the default "C" locale, and then;; copies over the first part of the localization file name. lea edx, [byte ebp + clocale - fmtchars] mov [byte edi + localedata - tm], edx mov edx, edi add edi, byte buf - tm lea esi, [byte ebp + lctimeprefix - fmtchars] push byte lctimeprefixlen pop ecx rep movsb;; Then the list of environment variables is searched for a variable;; named LANG. If no such variable is present, the default "C" locale;; is retained..searchenvloop: pop esi or esi, esi jz .useclocale lodsd cmp eax, 'LANG' jnz .searchenvloop lodsb cmp al, '=' jnz .searchenvloop;; If one is present, its value is used to complete the name of the;; localization file, which is then loaded into memory..copylangloop: lodsb stosb or al, al jnz .copylangloop dec edi lea esi, [byte ebp + lctimesuffix - fmtchars] movsd movsd stosb mov edi, edx lea ebx, [byte edi + buf - tm] call mmapfile js .useclocale mov [byte edi + localedata - tm], eax.useclocale: mov edi, edx;; If time zone information is already present, UTC is to be used and;; the translation to local time is skipped. Otherwise, the file for;; the local time zone is loaded. xor edx, edx cmp edx, [byte edi + tmfmt.tz] jnz skipzoning lea ebx, [byte ebp + tzfilename - fmtchars] call mmapfile js skipzoning;; At the top of the localtime file is a sequence of integers;; indicating the size of the various parts of the file. Following;; this is a list of time changes for this zone. (See tzfile(5) for a;; fuller description of the structure of this file.) The program runs;; through the list backwards, finding the current subsequence of;; linear time. mov ebx, [byte eax + 32] bswap ebx mov esi, [byte eax + 36] bswap esi lea esi, [esi*2 + esi] mov ecx, ebx add eax, byte 44.tmchgloop: dec ecx jz .tmchgloopexit mov edx, [eax + ecx*4] bswap edx cmp edx, [edi] jg .tmchgloop.tmchgloopexit:;; The index of the current subsequence gives us the offset into the;; next array, which itself contains indexes into the array of the;; current attributes of the time zone. These attributes give the;; offset from GMT in seconds (which is stored in zo), a flag;; indicating whether or not Daylight Savings is in effect, and a;; pointer to the current time zone's name (which is stored in tz). lea eax, [eax + ebx*4] movzx ecx, byte [eax + ecx] add eax, ebx lea ecx, [ecx*2 + ecx] mov edx, [eax + ecx*2] bswap edx mov [byte edi + tmfmt.zo], edx movzx ecx, byte [byte eax + ecx*2 + 5] lea eax, [eax + esi*2] fild qword [eax + ecx] fistp qword [byte edi + tmfmt.tz];; The current offset from GMT in seconds is then changed into hours;; and minutes. These are used to create a string of the form +HHMM,;; stored in zi.skipzoning: mov al, '+' or edx, edx jns .eastward mov al, '-' neg edx.eastward: mov [byte edi + tmfmt.zi], al xchg eax, edx cdq lea ebx, [byte edx + 60] div ebx cdq div ebx aam xchg eax, edx aam shl edx, 16 lea eax, [edx + eax + '0000'] bswap eax mov [byte edi + tmfmt.zi + 1], eax;; The current time is loaded into eax, the offset for the time zone;; is applied. If this makes the current time negative, a year is;; added to the time, and the start of the Epoch is moved back. The;; day of the week of the start of the Epoch is stored in esi and on;; the stack. mov ecx, 1969 push byte 4 pop esi mov eax, [edi] add eax, [byte edi + tmfmt.zo] jge .positivetime add eax, 365 * 24 * 60 * 60 dec ecx dec esi.positivetime: push esi;; eax holds the number of seconds since the Epoch. This is divided by;; 60 to get the current number of seconds, by 60 again to get the;; current number of minutes, and then by 24 to get the current number;; of hours. cdq lea ebx, [byte edx + 60] div ebx mov [byte edi + tmfmt.sc], edx cdq div ebx mov [byte edi + tmfmt.mn], edx mov bl, 24 cdq div ebx mov [byte edi + tmfmt.hr], edx;; The hours are also tested to determine the current side of the;; meridian, and the hours of the meridian. sub edx, byte 12 setae byte [byte edi + tmfmt.mr] ja .morning.midnight: add edx, byte 12 jz .midnight.morning: mov [byte edi + tmfmt.hm], edx;; eax now holds the number of days since the Epoch. This is divided;; by seven, after offsetting by the value in esi, to determine the;; current day of the week. push eax add eax, esi mov bl, 7 cdq div ebx mov [byte edi + tmfmt.wd], edx xor eax, eax cmpxchg edx, ebx mov [byte edi + tmfmt.w1], edx mov eax, [esp];; A year's worth of days are successively subtracted from eax until;; the current year is determined. The program takes advantage of the;; fact that every 4th year is a leap year within the range of our;; Epoch. mov bh, 1.yrloop: mov bl, 110 inc ecx test cl, 3 jz .leap dec ebx.leap: sub eax, ebx jge .yrloop add eax, ebx mov [byte edi + tmfmt.yr], ecx;; 1900 or 2000 is subtracted to determined the century and the year;; of the century. mov ch, 20 sub cl, 208 jnc .twentieth dec ch add cl, 100.twentieth: mov [byte edi + tmfmt.cy], cl mov [byte edi + tmfmt.ce], ch;; eax now holds the day of the year, and this is saved in esi. ebx is;; altered to hold a string of pairs of bits indicating the length of;; each month over 28 days. Each month's worth of days are;; successively subtracted from eax until the current month, and thus;; the current day of the month, is determined. mov esi, eax add ebx, 11000000001110111011111011101100b - 365 xor ecx, ecx cdq
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -