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.