| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 4634 人关注过本帖
标题:汇编能够实现显示当前日期,并输出当前日期是这一年中第多少天及第二天的日 ...
只看楼主 加入收藏
香菜爱obm
Rank: 1
等 级:新手上路
帖 子:5
专家分:0
注 册:2015-10-9
结帖率:50%
收藏
已结贴  问题点数:20 回复次数:7 
汇编能够实现显示当前日期,并输出当前日期是这一年中第多少天及第二天的日期。马上要交作业了,求大神!!
汇编能够实现显示当前日期,并输出当前日期是这一年中第多少天及第二天的日期。马上要交作业了,求大神!!
2015-10-13 09:10
wfoo
Rank: 3Rank: 3
等 级:论坛游侠
威 望:7
帖 子:120
专家分:134
注 册:2011-8-6
收藏
得分:20 
程序代码:
#include <stdarg.h>

extern void puts (const char *s); /* 用汇编实现 */
extern void gets (char *s); /* 用汇编实现 */

#define is_white(c) (c == ' ' || c == '\t' || c == '\r' || c == '\n')
#define to_int(c)   ('0' <= c && c <= '9' ? c - '0' :\
                     'a' <= c && c <= 'f' ? c - 'a' + 10 : \
                     'A' <= c && c <= 'F' ? c - 'A' + 10 : 17)

int vsscanf (const char *buff, const char *fmt, va_list ap)
{
  int base = 0, sign = 0;
  int c, nr = 0, v;
  char *str;
  int *int;

  while ((c = *fmt++))
    {
      if (is_white (c))
        {
          while (is_white (*buff))
            ++buff;
        }
      else if (c != '%' || (c = *fmt++) == '%')
        {
          if (c != *buff++)
            break;
        }
     else if (!*buff || is_white (*buff))
        break;
     else
        switch ((c))
          {
          case 'c':
            str = va_arg (ap, char *);
            *str = *buff++;
            ++nr;
            break;

          case 's':
            str = va_arg (ap, char *);
            *str
            while (*buff && !is_white(*buff))
              *str++ = *buff++;
            *str = 0;
            ++nr;
            break;

        case 'o':
            base = 8;
            goto case_int;
        case 'd':
            base = 10;
            goto case_int;
        case 'x':
            base = 16;
            goto case_int;

        case_int:
            v = sign = 0;
            if (*buff == '-')
              sign = 1, ++buff;

            while ((c = to_int (*buff)) < base)
              {
                v = v * base + c;
                ++buff;
              }

           * va_arg (ap, int *) = sign ? -v : v;
           ++nr;
           break;
        }
    }
}

int scanf (const char *buff, const char *fmt, ...)
{
  int res;
  va_list ap;
  char buff[512];
  
  gets (buff);
  va_start (ap, fmt);
  res = vsscanf (buff, fmt, ap);
  va_end (ap);

  return res;
}

void vsprintf (char *buff, const char *s, va_list ap)
{
  int c, n, base = 10, sign = 0;
  const char *str = NULL;
  char intbuff[65], *pint;
  static const char *alphas = "0123456789ABCDEF";

  while ((c = *s++))
    {
      if (c != '%')
        *buff++ = c;
      else 
        switch ((c = *s++))
          {
          case 0: 
            goto outloop;

          case 'c':
            *buff++ = va_arg (ap, int);
            break;

          case '%':
            *buff++ = '%';
            break;

          case 's':
            str = va_arg (ap, const char *);
          case_str:
            while ((*buff++ = *str++));
            break;

          case 'x':
            base = 16;
            goto case_int;

          case 'o':
            base = 8;
            goto case_int;

          case 'd':
            base = 10;
            goto case_int;

          case_int:
            sign = 0;
            n = va_arg (ap, int);
            if (n < 0) 
              n = -n, sign = 1;
            pint = intbuff + sizeof (intbuff) - 1;
            *pint-- = 0;
            do *pint-- = alphas [n % base]; while ((n /= base));
            if (sign)
              *pint-- = 0;
            str = pint + 1;
            goto case_str;
          }
    }

  *buff++ = 0;
}

void printf(const char *fmt, ...)
{
  va_list ap;
  char buff[512];

  va_start (ap, fmt);
  vsprintf (buff, fmt, ap);
  va_end (ap);

  puts (buff);
}

inline int is_leap (int year)
{
  return !(year % 4) && ((year % 25) || !(year % 16));
}

static const int tab_daysofyear_acc[2][13] = 
  {
    {非闰年的天数积累},
    {闰年的天数积累},
  };

int get_daysofyear_and_nextday(int *pyear, int *pmon, int *pdate)
{
  const int *tab = tab [is_leap (year)];
  int year = *pyear, mon = *pmon, *date = *pdate, days;

  days = tab[mon] + date;

  if (++date - 1 > tab[mon+1] - tab[mon])
    {
      date -= (tab[mon+1] - tab[mon]);
      if (++mon > 12)
        {
          mon -= 12;
          year += 1;
        }
    }

  *pyear = year;
  *pmon = mon;
  *pdate = date;

  return days;
}

void do_main_loop (void)
{
  int n, y, m, d, days;

  while (1)
    {
      printf ("input date(year month date)>> ");
      n = scanf ("%d %d %d", &y, &m, &d);
      if (n != 3)
        printf ("input error!\n");
      else
       {
         printf ("the %04d-%02d-%02d is ", y, m, d);
         days = get_daysofyear_and_nextday (&y, &m, &d);
         printf ("%d days in this year.\n"
                 "next date is: %04d-%02d-%02d \n",
                  days, y, m, d);
       }
    }
}

int main(int argc, char **argv)
{
  do_main_loop ();
  return 0;
}


其中键盘的输入和屏幕的输出用汇编写,gcc -S把代码生成汇编,大概能达到楼主的要求,随手写的没测试过。
2015-10-13 11:37
wfoo
Rank: 3Rank: 3
等 级:论坛游侠
威 望:7
帖 子:120
专家分:134
注 册:2011-8-6
收藏
得分:0 
忘记了,代码没有实现printf 的 “%02d"格式,应该改为 "%d",
还有 vsprintf 函数中掉了个outloop标签。
2015-10-13 11:45
香菜爱obm
Rank: 1
等 级:新手上路
帖 子:5
专家分:0
注 册:2015-10-9
收藏
得分:0 
可是需要完全用汇编语言写,现在写了一点,还有错误不会改,你能帮我看下吗?
;*************清屏宏定义***********  
CLEAR_SCREEN MACRO               ;宏定义,设置七个参数
  MOV AH,06H                       ;AH=06屏幕初始化或上卷指定的行
  MOV AL,00H                   ;清屏
  INT 10H                      ;调用BIOS功能
  MOV AH,02H                   ;制定光标位置
  MOV BH,00H                   ;第0页
  MOV DH,00H                   ;第0行
  MOV DL,00H                   ;第0列
  INT 10H   
ENDM  
;*********定义堆栈段********
STACK SEGMENT  
 DB 200 DUP(?)  
 tos label byte
STACK ENDS  
;*********定义数据段********
DATA SEGMENT  
 STR00 DB'      |**********  Welcome!  **********|$'    ;提示界面
 STR01 DB 0DH,0AH,'      |*                              *|$'
 STR02 DB 0DH,0AH,'      |*  This is a display program.  *|$'
 STR03 DB 0DH,0AH,'      |*     D: display Date          *|$'
 STR05 DB 0DH,0AH,'      |*     Q: Quit                  *|$'
 STR06 DB 0DH,0AH,'      |*                              *|$'
 STR07 DB 0DH,0AH,'      |********************************|$'
 STR08 DB 0DH,0AH,'Please input a char: $'  
 INPUTER DB 0DH,0AH,'Input Error!',0DH,0AH,'$'
 DATEDIS DB ' 0000-00-00 ',0AH,'$'     ;显示DATE

table dw 0,31,59,90,120,151,181,212,243,273,304,334  
 
DATA ENDS  
;*********定义代码段********
CODE SEGMENT  
 ASSUME CS:CODE,DS:DATA,SS:STACK
START:  
MAIN PROC FAR  
 MOV AH,00H                       ;AH=0设置显示模式
 MOV AL,03H                       ;设置80*25图形显示
 INT 10H  
 CLEAR_SCREEN                     ;调用宏定义
 MOV AX,DATA
 MOV DS,AX
 MOV AX,STACK
 MOV SS,AX  
 mov sp,offset tos  
;*******显示宏定义********
;用于显示字符串
SHOW MACRO str
 LEA DX,str
 MOV AH,9
 INT 21H
ENDM  
 SHOW STR00
 SHOW STR01
 SHOW STR02
 SHOW STR03
 SHOW STR05  
 SHOW STR06
 SHOW STR07
INPUT:  
 SHOW STR08                       ;显示输入提示
 MOV AH,01                        ;键盘输入并回写
 INT 21H  
 CMP AL,"D"                       ;与D比较  
 JE PRINT_DATE                    ;相等转PRINT_DATE打印日期
 CMP AL,"d"
 JE PRINT_DATE  
 CMP AL,"q"
 JE EXIT  
 SHOW INPUTER                     ;显示输入错误
 JMP INPUT
PRINT_DATE:  
 CALL DATEDISPLAY                 ;调用日期显示子程序
 JMP INPUT                       ;继续输入字母
 EXIT:                         ;结束,退出程序
 MOV AH,4CH
 INT 21H
MAIN ENDP  
;*********日期显示子程序*********
DATEDISPLAY PROC NEAR  
 MOV AH,2AH                       ;取当前系统日期
 INT 21H
        MOV AX,CX                         ;送年份入AX作为被除数【年份存在CX中】
        mov  dx,0
        mov  bx,4
        div  bx
        cmp  dx ,0
        jnz  nleap
        mov  ax,cx
        mov  dx,0
        mov  bx,100d
        div  bx
        cmp  dx,0
        jnz  leap  
        jz  again
    again:  mov  ax,cx
        mov  dx,0
        mov  bx,400
        div  bx
        cmp  dx,0
        jz   leap
        jnz  nleap                 
 MOV BX,10                        ;(BX)=10
 LEA SI,DATEDIS+4                 ;使SI指向年的最后一位【从0开始数】
 MOV CX,4                         ;(CX)=4  年的位数,循环4次
 PUSH DX                          ;DX入栈,保存月日
 TAB:   
    XOR DX,DX                        ;DX清零,存余数
    DIV BX                           ;(DX,AX)/BX,商送AX,余数送DX  
    ADD DL, 30H                      ;余数与30H相加变为字符的ASCII码
    MOV [SI], DL                     ;余数送入SI所指向的字节区
    DEC SI                           ;SI减一
    LOOP TAB                         ;循环4次
    POP DX                           ;DX还原
    MOV AL, DL                       ;日送AL【日存在DL中】
    XOR AH, AH                       ;AH清零
    DIV BL                           ;AX/BL,商送AL,余数送AH【AL为十位,AH为个位】
    ADD AX, 3030H                    ;转变为数字字符的ASCII码
    LEA SI, DATEDIS+9                ;使SI指向日的十位
    MOV [SI], AX                     ;(AX)送SI所指向的字节区
    MOV AL, DH                       ;月送AL 【月存在DH中】
    XOR AH, AH                       ;AH清零
    DIV BL                  ;AX/BL,商送AL,余数送AH【AL为十位,AH为个位】
    ADD AX, 3030H                    ;转变为数字字符的ASCII码
   LEA SI, DATEDIS+6                ;使SI指向月的十位
  MOV [SI], AX                     ;(AX)送SI所指向的字节区
 SHOW DATEDIS                     ;显示日期
 RET   ;调用后返回
 

leap:   
         mov al,dh
         lea ax,[table+al-1]
         mov bx,dl
         add ax,bx+1
         mov ah,09h
         int 21h


nleap:
         mov al,dh
         lea ax,[table+al-1]
         mov bx,dl
         add ax,bx
         mov ah,09h
         int 21h


   
DATEDISPLAY ENDP  
CODE ENDS     
     END START
2015-10-17 11:43
wfoo
Rank: 3Rank: 3
等 级:论坛游侠
威 望:7
帖 子:120
专家分:134
注 册:2011-8-6
收藏
得分:0 
用C语言写,gcc -S -O2 可以生成完全的汇编代码,你把生成的汇编稍微改下就可以交作业了,这样做花不到1个小时就能把整个汇编代码搞定,并且调试可以在操作系统下调试。
如果直接用汇编写起码要1天时间吧,可能还不止,调试和维护都很麻烦。
汇编写这种逻辑的代码实在是太繁琐了,“输出当前日期是这一年中第多少天及第二天的日期”很烦的。
其实真正需要汇编写的就2个函数,puts,gets, 这两个函数都是调用bios中断,甚至你写这样一个宏
struct regs { unsigned long ax, cx, bx, dx; };
#define bios_call(no, in, out) \
  __asm__("int %8" : "=a"(out->ax), "=b"(out->bx), "=c"(out->cx), "=d"(out->dx) \
                   : "0"(in->ax), "1"(in->bx), "2"(in->cx), "3"(in->dx), "i"(no))

两行汇编代码就可以得到整个程序的汇编代码, 这样难度大大降低了。
2015-10-17 17:23
香菜爱obm
Rank: 1
等 级:新手上路
帖 子:5
专家分:0
注 册:2015-10-9
收藏
得分:0 
能用汇编语言讲解一下显示第二天的日期应该怎么编写吗?
2015-10-19 13:05
wfoo
Rank: 3Rank: 3
等 级:论坛游侠
威 望:7
帖 子:120
专家分:134
注 册:2011-8-6
收藏
得分:0 
程序代码:
get_daysofyear_and_nextday:
.LFB1:
    pushl    %ebp
    pushl    %edi
    xorl    %edx, %edx
    pushl    %esi
    pushl    %ebx
    subl    $4, %esp
    movl    24(%esp), %eax
    movl    (%eax), %ecx
    movl    28(%esp), %eax
    movl    (%eax), %ebx
    movl    32(%esp), %eax
    testb    $3, %cl
    movl    (%eax), %esi
    jne    .L2
    movl    %ecx, %eax
    movl    $1374389535, %edx
    imull    %edx
    movl    %ecx, %eax
    sarl    $31, %eax
    sarl    $3, %edx
    subl    %eax, %edx
    leal    (%edx,%edx,4), %eax
    movl    $1, %edx
    leal    (%eax,%eax,4), %eax
    cmpl    %eax, %ecx
    je    .L9
.L2:
    imull    $52, %edx, %edx
    leal    0(,%ebx,4), %ebp
    movl    __tab(%ebp,%edx), %eax
    movl    __tab+4(%ebp,%edx), %edx
    movl    %edx, %ebp
    leal    (%eax,%esi), %edi
    subl    %eax, %ebp
    cmpl    %ebp, %esi
    movl    %edi, (%esp)
    leal    1(%esi), %edi
    jle    .L3
    subl    %edx, %eax
    addl    %eax, %edi
    leal    1(%ebx), %eax
    cmpl    $12, %eax
    jle    .L6
    subl    $11, %ebx
    addl    $1, %ecx
.L3:
    movl    24(%esp), %eax
    movl    %ecx, (%eax)
    movl    28(%esp), %eax
    movl    %ebx, (%eax)
    movl    32(%esp), %eax
    movl    %edi, (%eax)
    movl    (%esp), %eax
    addl    $4, %esp
    popl    %ebx
    popl    %esi
    popl    %edi
    popl    %ebp
    ret

.L9:
    xorl    %edx, %edx
    testb    $15, %cl
    sete    %dl
    jmp    .L2
.L6:
    movl    %eax, %ebx
    jmp    .L3
.LFE1:


就是我上面的C语言直接用gcc转换的汇编代码,
函数原型 int get_daysofyear_and_nextday(int *pyear, int *pmon, int *pdate);
            参数pyear:  年的指针,输入参数年,输出第二天的年份
            参数pmon:   月的指针,输入参数月,输出第二天的月份
            参数pdate:  日期的指针,输入参数日期,输出第二天的日期
      返回值:输入的日期在当年中的天数。

这个是AT&T格式的汇编汇编,和你的汇编的区别是
            指令的操作书顺序和楼主的相反,如  add eax, ebx, ecx 相当与 add %ecx, %ebx, %eax (eax <- ebx + ecx)
            寄存器前面加%号,常量前面加$,    add $1, %ecx, %eax (eax <- 1 + ecx)
            指令用后缀指定内存数的大小,     addl (%eax), %eax, %eax (eax <- [eax] + eax),应该intel汇编是这样的 add eax, eax, word ptr (eax)
2015-10-21 18:08
Alar30
Rank: 10Rank: 10Rank: 10
等 级:贵宾
威 望:10
帖 子:988
专家分:1627
注 册:2009-9-8
收藏
得分:0 
作业题哇……
2015-12-14 22:21
快速回复:汇编能够实现显示当前日期,并输出当前日期是这一年中第多少天及第二天 ...
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.020760 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved