You should not completely disregard the print command. I think you will get a better understanding if know why your camera shakes.
Use "set cursor 0,0" somewhere in your main loop. Whenever you use print command the cursor automatically starts next time round on the next line down, on the far left side. If you use set cursor command prior to a print command, text will appear at coords given. You need to use set cursor at least once if you use print command in a loop, otherwise the cursor ends up offscreen which is what you are seeing when the camera shakes.
The thing with text command is that you have to set the coords each time no matter what. Sometimes I just want to bring values to screen as its quicker than debugging so I`ll call set cursor once in the main loop and print the values in a column on the left. It has its uses.
For FPS you only need a string conversion if you choose to use the text command, if you use print command you can just print the value to screen as the variable is numerical. In your case you wish to draw two numerical values to screen. For this I would use the print command. Drawing any text to screen can be slow(depends on what else the prog does) using DBP commands, so I would think that the string conversion would add to this time, in this case unnecassarily. I too would remove the sync from this nested loop, and place it in the main loop, but only to ensure it only ever gets called once per main loop and that its at the end of the loop. I would guess that if your Ammoview routine is the last in the mainloop to get called, then leaving sync where it is now might be ok - I would still put it in main loop though;
AmmoView:
set cursor 0,0
print screen fps()
Print "Ammo: ", Ammo
Return