在Linux上尝试在NASM中编写循环时出现分段错误

时间:2011-03-18 22:13:50

标签: linux assembly x86 nasm

我正在尝试编写一个简单的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

3 个答案:

答案 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