简体   繁体   中英

Segmentation faults doing nested loops in assembly

I'm writing an assembly program for an assignment where I need to take an array, let's say

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

and I need to loop through it and print a star corresponding to the number in the array. So in the example above the program should output:

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

My problem is I'm getting Segmentation faults somewhere in the code and I can't pinpoint where. Anyone have any idea where this is happening?

code:

%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

First off, the ret you have at the end, is not the correct way to end your program! In Windows, you would use ExitProcess or call exit if you are linking to the C library. In Linux, you would use int 80H - sys_exit or syscall - 60 or exit if you are linking to the C Library.

When using nested loops, first get your outer loop working first; print out each value in the array. Once you have that working, add your "inner" loop to print the stars.

In the following code, I use esi and ebx since those must be saved by the callee so we shouldn't need to worry about saving those values.

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

Which would print out the stars as: 明星的东西 according to the array in your source.

If you wanted to make a pyramid, read this

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM