Using NM.EXE

I recently had a panic attack whereby I thought I had run out of RAM for my game. To fix the problem I needed to determine exactly how much RAM it occupies. Finding out the true size of your program isn't too easy. If you just go by the size of the MAIN file you're leaving out all the unitialized variables and arrays. Since these structures don't actually contain data at compile-time, GCC doesn't allocate space for them within MAIN. This actually is a good thing since it saves you download time; there's no need to transmit a bunch of zeroes anyway. But it makes determining your program's true size difficult.

While sulking about my realization that my game had hit a major snag, I started perusing the contents of the GCC folder. In the "bin/" area is a little utility called nm.exe. I have no idea what it stands for, but this little bugger saved me from hours of frustration.

You invoke it giving the name of your MAIN file:

  D:\DSI\EV> nm main

The output is a list that gives you the starting addresses of all functions, global variables, arrays, or anything else that takes up RAM (and is static of course - it doesn't give the address for variables allocated at runtime since it obviously doesn't know them). The output looks something like this:

  8002d4d8 A ApplyMatrix
  8002cde0 A ApplyMatrixLV
  8002d528 A ApplyMatrixSV
  80063f9c A CLIP2
  8003c388 A CdPlay
  8003bf60 A CdRead
  8003c2b4 A CdReadExec
  8003c14c A CdReadFile
  8003c068 A CdReadSync
  8003b198 A CdSearchFile
  800282e0 A ClearImage
  8002c898 A CompMatrix
  8002814c A DrawSync
  80042f28 A EnterCriticalSection

It continues on but you get the idea. This list is in alphabetical order. That's not entirely useful for our purposes so I'd recommend putting it through "sort" first:

  D:\DSI\EV> nm main | sort > nm.out

I also redirected output to a file so it's easier to read. So then you end up with a list ordered by address:

  800100c8 A GetPadBuf
  8001012c A TestCard
  80010700 A InitHeap
  80010754 A malloc
  80010924 A free
  8001095c A realloc
  800109f0 A calloc
  80010c90 A SsGetMute
  80010cb4 A SsGetMVol
  80010d34 A SsGetSerialAttr
  80010dcc A SsGetSerialVol
  80010ea0 A SsSetMute
  80010ee0 A SsSetMVol
  80010f30 A SsSetSerialAttr

This is somewhat interesting since it tells you the exact addresses and sizes of all the library functions. You could use this information to selectively overwrite the library routines you don't use with your own data (if you're really in dire need of space).

The more interesting part is farther down where it gets to your actual code. In my case, my code starts at 80012000:

  80120000 T byte_to_hex
  80120000 T eprol
  80120000 T _ftext
  801201a8 T print_mem_loc
  801202e0 T screen_grabber
  801204a8 t sg_init
  801205dc t sg_pad_inc
  801206f4 t sg_resize
  80120920 t sg_move
  80120b38 t sg_transmit
  80121030 T msg_handler
  80122854 T msg_init
  80122a04 t msg_char_adjust

You should be able to recognize the names of your own functions.

Now back to my running-out-of-RAM problem. When I scanned down the list of addresses I saw the following:

  80159c30 b menu_sprt
  80159c60 B pad_state
  80159ca0 B scrngrab_buffer
  80160ee0 A _gp
  801efca0 B menu_sprites
  801f01a0 B map
  801f01d0 B tv_text_border_array

Whoa! Judging by the difference between the address of scrngrab_buffer and menu_sprites, the buffer is sucking up 600k of space!

My routine to take screen shots allocates a lot of room and I had forgotten to take it out of my program. Once I killed it my RAM problem was solved!

Another thing I find useful is being able to spot structures that occupy lots of room. For instance:

  801626d0 B WorldOT
  80162700 B obj_array
  8016bf00 B prev_pad
  8016bf10 B hud_extra_outline

I have a structure named obj_array which has 512 entries. As you can see it occupies about 36k of space. If I could somehow reduce the structure so that each element takes up 8 bytes less, I could save 4k of that space (512 * 8 bytes).

Overall nm.exe is a good way of profiling your program to find out where your Yaroze memory is being used.


This web page and all other pages on this site are © 1998 Scott Cartier