[英]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
,您有一个错误; 由于inc
在mov
之前完成,您将访问[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.