我正在尝试将一个典型的wc C代码转换成英特尔汇编代码。C代码是源代码,aseembly是我做的代码。由于它没有任何函数调用,我认为这会起作用,但它总是以iCharCount损坏和iLineCount保持为0而结束。可能的问题是什么?
C代码
#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;
}汇编代码
.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发布于 2015-05-27 17:10:52
您的装配列表中缺少行:缺少label last以及循环末尾的iChar = fgetc(stdin);。
你应该简化你的C代码。首先使用经典的成语:
while ((iChar = fgetc(stdin)) != EOF) { ... }中不需要测试。
else if (!iInWord) iInWord = TRUE;这里也不需要两个测试:
if (isspace(iChar)){
if (iInWord){
iWordCount++;
iInWord = FALSE;
}
}您可以这样简化循环和单词test:
while ((iChar = fgetc(stdin)) != EOF) {
iCharCount++;
if (iChar == '\n') iLineCount++;
if (isspace(iChar)) {
iWordCount += iInWord;
iInWord = 0;
} else {
iInWord = 1;
}
}
iWordCount += iInWord;printf格式是不合适的:如果计数变得太大,数字就会粘合在一起。改用下面的代码:
printf("%7d %7d %7d\n", iLineCount, iWordCount, iCharCount);至于汇编版本,它似乎是由编译器生成的,然后有点手工修补。您确实重写了isspace()测试,并且没有测试一些空白字符,如'\r'和'\f'。'\n'的测试是多余的,您可以在递增iLineCount之后跳转到isspace:。
编辑:汇编代码的问题在于:您有时会错误地使用%ebp而不是%esp来访问局部变量。
...
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
... https://stackoverflow.com/questions/30474028
复制相似问题