437 lines
16 KiB
Plaintext
437 lines
16 KiB
Plaintext
MacsBug Tricks
|
||
|
||
Cool MacsBug Tricks
|
||
By Macneil Shonle
|
||
|
||
This guide is to help you in learning to use MacsBug. MacsBug is a system
|
||
|
||
extension that can help you debug your programs, it is free and is
|
||
available
|
||
from Apple Computer. Note that the name MacsBug is an acronym for
|
||
Motorola
|
||
advanced computer systems debuger.
|
||
|
||
This guide is a list of "tricks," but it is just the tip of the iceberg
|
||
of
|
||
the cool stuff you can do. The guide will start off with some easy topics
|
||
|
||
aimed towards beginners and then it will go into some more advanced
|
||
topics.
|
||
All of them are cool. Hopefully after reading this the help part of
|
||
MacsBug
|
||
won't be so intimidating.
|
||
|
||
Number Conversion
|
||
|
||
MacsBug can be used as a quick hexadecimal to decimal converter, and vise
|
||
|
||
versa. I used to use a calculator DA, but now I just simply drop into
|
||
MacsBug and type in the number I want to convert and hit return.
|
||
|
||
Example: You want to find out what 0x3E is in decimal. When in MacsBug,
|
||
type
|
||
in $3E and hit return. This will be the output:
|
||
|
||
$3E = $0000003E #62 #62 '***>'
|
||
|
||
The first number ($0000003E) is the value in hexadecimal that you just
|
||
typed in. The second number is what the value is as an unsigned decimal,
|
||
the third is the signed version. The set of characters in single quotes
|
||
('***>') is
|
||
the ASCII representation of the number, the null character is denoted
|
||
with
|
||
the bullet.
|
||
|
||
You can find out the decimal/hexadecimal equivalent of any ASCII
|
||
character
|
||
by typing the letter balanced between two single quotes.
|
||
|
||
Example: Type in: 'A' and hit return. You will get #65 as your answer.
|
||
|
||
By the way-The dollar sign means that the number is in hexadecimal. Much
|
||
like C's 0xXX notation, $XX is how hexadecimal numbers are represented in
|
||
|
||
assembly. Numbers in MacsBug will default to hexadecimal, except for when
|
||
|
||
the hexadecimal number is a command or a regster. For example: "ea" is
|
||
the
|
||
command to restart the current application, when you type in ea it will
|
||
try
|
||
this command, you must type in $ea in order to avoid this conflict.
|
||
|
||
Similarly, you have to type a # in order to express decimal numbers. You
|
||
can
|
||
use the conversion method just described (type in the number, hit return)
|
||
to
|
||
find out a decimal number's corresponding hexadecimal number and ASCII
|
||
character.
|
||
|
||
What Was My Monitor Size?
|
||
|
||
Here's an impresive way to show a friend how many pixels horizontally and
|
||
vertically they have on their monitor (other than looking at the manual,
|
||
or something silly like that). Drop into MacsBug and type in: dm
|
||
@@MainDevice GDevice. This will show you the struct members of the
|
||
MainDevice (which happens to be a GDevice), you should see the gdPMap
|
||
indented, three lines below it will be bounds with four numbers to the
|
||
right of it. These four numbers are the top, left, bottom and right
|
||
coordinates of the monitor, respectively.
|
||
|
||
The dm command is short for display memory, after you type in dm type in
|
||
the address of the memory you want to display. MainDevice is a system
|
||
global that is a handle (a pointer to a pointer) to the main graphics
|
||
device (the one with the menu bar). The two @@ symbols are how you
|
||
express
|
||
double-indirection in MacsBug, in C you use "*" to express indirection
|
||
(i.e.
|
||
de-referencing) which is in put in prefix notation. People who program in
|
||
|
||
Pascal can use the postfix indirection notation by saying "dm
|
||
MainDevice^^
|
||
GDevice".
|
||
|
||
After you give the dm command the address, you give it the format you
|
||
want
|
||
to see it diplayed as. You can use any number for the number of bytes you
|
||
|
||
want displayed, or you can say "Rect", for instance, to see the first
|
||
eight
|
||
bytes of the memory in the form of a rectangle. You can also use: Byte,
|
||
Word, Long, SignedByte, SignedWord, SignedLong, UnsignedByte,
|
||
UnsignedWord, UnsignedLong, PString, CString, and PixMap, GDevice,
|
||
RGBColor, CGrafPort and any number of other templates you may have
|
||
installed.
|
||
|
||
Example: if you know a rectangle is at address $00058EA6 and you want to
|
||
see what its value is, all you have to do is type in "dm $00058EA6 Rect".
|
||
|
||
|
||
By the way<61>A template a layout of memory that MacsBug knows about (such
|
||
as a C struct or a Pascal record), you can type "tmp" to find out all of
|
||
the
|
||
templates your version of MacsBug has.
|
||
|
||
Don't you hate it when you are working in an application, minding your
|
||
own
|
||
business, when all-of-a-sudden the program quits and the system tells you
|
||
an error of type X occured? There are many applications made where you
|
||
can look up these numbers and find out what went wrong. MacsBug can also
|
||
do this, all you have to do is type error and then the error number. Keep
|
||
in mind that the error numbers the system gives you are decimal (not
|
||
hexadecimal), so you should put a "#" in front of them.
|
||
|
||
Example: The sytem tells you: "An error of type 4 has occured," drop into
|
||
|
||
MacsBug and type "error<6F>#4", MacsBug will then output
|
||
"$0004<30>#4<>zero<72>divide<64>error".
|
||
|
||
Note: This error feature is not in earlier versions of MacsBug, so you
|
||
may
|
||
not have it.
|
||
|
||
The Simple Calculator You can use MacsBug as a simple calucator. Let<65>s
|
||
say
|
||
you need to know what seven times seventeen is, type in "#7<>*<2A>#17", and
|
||
hit return. The number 119 should now be on your screen. It will be
|
||
hidden in
|
||
the line:
|
||
|
||
#7 * #17 = $00000077 #119 #119 '<27><><EFBFBD>w'
|
||
|
||
The lower case letter w is the 119th ASCII character, as the previous
|
||
line
|
||
shows us. Let's try another example, how about five plus six? You would
|
||
type
|
||
in "#5 + #6", and hit return. You should then see:
|
||
|
||
#5 + #6 = $0000000B #11 #11 '<27><><EFBFBD><EFBFBD>'
|
||
|
||
MacsBug can also handle multiple operations at a time, like five plus six
|
||
|
||
plus ten. If you want to say something like five plus six times four
|
||
remember to put parentheses around the apropiate numbers. MacsBug has no
|
||
concept of orders of operations and it's quite possible for it to add
|
||
before
|
||
it multiplies. So say this: "#5<>+ (#6<>*<2A>#4)", which equals #29, instead
|
||
of
|
||
"#5<>+<2B>#6<>*<2A>#4", which equals #44.
|
||
|
||
You can use +, -, *, /, MOD for arithmetic operations. You can use AND
|
||
(or
|
||
&), OR (or |), NOT (or !), XOR for boolean operations. And you can use =
|
||
(or
|
||
==), <> (or !=), <, >, <=, >= for equality operations.
|
||
|
||
If you type in "#5<>+<2B>#4<>=<3D>#9" MacsBug will give you a one, meaning that
|
||
the equality you just said was true. If you said "#5<>+<2B>#4<>=<3D>#10", Macsbug
|
||
will give you a zero, meaning that the equality five plus four equals ten
|
||
is
|
||
false.
|
||
|
||
Moving the Cursor Here is a cool trick to move the cursor. It done by
|
||
setting memory, the mouse tracking variables specifically. But I'd like
|
||
to
|
||
talk about setting memory beforehand. There are four commands in MacsBug
|
||
to set memory: SB (set byte), SW (set word), SL (set long), and SM (set
|
||
memory). You give each of these commands an address first, and then the
|
||
values of what you want to set the memory to. Example: There is a byte
|
||
that
|
||
you have the address of that you want to set to ten, you should type in:
|
||
|
||
SB $XXXXXXXX #10
|
||
|
||
where $XXXXXXXX is the address of the byte. Another example: There is a
|
||
long
|
||
that you have the address of that you want to set to "$4D616320", you
|
||
should
|
||
type in:
|
||
|
||
SL $XXXXXXXX $4D616320
|
||
|
||
again, where $XXXXXXXX is the address of the long. You can use the SM
|
||
command the same way in the case that the length you want to set is not
|
||
1, 2
|
||
or 4 bytes long. You can use SW when you want to set a word (2 bytes).
|
||
|
||
If you are familiar with Points (the vertical and horizontal coordinates
|
||
of
|
||
a point on the graf plane), you should know that they take up four bytes
|
||
in
|
||
memory. The high two bytes (the high word) is the vertical coordinate,
|
||
and
|
||
the low two bytes (the low word) is the horizontal coordinate. There are
|
||
two
|
||
global variables that are both Points, one called MTemp, the other called
|
||
|
||
RawMouse, these variables are the information the Macintosh uses for
|
||
controling the cursor. You can set these points by using SL.
|
||
|
||
There is also a byte called CrsrNew, set this byte to 1 when you want to
|
||
notify the Macintosh that the cursor posistions have changed. This is how
|
||
|
||
you move the mouse to point (5,<2C>6), near the upper-left corner of the
|
||
screen:
|
||
|
||
SL MTemp $00060005 SL RawMouse $00060005 SB CrsrNew #1
|
||
|
||
Make sure MTemp and RawMouse have the same value. Now type Command-G to
|
||
see your newly moved cursor.
|
||
|
||
Recovering from a Hung Serial Port
|
||
|
||
Sometimes when you're AppleTalking or modeming and something goes wrong
|
||
(like you switch the modem off while data is being sent to it), the
|
||
comptuer
|
||
will hang. The mouse will still move, but clicking will have no effect.
|
||
Here's the solution:
|
||
|
||
Drop into MacsBug. You should see the routine name "_vSyncWait" plus
|
||
something as the current location. If you don't, you probably hit the
|
||
system
|
||
while it was doing something else. Hit Command-G to get back out of
|
||
MacsBug, and try again. After a few tries you should find _vSyncWait.
|
||
|
||
_vSyncWait is the routine that the system uses to wait for some input
|
||
from a serial port. If you can read assembly code, you'll see that it's
|
||
pretty
|
||
simple. Here's the dump of the significant part:
|
||
|
||
+0000 4080BB8C MOVE.W $0010(A0),D0 |
|
||
3028 0010
|
||
+0004 4080BB90 BGT.S _vSyncWait ; 4080BB8C |
|
||
6EFA
|
||
|
||
Register A0 is pointing to a system data structure, in which a word will
|
||
be
|
||
cleared when the awaited input arrives. The MOVE.W instruction grabs this
|
||
|
||
word and puts it into register D0. The BGT.S instruction then Branches
|
||
back
|
||
to the MOVE.W if the byte it just fetched is Greater Than zero. So it
|
||
happens that this byte is never going to arrive for whatever reason, but
|
||
the
|
||
computer is going to wait for eternity. The secret to fixing this is to
|
||
use
|
||
Command-T to go step along until the MOVE.W instruction is displayed as
|
||
the
|
||
current instruction. Now use the sw command to set "@(A0+10)" to zero:
|
||
|
||
sw @(A0+10) 0
|
||
|
||
Hit Command-T twice more. The MOVE.W instruction will take the zero you
|
||
just set into memory and put it in D0, so the D0 display on the left of
|
||
the
|
||
screen should have its right four digits all zeros. Then when you execute
|
||
|
||
the BGT.S instruction, it should not go back to the MOVE.W since zero is
|
||
not
|
||
greater than zero.
|
||
|
||
Hit Command-G to go. If this was the only byte the software was waiting
|
||
for, then it should continue running, although it may go a little crazy
|
||
because
|
||
it's been suddenly disconnected from whatever peripheral it was talking
|
||
to.
|
||
Quit the program, fix your hardware, and try again.
|
||
|
||
Shameless Strobe Light Trick
|
||
|
||
Okay, this is a really useless trick, but it's cool for at least a little
|
||
|
||
while. Go into MacsBug. If you have a single screen type in "swap", the
|
||
console should then say "Display will be swapped after each trace or
|
||
step",
|
||
if it doesn't type in "swap" again. Swapping is when the screen switches
|
||
from the MacsBug console to the normal Macintosh screen. We want it to
|
||
swap after each trace or step, which is what we just did up above. Now we
|
||
need it to step, thereby swapping the screen, the "s" command (the step
|
||
command) is just what we need to do this. We want this to happend more
|
||
than once, so we type in: "s 100", which steps 100 times. Enjoy the show.
|
||
|
||
|
||
Warning: Swapping with a number like 1000 can render some machines, like
|
||
my PowerBook 165c, useless until it is all over with, so keep the numbers
|
||
low or the patience high.
|
||
|
||
GetKeys from within MacsBug
|
||
|
||
There is a routine in the Macintosh toolbox called GetKeys, this routine
|
||
is
|
||
great for game programmers who want a reasonably fast way to read the
|
||
keyboard, without using (slower) events. The problem for C and C++
|
||
programmers using this routine is that the KeyMap type is a Pascal packed
|
||
|
||
array. Each bit of the packed array is designated to a certain key, the
|
||
bit
|
||
is set to 1 if the key is down, and set to zero if the key is up. This
|
||
array
|
||
takes up 16 bytes (128 bits). C cannot access the elements of the packed
|
||
array like a normal array, so the programmer has to mask out some bits to
|
||
|
||
get the result that he/she wants. There is a desk accessory named
|
||
"GetKeys,"
|
||
that is made just for this case. The problem is, you might not be on a
|
||
machine with that program on it.
|
||
|
||
Good thing MacsBug is able to help us. Here is how you locate the bit for
|
||
|
||
the letter "M": go into MacsBug and type in "dm KeyMap", but don't hit
|
||
return just yet. Now strike the escape key, this should swap the screen.
|
||
Press and hold down the letter "M" on your keyboard, this should swap the
|
||
|
||
screen back. Now, while still holding down "M", press return. This is
|
||
what
|
||
you should see:
|
||
|
||
Displaying memory from 0174
|
||
00000174 0000 0000 0040 0000 0000 0000 0000 0000 <20><><EFBFBD><EFBFBD><EFBFBD>@<40><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
|
||
The number "00000174" is the address of the KeyMap global variable. The
|
||
next set of numbers <20>0000<30>0000<30> is the first element of the C version of
|
||
the array, in other words, it<69>s: "keyMap[0]". The next set of numbers
|
||
"0040<34>0000" is the second element of the array, keyMap[1]. The next group
|
||
of 8 hexadecimal digits is the third element (keyMap[2]), and the last
|
||
group of 8 hexadecimal digits is the fourth element (keyMap[3]). The
|
||
series of
|
||
bullets is what the array looks like in ASCII form. In the second group
|
||
("0040<34>0000") there is a 4 in the midst of all of those zeros. This is
|
||
the
|
||
bit that is set to 1 whenever the "M" key is held down. So, to see if the
|
||
|
||
"M" is down from within C we will do this:
|
||
|
||
KeyMap keyMap;
|
||
GetKeys( keyMap );
|
||
|
||
if( keyMap[1] & 0x00400000 )
|
||
{ DoMKeyDown();
|
||
|
||
The Lost Paper
|
||
|
||
I was once typing in some text in a word processor, when the computer
|
||
suddenly crashed on me. I didn't save a copy on to the hard-disk yet. I
|
||
had
|
||
to restart the computer and type it all over again. But wait, the paper
|
||
is
|
||
still in the machine I thought to myself. You see, when you restart, all
|
||
of
|
||
the computer's memory doesn't get cleared, it just stays to what it was
|
||
until it gets replaced with other information, much like the behavior of
|
||
a
|
||
hard-disk. I had one thing going for me, I had MacsBug installed. Here
|
||
are
|
||
the steps I took to recover the paper:
|
||
|
||
First, I logged all of the work I was doing in MacsBug to a file. I did
|
||
this
|
||
using the log command. All you need to give the log command is the name
|
||
of
|
||
the new file to log to. I named it MyPaper. Good, now all of my MacsBug
|
||
session will be on the hard-disk so I can open it up with a normal text
|
||
editor when I'm done.
|
||
|
||
Next, I needed to find where in memory my paper was. I did this using the
|
||
|
||
"f" command. The first two parameters for this command is the range in
|
||
memory in which you want MacsBug to search through. I wanted to search
|
||
through all of my memory, which is 8 megs on my machine, so I typed in:
|
||
"f<>0<EFBFBD>(400<30>*<2A>400<30>*<2A>8)<29>"any string". Where 0 is the beginning of memory and
|
||
8 megs is the top of it. (Note: "400<30>*<2A>400" is exactly one megabyte of
|
||
memory.) The last parameter is the search string, balanced between two
|
||
single quotes. I wanted to pick a distinct string, otherwise I would have
|
||
|
||
found other parts of memory, which would take longer to do. I knew the
|
||
most
|
||
famous mammal, the aardvark, was mentioned in my paper, so I typed in
|
||
this
|
||
for the find command:
|
||
|
||
f 0 (400 * 400 * 8) "aardvark"
|
||
|
||
MacsBug then started searching for me. It came up with a small memory
|
||
dump of something with the word arrdvark in it, but the words after it
|
||
were not mine, which meant that I found another part of memory instead of
|
||
my paper. I hit return to tell MacsBug to keep on searching. MacsBug then
|
||
came up with a dump from my paper:
|
||
|
||
Searching for "aardvark" from 00000000 to 007FFFFF
|
||
00358200 6161 7264 7661 726B 8000 0000 0000 002C aardvark answer
|
||
|
||
Which was very good news indeed! This told me that the string "aardvark
|
||
answer" could be found at address 00358200. (I got this address from the
|
||
leftmost number given.)
|
||
|
||
Now that I knew where it was, the rest my task would be easy. I used
|
||
MacsBug's display ASCII command to show me what came after it, by typing
|
||
in: dma 00358200. You might not have this command, in which case you'll
|
||
have to use plain old dm, instead of dma. I hit return until my paper was
|
||
done beingdisplayed.
|
||
|
||
Note: You can subract a number from the address to see what was before
|
||
it.
|
||
|
||
I then typed in "log" again, which closed my log. Finally, I went out of
|
||
MacsBug and opened the log file with SimpleText. Remember, the log had my
|
||
|
||
whole session not just the paper so I had to delete the addresses and
|
||
such
|
||
from it, which really isn't that hard to do, if you know how to use your
|
||
mouse and your delete key efficiently. The paper was saved.
|
||
|
||
Warning: In your search you might stumble upon MacsBug's very own memory,
|
||
|
||
with its own copy of your search string. To get out of this loop, start
|
||
the
|
||
search over again with the base search address being outside of MacsBug's
|
||
|
||
memory.
|
||
|
||
Credits
|
||
|
||
The authors of this are Macneil Shonle and Dustin Mitchell of The Syzygy
|
||
Cult, a programming group that makes games and utilities. Dustin reviewed
|
||
|
||
this and submitted the Recovering from a Hung Serial Port section, thanks
|
||
|
||
Dustin!
|
||
|
||
Email MacneilS@aol.com if you have some input on how I can make Cool
|
||
MacsBug Tricks even better; nothing is too small to mention. Thanks for
|
||
reading!
|