我正在尝试编写一个简单的NASM程序以获得乐趣,但我似乎无法弄清楚如何在其中编写for循环。使用以下代码,我得到一个分段错误。以下代码应打印出“Hello world!”然后是从1到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
答案 0 :(得分:2)
在跳转到循环之前,您将0分配给ECX ...
这意味着您的程序将尝试打印位于内存地址0的字符串,这是您不拥有的字符串,因此会出现分段错误...
请记住,您正在处理内存地址。 将10分配给寄存器值实际上不会以ASCII格式打印10 ...这只是意味着你得到了内存地址10 ...
答案 1 :(得分:0)
你有两个问题:首先,你的系统调用exit()来自循环之前,而不是之后;第二种是传递一个整数而不是一个指向write()系统调用的内存指针。
请改为尝试:
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
这是一个格式化数字并打印循环计数器的版本:
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
答案 2 :(得分:0)
您的代码存在的问题是您尝试将整数打印为dword。 我宁愿像这样使用printf:
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