首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在汇编中实现wc

在汇编中实现wc
EN

Stack Overflow用户
提问于 2015-05-27 13:40:32
回答 1查看 520关注 0票数 0

我正在尝试将一个典型的wc C代码转换成英特尔汇编代码。C代码是源代码,aseembly是我做的代码。由于它没有任何函数调用,我认为这会起作用,但它总是以iCharCount损坏和iLineCount保持为0而结束。可能的问题是什么?

C代码

代码语言:javascript
复制
#include <stdio.h>
#include <ctype.h>
enum {FALSE, TRUE};
int main(void){
   int iLineCount = 0;
   int iWordCount = 0;
   int iCharCount = 0;
   int iChar;
   int iInWord = FALSE;
   iChar = fgetc(stdin);
   for( ;iChar != EOF; ){
      iCharCount++;

      if (iChar == '\n') iLineCount++;
      if (isspace(iChar)){
         if (iInWord){
            iWordCount++;
            iInWord = FALSE;
         }
      }
      else if (!iInWord) iInWord = TRUE;
      iChar = fgetc(stdin);
   }

   if (iInWord) iWordCount++;
   printf("%7d%8d%8d\n", iLineCount, iWordCount, iCharCount);
   return 0;
}

汇编代码

代码语言:javascript
复制
    .file "wc.s"
    .section        .rodata
    .equ TRUE, 1
    .equ FALSE, 0
    .equ SPACE, 32
    .equ LCHANGE, 10
    .equ TAB, 9
    .equ EOF, -1
    .globl main
    .type main, @function
main:
start:
    pushl %ebp
    movl %esp, %ebp
    andl $-16, %esp
    subl $48, %esp
    movl $0, 20(%esp) #int iLineCount = 0
    movl $0, 24(%esp) #int iWordCount
    movl $0, 28(%esp) #int iCharCount
    movl $0, 36(%esp) #int iInWord = FALSE
    movl stdin, %eax
    movl %eax, (%esp)
    call fgetc
    movl %eax, 32(%esp) #iChar = fgetc(stdin)
    cmpl $EOF, 8(%ebp) #Start of for( ;iChar != EOF;)
    je endloop
loop:
    incl 28(%ebp)   #iCharCount++
    cmpl $LCHANGE, 32(%ebp) #if(iChar == '\n')
    jne ecomp1
    incl 20(%esp) #iLineCount++
ecomp1:
    cmpl $LCHANGE, 32(%esp) #if(isspace(iChar) ->'\n'
    je isspace
    cmpl $SPACE, 32(%esp) #-> ' '
    je isspace
    cmpl $TAB, 32(%esp) # -> '\t'
    je isspace
    jmp elsespace
isspace:
    cmpl $TRUE, 36(%esp)    #if(iInWord)
    jne last
    movl $FALSE, 36(%esp) #iInWord = FALSE
    incl 24(%esp)   #iWordCount++
    jmp last
elsespace:
    cmpl $FALSE, 36(%esp)   #if(!InWord)
    jne last
    movl $TRUE, 36(%esp)    #iInWord = TRUE
last:
    movl stdin, %eax
    call fgetc
    movl %eax, 32(%esp)     #iChar = fgetc(stdin)
    cmpl $EOF, 32(%esp)     #Recheck for statement
    jne loop
endloop:
    cmpl $TRUE, 36(%esp)    #if(iInWord)
    jne else
    incl 24(%esp)   #iWordCount++
else:
    movl 28(%esp), %eax
    movl %eax, 12(%esp) #push iCharCount in printf
    movl 24(%esp), %eax
    movl %eax, 8(%esp) #push iWordCount in printf
    movl 20(%ebp), %eax
    movl %eax, 4(%esp) #push iLineCount in printf
    movl $.format, (%esp)
    call printf
    leave
    ret
.format:
    .string "%7d%8d%8d\n"
    .text
EN

回答 1

Stack Overflow用户

发布于 2015-05-27 17:10:52

您的装配列表中缺少行:缺少label last以及循环末尾的iChar = fgetc(stdin);

你应该简化你的C代码。首先使用经典的成语:

代码语言:javascript
复制
while ((iChar = fgetc(stdin)) != EOF) { ... }

中不需要测试。

代码语言:javascript
复制
else if (!iInWord) iInWord = TRUE;

这里也不需要两个测试:

代码语言:javascript
复制
  if (isspace(iChar)){
     if (iInWord){
        iWordCount++;
        iInWord = FALSE;
     }
  }

您可以这样简化循环和单词test:

代码语言:javascript
复制
while ((iChar = fgetc(stdin)) != EOF) {
    iCharCount++;
    if (iChar == '\n') iLineCount++;
    if (isspace(iChar)) {
        iWordCount += iInWord;
        iInWord = 0;
    } else {
        iInWord = 1;
    }
}
iWordCount += iInWord;

printf格式是不合适的:如果计数变得太大,数字就会粘合在一起。改用下面的代码:

代码语言:javascript
复制
printf("%7d %7d %7d\n", iLineCount, iWordCount, iCharCount);

至于汇编版本,它似乎是由编译器生成的,然后有点手工修补。您确实重写了isspace()测试,并且没有测试一些空白字符,如'\r''\f''\n'的测试是多余的,您可以在递增iLineCount之后跳转到isspace:

编辑:汇编代码的问题在于:您有时会错误地使用%ebp而不是%esp来访问局部变量。

代码语言:javascript
复制
    ...
    cmpl $EOF, 8(%ebp) #Start of for( ;iChar != EOF;)
    ...
loop:
    incl 28(%ebp)   #iCharCount++
    cmpl $LCHANGE, 32(%ebp) #if(iChar == '\n')
    ...
    movl 20(%ebp), %eax
    ...            
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30474028

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档