gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

ASM > A Little ASM Help(80x86)

#144103 - jake2431 - Mon Oct 29, 2007 3:38 am

I need some help with my ASM homework, if you guys don't mind. I am writing code to find the average of numbers stored in an array, but I am getting 0 when it should be 89(if I remember correctly). I have stepped through it with a debugger, but since I am linking the files I can't follow my variables (not sure how to just watch the memory). Stepping through, everything looks from (I even get the average) until the computer travels from the procedure to the main program again. Somehow I don't think I ever stored it in my average variable. I don't need another way to do it, as the code I have is how the teacher wants us to program it (we are learning how to pass local variables as arguments to the procedure. My books is hard for me to understand, so after working on it for a while, I would like to ask for you guys help.

The main program:
Code:

;Jake Johnson
;Programming exercise 6.3 #3
;main

.386
.MODEL FLAT

ExitProcess PROTO NEAR32 stdcall, dwExitCode:DWORD

INCLUDE io.h            ; header file for input/output

.STACK  4096            ; reserve 4096-byte stack
EXTERN   Avg:Near32   ;make external procedure available

.DATA                   ; reserve storage for data
   string   BYTE   "The average of the grades is: ", 0
   see      BYTE   11 DUP   (?)
         BYTE   0
   string6 BYTE   40 DUP (?) ;use to pause without exiting program
   array   DWORD   80,95,70,100,100 ;setup array
   count   DWORD   5
   average   DWORD   0

.CODE                           ; start of main program code
_start:
      lea      ebx, array      ;get address of array (parm 1)
      push   ebx
      push      count         ;(parm 2): number of ints in array
      lea      ecx, average   ;get address of average(parm 3)
      push   ecx
      
      call   Avg            ;call procedure
      
      add      esp,16
      output  string
      dtoa   see, average   ;convert average to ascii for display
      output   see
      input   string6, 40

        INVOKE  ExitProcess, 0  ; exit with return code 0

PUBLIC _start                   ; make entry point public

END                             ; end of source code


The Procedure:

Code:

;Jake Johnson
;Programming exercise 6.3 #3
;procedure

.386
.MODEL FLAT

.STACK 4096
PUBLIC Avg      ;make Avg public
.CODE

Avg      PROC   NEAR32
         push   ebp         ;establish stack frame
         mov      ebp, esp   
         pushad            ;save all registers
         pushf            ;save flags
         mov      eax, 0      ;clear out eax
         mov      ebx, 0      ;clear out ebx
         mov      ecx,[ebp+16]   ;get address of array
      startLoop:
         cmp      eax, [ebp+12]   ;compare eax to number of elements in array   
         je      endLoop
         add      ebx, [ecx]   ;add element to ebx
         add      ecx, 4      ;get next element in array
         inc      eax
         jmp    startLoop
      endLoop:
         mov      eax, ebx   ;get average
         mov      ecx,[ebp+12]
         cdq   
         div      ecx
         mov      [ebp+8], eax
         popf            ;restore register values
         popad
         mov      esp, ebp   ;restore esp
         pop      ebp
         ret               ;return
Avg      ENDP
END


P.S. If this should be in the OffTopic forum, since it isn't GBA or NDS related, feel free to move it. I just thought since it was ASM, well... :-)

#144112 - jake2431 - Mon Oct 29, 2007 5:29 am

Oh, and what windows debuggers do you guys use. I am using windbg for this class, but I didn't know if there was a better one.

#144140 - gmiller - Mon Oct 29, 2007 2:55 pm

look at how you set the return value using the pointer to your answer ....

BTW: this is for ARM assembly not x86 so you might not get many answers. I just glanced at it and saw the error with the return value I did not look to see if your divide was correct.

#144150 - kusma - Mon Oct 29, 2007 5:41 pm

Why don't you step through the routine in your debugger to see where it fails?

#144154 - jake2431 - Mon Oct 29, 2007 6:15 pm

I did step through with the debugger, but since it is multiple source files, I don't know how to watch my average variable in memory. I have to use the disassembler and watch registers. I get the right answer until I leave the procedure, but I finally figured it out. Thanks for the help guys.

Sorry, I should have posted in OffTopic.

#144158 - gmiller - Mon Oct 29, 2007 7:30 pm

Good, the address was on the stack and you needed to get that address and then indirect address it ...

#144162 - keldon - Mon Oct 29, 2007 8:32 pm

I use RosAsm for my assembler. It's macro system allows for amazing things, like ...

Code:

L1:
   jmp L1>
L1:


Basically labels in the form of [character][number] can appear multiple times in a file and you decide by direction. This allows for further features that are self explanatory when you begin to use it.

Also its IDE has a built in debugger, fairly good disassembler and is just great. The Nessie emulator was written entirely in RosAsm!

#144178 - gmiller - Mon Oct 29, 2007 11:20 pm

If you happen to have Visual Studio then you can use it to create and debug ASM files. To get it to assemble in 2005 you will need some custom steps defined, but it is pretty simple. My students use it to debug assembly calls from C and C++.

#144183 - jake2431 - Mon Oct 29, 2007 11:59 pm

Thanks for the help, guys. That RosAsm looks really cool keldon.