Segmentation fault while trying to write for loop in NASM on Linux
I'm trying to write a simple NASM program for fun, but I can't seem to figure out how to write a for loop in it. With the following code, I get a segmentation fault. The following code is supposed to print out "Hello world!" followed by all of the numbers from one to 100.
section .data
开发者_开发知识库 message: db 'Hello world!', 10
messageLength: equ $-message
section .text
global _start
_start:
mov eax, 4
mov ebx, 1
mov ecx, message
mov edx, messageLength
int 80h
mov ecx, 0
jmp loop
mov eax, 1
mov ebx, 0
int 80h
loop:
mov eax, 4
mov ebx, 1
mov edx, 1
int 80h
add ecx, 1
cmp ecx, 100
jl loop
Before you jump to the loop, you are assigning 0 to ECX...
It means your program will try to print a string located at memory address 0, which you don't own, hence the segmentation fault...
Remember you are working with memory addresses. Assigning 10 to a register value wont actually print 10, in ASCII... It just means you are getting memory address 10...
You had two problems: first, your syscall to exit() came before the loop, instead of after; second you are passing an integer instead of a memory pointer to the write() syscall.
Try this instead:
section .data
message: db 'Hello world!', 10
messageLength: equ $-message
digits: db '0123456789'
section .text
global _start
_start:
mov eax, 4
mov ebx, 1
mov ecx, message
mov edx, messageLength
int 80h
mov ecx, 0
jmp loop
loop:
push ecx
mov eax, digits
add ecx, eax
mov eax, 4
mov ebx, 1
mov edx, 1
int 80h
pop ecx
add ecx, 1
cmp ecx, 10
jl loop
And here is a version that formats numbers and prints the loop counter:
section .data
message: db 'Hello world!', 10
messageLength: equ $-message
number: db '000'
db 10
section .text
global _start
_start:
mov eax, 4
mov ebx, 1
mov ecx, message
mov edx, messageLength
int 80h
mov ecx, 0
jmp loop
loop:
call _format_number
push ecx
mov ecx, number
mov eax, 4
mov ebx, 1
mov edx, 4
int 80h
pop ecx
add ecx, 1
cmp ecx, 10
jl loop
mov eax, 1
mov ebx, 0
int 80h
_format_number:
push ecx
xor edx, edx
mov eax, ecx
mov ecx, 10
idiv ecx
add edx, '0'
mov ebx, number
mov [ebx+2], dl
xor edx, edx
idiv ecx
add edx, '0'
mov [ebx+1], dl
xor edx, edx
idiv ecx
add edx, '0'
mov [ebx+0], dl
pop ecx
ret
The problem with your code is that you try to print a integer as a dword. I would rather use printf like this:
extern printf ;make sure we can use printf
section .data
message: db 'Hello world!', 10
messageLength: equ $-message
decFormat db '%d',10 ;format string to use in printf
section .text
global main
main:
;print hello world the usual way
mov eax, 4
mov ebx, 1
mov ecx, message
mov edx, messageLength
int 80h
mov ecx, 0
loop:
push ecx ;add counter
push decFormat ;add format string
call printf ;execute printf, which will use the stack values as arguments
pop ecx ;clean the stack
pop ecx
inc ecx ;if you just want to add 1 to the value, you should use inc not add
cmp ecx, 100
jl loop
mov eax,1
mov ebx,0
int 80h
精彩评论