3

我编写了以下用于添加 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
4

3 回答 3

3

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

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

add eax,[ebx]

出于完全相同的原因,以下内容也不完全正确:

mov [total],eax

我认为还有一个问题,您在调用之前推送地址,而您可能应该推送它的totalprintf()

此外,正如@JasonD 所指出的,您需要在调用printf().

最后,

mov esp,ebp

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

于 2013-01-08T13:35:24.310 回答
3

我在这里看到了几个问题。首先,您已经获得num1total声明为dw. dw听起来像是“dword”的意思,但它的意思是“数据字”。你希望这些是dd- “数据双字”......因为这就是你使用它们的方式。(而add ebx, 4不是 2)如果您确实需要在 32 位代码中使用字(16 位)值,可以这样做,但很尴尬。

我看到的第二个问题是,push total在您call _printf推送total. 你想要内存的“[内容]”,所以push dword [total]. (push msg是正确的)

在此之后,您可能想要add esp, 8(我喜欢将其写为add esp, 4 * 2- 两个参数,每个参数 4 个字节)。可以“推迟”此堆栈清理 -mov esp, ebp将修复您,但需要在pop ebp!!!

……可能还有更多……

于 2013-01-08T13:58:10.933 回答
2

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

于 2013-01-08T13:36:07.357 回答