NASM - The Netwide Assembler

NASM Forum => Using NASM => Topic started by: dstudentx on April 11, 2010, 09:40:20 PM

Title: What am I doing wrong
Post by: dstudentx on April 11, 2010, 09:40:20 PM
why can't I store a integers into and array, well two arrays for that matter.

all I'm trying to do is store user input (integers) into an array, then store another set of user input of integers into another array.  my first while loop ends after three inputs and my second while loop ends after 1 input.  and only the last integer input seems to be stored into the array.
Code: [Select]
%include "asm_io.inc"

%define ARRAY_SIZE 100
segment .data
Message         db      "Welcome ", 0
Message1 db "" ,0
Message2 db "Please enter doublewords for the first array. " , 0
Message3 db "Are there more inputs(1 (yes) or 0)?  " , 0
Message4 db "Please enter doublewords for the second array.", 0
Message5 db "The first array is: " , 0
Message6 db   "  " , 0
Message7 db "The second array is: " , 0
segment .bss
runAgain        resd    1                     ; find primes up to this limit
firstArray      resd ARRAY_SIZE               ; the current guess for prime
secondArray     resd ARRAY_SIZE
compar resd    1

segment .text
        global  asm_main
asm_main:
        enter   0,0                           ; setup routine
        pusha

call    print_nl       ;printing a new line
        mov   eax,  Message     ;putting first message in eax for output
        call    print_string      ;printing first message
call    print_nl      ;printing a new line

mov  eax,  Message1      ;putting 1st message in eax for output
        call    print_string      ;printing 1st message
   call    print_nl      ;printing a new line

mov   eax,  Message2      ;putting 2nd message in eax for output
        call    print_string      ;printing 2nd message
call    read_int      ;reading in user input
mov  [firstArray], ax      ;storing input in a array
   call    print_nl      ;print new line

mov   eax,  Message3      ;putting 3rd message in eax for output
        call    print_string      ;printing 3rd message
        
        call    read_int                      ;reading int for new run
        mov   [runAgain], eax      ;storing input in eax


while_first_Array:                            ; while ( runAgain <= 1 )
        mov     eax,[runAgain]      ;moving runAgian to compar for the loop
        cmp     eax, 1      ;comparing to see if loop ends
mov     [runAgain],0
mov     eax,  Message2      ;putting 2nd message in eax for output
        call      print_string      ;printing 2nd message
call   read_int      ;reading in user input
mov   [firstArray+4],ax      ;storing input in array
   call     print_nl      ;printing new line

mov     eax,  Message3      ;putting 3rd message in eax for output
        call       print_string      ;printing third message        
        call       read_int                  ;reading in input for loop check
        mov     [runAgain], eax              ;storing in eax for loop check

       jnbe    end_first_Array          ; use jnbe since numbers are unsigned
end_first_Array:          ;end of loop

mov     eax,  Message4      ;putting 4th message in eax
        call      print_string              ;printing fourth message
call      print_nl      ;printing a new line

while_Second_Array:                           ;while ( runAgain <= 1 ) for second array
        mov     eax,[runAgain]      ;moving runAgian to compar for the loop
        cmp      eax, 1                      ;moving runAgian to com

mov     eax,  Message2      ;putting 2nd message in eax for output
        call      print_string              ;printing 2nd message
call   read_int              ;reading in user input
mov   [secondArray+4],eax      ;storing input in array
   call      print_nl      ;printing a new line

mov     eax,  Message3      ;putting 3rd message in eax for output
        call      print_string      ;printing third message  
        
        call      read_int                  ;reading in input for loop check
        mov     [runAgain], eax              ;storing in eax for loop check

       jnbe    end_Second_Array               ; use jnbe since numbers are unsigned
end_Second_Array:    
Title: Re: What am I doing wrong
Post by: Frank Kotler on April 12, 2010, 02:53:23 AM
Same thing(s) you were doing wrong last time we spoke! :)

while_first_Array:                            ; while ( runAgain <= 1 )
        mov     eax,[runAgain]            ;moving runAgian to compar for the loop
        cmp     eax, 1               ;comparing to see if loop ends

Okay, you've set the flags...

   mov     [runAgain],0

Dude! This doesn't even assemble!

   mov     eax,  Message2            ;putting 2nd message in eax for output
        call      print_string            ;printing 2nd message
   call      read_int            ;reading in user input   
   mov      [firstArray+4],ax         ;storing input in array

Why ax? Why "firstArray + 4"... every time?

     call     print_nl             ;printing new line

   mov     eax,  Message3            ;putting 3rd message in eax for output
        call       print_string            ;printing third message       
        call       read_int                      ;reading in input for loop check
        mov     [runAgain], eax                 ;storing in eax for loop check

       jnbe    end_first_Array              ; use jnbe since numbers are unsigned

Having set flags waaay back at the beginning of this section, you expect 'em to still be set? Well... Dr. Carter considerately preserves flags in his functions, and none of the instructions you use happen to set flags... so I quess they are... So you've compared "[runAgain]" to one, and you're going to jump if it's not below or equal. When will that be? (if the user misbehaves and enters 2 when you ask for 1 or 0, I guess) What happens if the jump is not taken?

end_first_Array:                    ;end of loop

Answer: you fall through into second_array... And at the end of that... you fall off the end of your program into the puckerbrush! By some mechanism I don't understand, after a few nops, this hits "call asm_main" (in main, presumably?), and we start off again with "Welcome". I'd expect this to just-plain-crash, and I have no idea why it's re-running the program, but that's what you're doing wrong.

I suggest you re-read (or maybe just read) Dr Carter's chapter on arrays. It's a handful, I'll give ya that! When I first(?) read it (not "in order"), I thought he was crazy, teaching 'em about arrays, and just now introducing the addressing mode required to do it. But... arrays are pretty much what the addressing mode is "good for", so I guess it's appropriate to introduce 'em together. Pay special attention to the example code!

Maybe I should take that back... his "array1.asm" uses that special version of "driver.c", and calls scanf directly. That complicates the situation somewhat. Scanf takes the address to store the integer as a parameter, so you're not doing "get the result, store it in an array" like you want...

Try this example instead:

Code: [Select]
;
; file: arraytest.asm
;
; for Linux:
; nasm -elf -d ELF_TYPE arraytest.asm
; gcc -o arraytest arraytest.o driver.c asm_io.o
;
; other OSen? RTFM

; http://www.drpaulcarter.com/pcasm
%include "asm_io.inc"

%define ARRAY_SIZE 10 ; enough for test purposes

;
; initialized data is put in the .data section
;
section .data
;
; These labels refer to strings used for output
;

prompt1 db    "Please enter a number. ", 0
querry  db    "More to enter? (y/n)", 0
outmsg1 db    "You entered ", 0

;
; uninitialized data is put in the .bss section
;
section .bss
;
; These labels refer to double words used to store the inputs
;

input1  resd ARRAY_SIZE

;
; code is put in the .text section
;
section .text
        global  asm_main
asm_main:
        enter   0,0               ; setup routine
        pusha

        xor ecx, ecx ; element number
.top:
        mov     eax, prompt1      ; print out prompt
        call    print_string

        call    read_int          ; read integer

; store it in "element ecx".
        mov [input1 + ecx * 4], eax
        inc ecx ; next element
cmp ecx, ARRAY_SIZE - 1
ja .show_em ; if we run out of space, quit and print 'em
.ask:
mov eax, querry
call print_string

call read_char ; flush trailing garbage from i/o buffer???
call read_char
cmp al, 'y'
je .top
cmp al, 'n'
jne .ask

;
; next print out result message as series of steps
;

.show_em:

        mov     eax, outmsg1
        call    print_string      ; print out first message

; ecx still holds the count of elements we entered
xor ebx, ebx ; start with index zero
.more:
        mov     eax, [input1 + ebx * 4]     
        call    print_int         ; print out input1

mov al, ' ' ; (or other spacer)
call print_char

        inc ebx ; next index into array
loop .more ; do 'em all

        call    print_nl          ; print new-line

        popa
        mov     eax, 0            ; return back to C
        leave                     
        ret
;------------------------------------------

Don't ask me why I had to call read_char twice. I can see why you were going for 0 or 1. I think maybe that "dump_line" routine needs to go into the regular "driver.c", and perhaps get called more often...

In any case, that should show you how to store an integer in an array, without them all being in the same place. Re-read that chapter anyway!

Best,
Frank