将C代码翻译成汇编

3

我需要将这段C代码翻译成汇编语言代码

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int answer, i;
    int right, wrong;
    right = 0;
    wrong = 0;

    for(i =1; i < 11; i = i+1){
        printf("What is %d + %d? ", i,i);
        scanf( "%d", &answer);

        if(answer == i + 1) {
            printf("right!  ");
            right++;
        }
        else {
            printf("Sorry, you're wrong.    ");
            printf("The answer is %d.   ", i + 1);
            wrong++;
        }
    }
    printf("You got %d right and %d wrong. ", right, wrong );
    return 0;
}

我只需要知道如何在汇编语言中像上面的C代码一样将变量与字符串组合起来。其他的我认为我可以处理。有人能告诉我吗?我是否需要使用某种reference[]。

注意,我正在使用MASM,并从Kip Irvine的《x86处理器汇编语言》第6版书中学习

更新:这是我尝试从回答者的答案中转换到MASM的代码。但我一直收到一个错误。就像我之前说的一样,我正在使用Kip Irvine的汇编语言,所以必须包含库链接INCLUDE Irvine32.inc

这是错误 >>>>> programb.obj: error LNK2019:未解析的外部符号_scanf,它被引用于函数_main@0

INCLUDE Irvine32.inc

有人能帮我把它弄对吗?

.data
string1 db "What is %d + %d?  ", 0
string2 db "%d", 0
string3 db "right!  ", 0
string4 db "Sorry, you're wrong.   The answer is %d", 10, 0
string5 db "You got %d right and %d wrong.", 10, 0


answer dd 0
right  dd 0
wrong  dd 0

.code
main PROC

   mov ebx, 1

L1:

   cmp ebx, 11
   je L2

   push 1
   push ebx
   mov edx,OFFSET string1
   call WriteString
   add esp, 12

   push answer
   mov edx,OFFSET string2
   call scanf
   add esp, 8

   inc ebx
   cmp answer, ebx
   jne L3

   push ebx
   mov edx,OFFSET string3
   call WriteString
   add esp, 8
   inc right

   jmp L1

L3:

   push ebx
   mov edx,OFFSET string4
   call WriteString
   add esp, 8
   inc  wrong

   jmp L1

L2:

   push  wrong
   push  right
   mov EDX,OFFSET string5
   call WriteString
   add esp, 12


   exit

main ENDP
END main

programb.obj : error LNK2019: unresolved external symbol _scanf referenced in function _main@0

非常抱歉关于汇编语言代码的问题...我不知道如何格式化它以便更容易阅读...


你是在问如何从汇编调用printf函数,还是在询问如何在汇编中进行整数转字符串并进行字符串连接?这两个问题是非常不同的。 - Prof. Falken
基本上是字符串拼接。 - jwill22
4个回答

9
你可以使用-S标志来运行gcc以生成汇编代码: gcc myfile.c -S -o myfile.s 我的意思是,这个汇编文件应该能回答你所有的问题。

2
在命令行中添加标志-masm=intel,以获得类似MASM的代码(intel语法):gcc -S -masm=intel myfile.c -o myfile.s - Noe
不幸的是,这将生成委托给libc的代码,而不是生成实际执行操作的代码。 - Ignacio Vazquez-Abrams
3
他可以使用静态编译模式,但重新编写“printf()”将是一场噩梦! - Antoine Pelisse

5

我很无聊,所以为你做了这个。我使用了NASM,而不是MASM。我假设EBX是被调用者保存的寄存器。代码并不特别好。 :-)

section .data
answer: dd 0
right:  dd 0
wrong:  dd 0

section .text
extern printf
extern scanf
global main
main:

   push ebx
   mov ebx, 1

.loop_start:

   cmp ebx, 11
   je .loop_end

   push 1
   push ebx
   push .string0
   call printf
   add esp, 12

   push answer
   push .string1
   call scanf
   add esp, 8

   inc ebx
   cmp dword [answer], ebx
   jne .wrong

   push ebx
   push .string2
   call printf
   add esp, 8
   inc dword [right]

   jmp .loop_start

.wrong:

   push ebx
   push .string3
   call printf
   add esp, 8
   inc dword [wrong]

   jmp .loop_start

.loop_end:

   push dword [wrong]
   push dword [right]
   push .string4
   call printf
   add esp, 12

   pop ebx
   xor eax, eax
   ret

section .data

.string0:
   db "What is %d + %d?  ", 0
.string1:
   db "%d", 0
.string2:
   db "right!  ", 0
.string3:
   db "Sorry, you're wrong.   The answer is %d", 10, 0
.string4:
   db "You got %d right and %d wrong.", 10, 0

@user498084 我并没有真正使用过MASM,但它应该非常相似。我相信你可以弄清楚的。此外,对@Rob的愤怒评论是不必要的。 - asveikau
好的,我了解你的感受......我尝试了(难过的脸),它能够运行,但是它并没有像C代码一样运行。没关系,而且忘了他应得的报应......如果他没有任何有建设性的话或贡献,那么他就该闭嘴。 - jwill22

1
幸运的是,printf函数几乎可以为您完成所有工作,即使是从汇编语言中调用。您可能已经了解了堆栈以及如何调用需要在堆栈上推送参数的函数。对于printf也是如此。按相反的顺序将参数推入堆栈,以便堆栈顶部的内容是格式字符串的引用。然后您所要做的就是:
       call     printf

如果我没记错的话,printf知道它至少有一个参数,而第一个参数(格式化字符串)就是栈指针所指向的参数。然后printf会扫描格式化字符串并检查是否需要替换您的其他参数,如i和i + 1。同样,printf正在执行此操作,您不需要担心。
希望这可以帮到您!
附言:关于先前的答案,通常查看编译器生成的汇编代码并不有助于学习汇编语言。即使禁用了优化,输出也不是面向人类阅读的。

2
显然,这不是为人类设计的,但你可以很容易地编写一个简单的函数,在非常简单的情况下调用printf()来查看它的调用方式。 - Antoine Pelisse

0
作为一个例子,在C编程语言中的这一行:
printf("\n%d%s%d\n\n",num1," is not equal to ",num2);

等同于:

printf PROTO arg1:Ptr Byte, printlist:VARARG
.data
msg1fmt byte 0Ah,"%d%s%d",0Ah,0Ah,0
msg1 byte " is not equal to ",0
num1 sdword 5
num2 sdword 7
.code
main proc
INVOKE printf, ADDR msg1fmt, num1, ADDR msg1, num2
ret

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接