繁体   English   中英

在 NASM 中使用 printf 循环

[英]Loop with printf in NASM

在第一个循环中,我填充了array ,然后我想打印这个数组,但是会出错。 这是Segmentation fault 我只是更改ecx寄存器,因为是我的_loop2计数器。

extern  printf

SECTION .bss
    array resb 10

SECTION .data
    fmt: db "array[%d] = %d", 10, 0 ; The printf format, "\n",'0'


SECTION .text

global main

main:
    mov ecx, 0

_loop:
    inc ecx
    mov [array + ecx * 4], ecx
    cmp ecx, 10
    jnz _loop

    mov ecx, 0


_loop2:
    jmp print
    add ecx, 1
    cmp ecx, 10
    jnz _loop2
    
    ret

print:
    ;push    ebp        ; set up stack frame
    ;mov     ebp, esp
    push    ecx
    push    dword [array + ecx * 4] ; value of variable a SECOND
    push    dword fmt   ; address of ctrl string
    call    printf      ; Call C function
    
    add     esp, 8      ; stack (4 * 2)

    ;mov     esp, ebp   ; takedown stack frame
    ;pop     ebp        ; same as "leave" op

    mov     eax,0       ;  normal, no error, return value

    ;ret            ; return

评论中提到的几个问题:

  • array resb 10将为 10 个字节保留空间,但您想在其中存储 10 个双字(40 个字节)。 更改为array resd 10

  • (由 Sep Roland 指出)在_loop ,您有一个错误; 由于incmov之前完成,您将访问[array+4], [array+8], ... [array+40]处的双字,其中最后一个超出范围。 这就像做int array[10]; for (i=1; i <= 10; i++) array[i]=i; int array[10]; for (i=1; i <= 10; i++) array[i]=i; 在 C 中,并且由于完全相同的原因不正确。 一种解决方法是mov [array + ecx * 4 - 4], ecx代替。

  • _loop2之后你有jmp print ,它将控制权转移到print并且永远不会回来。 由于您显然想将print作为子例程调用并继续执行add ecx, 1; cmp ecx, 10 add ecx, 1; cmp ecx, 10等,您需要call print而不是jmp 并且还取消注释print末尾的ret以便它实际返回。 除非您实际执行ret ,否则汇编语言中的子程序不会自动返回; 否则 CPU 将继续执行 memory 中接下来发生的任何垃圾。

  • 在调用printf之前,您有一个push ecx来保存ecx的值,这很好,因为printf会覆盖该寄存器,但是您需要在之后pop ecx以取回该值并将堆栈放回原来的位置。

    具体来说, pop ecx应该跟在add esp, 8 堆栈是后进先出结构,并且push ecx是在printf arguments的push之前,因此您需要在从堆栈中删除那些arguments之后pop ecx

  • mov eax, 0作为print末尾的返回值是不必要的,因为您从不在其他任何地方使用它。

通过这些更改,代码可以正常工作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM