在NASM中将10个数字和打印结果相加

时间:2013-01-08 13:25:44

标签: assembly x86 nasm

我已经编写了以下汇编代码,用于添加10个数字。我能够编译并执行它但是我得到了错误的结果。 我只是想知道如何在scree上打印 total 的值。

section .data
num1: dw 10, 20, 30, 40, 50, 10, 20, 30, 40, 50
total: dw 0
msg :  db "sum=%d",10,0

section .text
    extern _printf
    global _main
_main:
    push ebp
    mov ebp,esp
    mov ebx,num1 ;point bx to first number
    mov ecx,10      ;load count of numbers in ecx
    mov eax,0       ;initialize sum to zero
loop:
    add eax,[ebx]
    add ebx,2
    sub ecx,1
    jnz loop
    mov [total],eax

    push total
    push msg
    call _printf

    pop ebp
    mov esp,ebp
    ret

溶液

section .data
num1: dd 10, 20, 30, 40, 50, 10, 20, 30, 40, 50,300
total: dd 0
msg :  dd "sum=%d",10,0

    section .text
        extern _printf
        global _main
    _main:
        push ebp
        mov ebp,esp
        mov ebx,num1 ;point bx to first number
        mov ecx,11     ;load count of numbers in ecx
        mov eax,0       ;initialize sum to zero
    loop:
        add eax,[ebx]
        add ebx,4
        sub ecx,1
        jnz loop
        mov  [total],eax
        push dword [total]

        push msg
        call _printf
        mov esp,ebp
        pop ebp

        ret

3 个答案:

答案 0 :(得分:3)

您正在使用32位内存访问来处理16位值。

数组的每个元素都是16位宽。但是,由于eax是32位宽,因此以下内容将数组视为每个元素也是32位宽:

add eax,[ebx]

以下也不完全正确,原因完全相同:

mov [total],eax

我认为还有一个问题是你在调用total之前推送printf()地址,而你应该推送它的

另外,正如@JasonD指出的那样,你需要在调用printf()后清理堆栈。

最后,

mov esp,ebp

指令应该被删除,因为它只会破坏你的堆栈指针。

答案 1 :(得分:3)

我在这里看到了几个问题。首先,您已将num1total声明为dwdw可能听起来像是“dword”,但它的意思是“数据字”。您希望这些是dd - “数据dword”...因为这就是您使用它们的方式。 (并且add ebx, 4不是2)如果你真的需要在32位代码中使用字(16位)值,那么它可以完成,但是很尴尬。

我看到的第二个问题是push totalcall _printf推送total的地址之前push dword [total]。你想要内存的“[内容]”,所以push msg。 (add esp, 8是正确的)

在此之后,您可能需要add esp, 4 * 2(我喜欢将其写为mov esp, ebp - 两个参数,每个4个字节)。可以“推迟”此堆栈清理 - pop ebp将解决您的问题,但需要在{{1}} !!!

之前完成

......可能会有更多......

答案 2 :(得分:2)

dw 定义了16位实体,但add eax,[ebx]正在添加32位实体。在 [ebx] 之前将 dw 更改为 dd 或将 WORD PTR 更改为 [ebx] 。此外,正如NPE指出的那样,您需要更改将 eax 存储到总计的处理方式。