分段错误在程序集中执行嵌套循环

时间:2013-10-06 02:34:45

标签: loops assembly x86 nasm

我正在编写一个程序集程序,我需要一个数组,比如说

array:  DB  1, 2, 3, 4, 5

我需要遍历它并打印一个与数组中的数字对应的星号。所以在上面的例子中,程序应该输出:

* * * * *
  * * * *
    * * *
      * *
        *

我的问题是我在代码中的某个地方遇到了分段错误,我无法确定在哪里。任何人都知道这是怎么回事?

代码:

%INCLUDE    "csci224.inc"

SEGMENT     .data
array:      DB      1, 2, 3, 4, 5, 4, 3, 2, 1
star:       DB      "*",0,10
n:          DB      0

SEGMENT     .text
main:
    mov         edx, 9                  ;length of array
    mov         ecx, 0                  ;loop counter
    jmp         outerloop               ;begin outerloop

outerloop:

    mov         ah, [array+ecx]         ;move (array element + loop counter) to ah

    movzx       ebx, ah                 ;zero extend ah to ebx
    mov         [n], ebx                ;copy value of array element to variable
    mov         eax, ebx

    inc         ecx

    ;call       WriteInt    
    dec         edx
    jnz         innerloop               ;jump to innerloop

innerloop:                              ;cycle through '[n]', printing a star each time
        mov     edi, [n]
        mov     eax, [star]
        call    WriteString             ;print star
        dec     edi                     ;decrement counter
        jnz     innerloop               ;is edi zero? if no, loop again
        cmp     ecx, byte 0             ;if yes, go back to outerloop
        jz      outerloop


    ret

1 个答案:

答案 0 :(得分:1)

首先,你最后的ret不是结束你的程序的正确方法!在Windows中,如果要链接到C库,则可以使用ExitProcess或调用exit。在Linux中,如果要链接到C库,则可以使用int 80H - sys_exitsyscall - 60exit

使用嵌套循环时,首先让外循环工作;打印出数组中的每个值。完成后,添加“内部”循环以打印星星。

在下面的代码中,我使用esiebx,因为这些必须由被调用方保存,因此我们不必担心保存这些值。

extern printf, exit
global main

SEGMENT     .data
array:      DB      1, 2, 3, 4, 5, 4, 3, 2, 1
array_len   equ     $ - array
star:       DB      "*", 0

SEGMENT     .text
main:
    mov     esi, 0                  ;loop counter

.ArrayLoop:
    ;~ Get array value to use as PrintStars loop counter, esi is index into array
    movzx   ebx, byte [array + esi]
    ;~ increase ArrayLoop "Outer Loop" counter
    inc     esi
    cmp     esi, array_len
    ;~ if esi > array_len, we are done
    jg      .Done   

.PrintStars:
    ;~ print stars here

    ;~ decrease "Inner Loop" counter
    dec     ebx
    ;~ If ebx != 0, continue "Inner Loop"
    jnz     .PrintStars

    ;~ ebx == 0, print new line char and continue "Outer Loop"    
    ;~ print newline char here
    jmp     .ArrayLoop

.Done:
    call    exit

哪会打印出星星: Star thing根据您的来源中的数组。

如果您想制作金字塔,请阅读this