简体   繁体   中英

Loop with printf in NASM

In the first loop I fill the array , then I want to print this array, but I'll have an error. It's Segmentation fault . I just change ecx register, since is my counter for _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

Several issues as mentioned in comments:

  • array resb 10 will reserve space for 10 bytes, but you want to store 10 dwords there (40 bytes). Change to array resd 10 .

  • (Pointed out by Sep Roland) In _loop you have an off-by-one bug; since the inc is done before the mov you will access the dwords at [array+4], [array+8], ... [array+40] , where the last one is out of range. This is like doing int array[10]; for (i=1; i <= 10; i++) array[i]=i; int array[10]; for (i=1; i <= 10; i++) array[i]=i; in C, and is incorrect for exactly the same reason. One fix would be to do mov [array + ecx * 4 - 4], ecx instead.

  • After _loop2 you have jmp print , which will transfer control to print and never come back. Since you apparently want to call print as a subroutine and continue executing with add ecx, 1; cmp ecx, 10 add ecx, 1; cmp ecx, 10 , etc, you need to call print instead of jmp . And also uncomment the ret at the end of print so that it will actually return. Subroutines in assembly language don't automatically return unless you actually execute ret ; otherwise the CPU will just continue executing whatever garbage happens to be next in memory.

  • You have a push ecx to save the value of ecx before the call to printf , which is good since printf will overwrite that register, but you need to pop ecx afterwards to get that value back and put the stack back to where it was.

    Specifically, the pop ecx should follow the add esp, 8 ; a stack is a last-in-first-out structure, and the push ecx was before the pushing of the printf arguments, so you need to pop ecx after removing those arguments from the stack.

  • The mov eax, 0 as a return value at the end of print is unnecessary since you never use it anywhere else.

With these changes the code works as it should.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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