实现一个根据输入的年、月、日计算总天数的函数,先用Delphi实现如下(没有考虑2月的特例,如输入2月30日),不过用于汇编练习,可以了:
1 function GetDays(year, month, day: Cardinal): Cardinal; 2 begin 3 Result := month * 30 - 30 + day; 4 if month>1 then 5 Result := Result + (month-1) div 2 + (month-1) mod 2; //31天的月 6 if month>2 then 7 if (year mod 4)=0 then 8 Dec(Result) 9 else 10 Dec(Result, 2); 11 end;
以下为汇编实现(我原自个辛辛苦苦写了一个,发现还没有Delphi编译器实现的漂亮,晕)
1 function GetDays2(year, month, day: Cardinal): Cardinal; 2 begin 3 ;按delphi的参数传递规则,前三个小于32位参数从左到右分别存到eax、edx、ecx 4 ;因此eax = year、edx = month、ecx = day 5 asm 6 push ebx 7 push esi 8 9 ;Result := month * 30 - 30 + day; 10 imul ebx, edx, 30 ;这句指edx * 30 存到ebx中 11 sub ebx, 30 12 add ecx, ebx 13 14 cmp edx, 1d ;if month>1 then 15 jbe @next1 ;jbe是小于等于 16 17 ;Result := Result + (month-1) div 2 + (month-1) mod 2; 31天的月 18 mov ebx, edx 19 dec ebx 20 mov esi, ebx 21 shr esi, 1 ;month div 2,右移一位相当于除以2,左移则是乘2 22 add ecx, esi 23 and ebx, 1d ;求余操作用and r32, x-1,如对4求余,则是 and r32, 3d 24 add ecx, ebx 25 26 @next1: 27 ;if month>2 then 28 cmp edx, 2d 29 jbe @end 30 and eax, 3d 31 test eax, eax ;test相当于and,唯一不同的时不修改结果,只影响标志位 32 jnz @dec2 ;不为0,则跳转 33 dec ecx 34 jmp @end 35 36 @dec2: 37 sub ecx, 2 38 39 @end: 40 mov eax, ecx 41 pop esi 42 pop ebx 43 ret ;对于在函数中另起asm...end的,需要ret,这种情况下,汇编中不能直接 44 ;引用参数,如mov eax, month。如果是用asm代替了函数的being...end 45 ;则可以引用参数,且不要加ret。 46 end; 47 end;