Simple SSH over Back To My Mac

December 3, 2010
Tags: ,

If you use Back To My Mac, and often ssh to your machines, you can save a lot of typing by adding the following to your ~/.ssh/config file[1]:

Host *.«account»
ProxyCommand /usr/bin/nc -6 "%h".members.mac.com %p

From that point on, you can ssh to your machines with:

ssh «machine».«account»

For instance, I have a machine called “ccox-imac”, and I can ssh to it with:

ssh ccox-imac.clarkcox3

And this also works with anything that sits atop of ssh, such as

  • git – git clone ccox-imac.clarkcox3:/somerepo.git
  • svn – svn co svn+ssh://ccox-imac.clarkcox3/somesvnrepo
  • bbedit – bbedit sftp://ccox-imac.clarkcox3//etc/sshd_config
  1. where «account» is your MobileMe account name []
0

Woman in Technology

July 29, 2010

I just got finished reading the blog post Woman in technology, where Nicole Sullivan explains some of the issues she and others have faced in a male-dominated industry. (I’m posting here because comments are disabled for her post).

While I don’t deny that there are problems of discrimination (some of her examples made my stomach turn), I do have problems with a few of her proposed solutions:

Video games are largely made by and for men. We need to be willing to rethink the genre completely, bust things wide open to make video games appeal more to girls.

I think this is backwards (or is, at the very least, a chicken–and–egg problem). People write and design games that they would like to play, so it seems natural that male designers would write games that would appeal to male gamers. Making video games “appeal more to girls” seems condescending to me; that’s like claiming that we need to make video games “appeal more to black people”.

CS education works best for people who already know how to code before they begin. CS teaches the theory behind a practice in which they assume you already have some skill. Women are less likely to already know, because they don’t play video games as much. In addition, code-cowboys among their classmates are likely to judge them harshly for being a beginner. Are psychology majors expected to already know how to psychoanalyze patients before their first semester?

No, psychology majors aren’t expected to already know how to psychoanalyze patients, but they are expected to have some kind of interest in the subject that they are majoring in. If someone wants to major in CS, it’s perfectly reasonable that they already have some idea what’s involved, and to even have done some research on their own beforehand.

Women are less likely to jump up and say “me! me! me!” They are far more likely to wait to be asked to participate. We don’t need women to be different than they are, we just need to invite them in a way that works.

But that devalues the effort of people who put in the work to say, “me! me! me!”. Given two people, of any gender, if one person is willing to work harder than the other to be recognized, don’t they deserve to be recognized? Someone’s getting “invited” because they aren’t willing to put themselves forward to be recognized seems to reward just waiting around to be recognized, instead of making it happen.

Hell, I spent 8 years coding CSS before I ever spoke about it to anyone. The first time I spoke at a conference, John Allsopp contacted me to ask if I would do it. I never would have submitted a proposal. You might say that I should have, but I would counter that I shouldn’t need to act like a dude to get respect.

I find it a little offensive (and pretty sexist) that submitting a proposal is “acting like a dude”. It is not “acting like a chick” to sit back and undervalue your own work. If you have an idea, you develop it; there is nothing inherently masculine or feminine about that. Relying on the chance that someone else will convince you to do something seems like a bad strategy to me.

The main problem with affirmative action is that, despite all of the best intentions, it reinforces, rather than diminishes, the idea that class-X of people are inherently different and therefore need special treatment. That to me, seems to be more a part of the problem and less a part of the solution.

0

Westinghouse TVs are great…

June 24, 2009

…as long as you never need any customer service.

(feel free to skip this entry, as it has nothing to do with development, and is probably too long and boring for most people out there)

I have been largely happy with my 47″, Westinghouse HDTV, however, for the past six months or so, it has had issues talking to both of my PS3s (yes, two of them). Frequently, while displaying anything (DVDs, Blu-Rays, PS3 games, PS2 games, PS1 games, anything), the screen will just go blank. At this point, it’s a flip of a coin as to whether or not the picture will come back. The only solution is to unplug the HDMI cable and reattach it.

So, as any relatively geeky person of my generation would do, I went looking on Google. I found several places online where people were complaining about the same issue. One place of note was the Popular Mechanics website:

http://www.popularmechanics.com/blogs/technology_news/4203691.html
http://www.popularmechanics.com/blogs/technology_news/4212161.html
http://www.popularmechanics.com/blogs/technology_news/4212233.html

Since, as you can see, those articles are dated as early as 2006, so I thought that there was a good chance that the problem had been fixed. So I go to make sure that I have the latest firmware on all concerned devices. I check for updates on both PS3’s and find that they are up to date, and I search for a way to update the firmware in the TV.

I find that my TV has the “5110_1.1.0 april 13th 2007” firmware installed and that many people on internet forums claim that a version 1.3 of the firmware has fixed their issue. As I don’t really want to download firmware from an untrusted third party (namely some anonymous guy on a technology forum), all I have to do is head to Westinghouse’s site, download the newest firmware, load it onto a USB key and transfer it to my TV, right? wrong, oh so wrong.

I go to Westinghouse’s support site and enter my serial number (which I had to unmount my TV from the wall in order to see in the first place) on http://westinghousedigital.com/firmware.aspx. After which, I am presented with this unhelpful message:
Firmware_Updates_WTF

Since I was doing this on the weekend, and I am either working or getting ready to go to work during those hours, I didn’t have the option to call the customer support line. So I e-mailed them using their support form:

I am seeing some disturbing flickering whenever I use my PS3 with my HDTV. I have searched online, and have found that this seems to be common among users of Westinghouse HDTV’s, and was told that I probably need a firmware update. Currently my television reports its firmware version as 5110_1.1.0 april 13th 2007

Three hours later, I received a response. (“Wow,” I thought, “that’s some speedy turnaround.”):

Hello Clark Cox,

Thank you for your inquiry.

We apologize for any inconvenience in awaiting our response; we’re happy to assist you in any way we can. You can try updating the firmware for the TV if you are using an HDMI input. Also PS3 has released a firmware update to work with our TV’s.

If you have any further questions, you may contact us through email, or by calling us toll-free at 1-866-287-5555, between 9am and 9pm Eastern Standard Time, Monday through Saturday. One of our technicians will assist you.

-Nick, Westinghouse Digital Support Staff

“OK,” I thought, “now I’m getting somewhere; all I need do is ask, and Nick will tell me how to update my TV.”:

On Mon, May 4, 2009 at 1:18 PM, Westinghouse Digital Support
<westinghouse@microdyne.com> wrote:

Hello Clark Cox,

Thank you for your inquiry.

And thank you for your quick response.

We apologize for any inconvenience in awaiting our response; we’re happy to assist you in any way we can. You can try updating the firmware for the TV if you are using an HDMI input.

How do I do that? When I enter my serial number on <http://westinghousedigital.com/firmware.aspx>, I get the message: “Sorry, those numbers do not match our records. Please call Customer Support for assistance.”

Is there a direct link to a file I could download to a USB key?

Also PS3 has released a firmware update to work with our TV’s.

I believe that I already have the latest Firmware on my PS3, but I can check when I get home. Do you happen to know which version of their firmware addresses compatibility with your TV’s?

Two days later, I hear back from someone (“Meg”, this time):

Hello Clark,

Thank you for your inquiry.

We apologize for any inconvenience in awaiting our response; we’re happy to assist you in any way we can. The message you are receiving indicates a firmware update is not currently available on our website for your product. I’m sorry for any confusion regarding that. You may also want to try updating the firmware in the Playstation to help resolve the issue you are experiencing.

If you have any further questions, you may contact us through email, or by calling us toll-free at 1-866-287-5555, between 9am and 9pm Eastern Standard Time, Monday through Saturday. One of our technicians will assist you.

-Meg, Westinghouse Digital Support Staff

So, I got passed off to someone else, who didn’t read the e-mail that she was responding to (otherwise she would have known that I already had the latest firmware on my PS3), and told me that there isn’t a firmware update for my TV (So, “Nick” lied to me, and “Meg” is just parroting advice that I’d already followed a week prior to even contacting them in the first place). So, I respond, still attempting to remain civil:

On Wed, May 6, 2009 at 10:37 AM, Westinghouse Digital Support
<westinghouse@microdyne.com> wrote:

Hello Clark,

Thank you for your inquiry.

We apologize for any inconvenience in awaiting our response; we’re happy to assist you in any way we can. The message you are receiving indicates a firmware update is not currently available on our website for your product.

Someone really should fix your website in that case (i.e. it should actually display a message to that effect, instead of the “Sorry, those numbers do not match our records.” message). Additionally, I find it hard to believe that firmware built over two years ago is the latest firmware (especially since I see people posting on message boards about a version 1.3 firmware for the TX-47F430S).

I’m sorry for any confusion regarding that. You may also want to try updating the firmware in the Playstation to help resolve the issue you are experiencing.

I’ve verified that my PS3 already has the latest firmware (i.e. 2.70). This essentially makes my TV useless for virtually all of my HD content (i.e. my PS3 is my BluRay player). I can connect through component cables, but then I get some pretty obvious ghosting on the screen in high contrast areas (to the point where my not–technically-minded wife said, “Wow, that looks like crap”). What are my options at this point?

Two days later, I hear back from “Nick”:

Hello Clark Cox,

Thank you for your inquiry.

We apologize for any inconvenience in awaiting our response; we’re happy to assist you in any way we can. If the unit does have a firmware update and is not showing one currently available, it may have been taken down for maintenance. If a firmware is taken down we will post it again as soon as possible. Is this issue happening on any other HDMI sources?

If you have any further questions, you may contact us through email, or by calling us toll-free at 1-866-287-5555, between 9am and 9pm Eastern Standard Time, Monday through Saturday. One of our technicians will assist you.

-Nick, Westinghouse Digital Support Staff

And my response:

On Thu, May 7, 2009 at 7:49 AM, Westinghouse Digital Support
<westinghouse@microdyne.com> wrote:

Hello Clark Cox,

Thank you for your inquiry.

We apologize for any inconvenience in awaiting our response; we’re happy to assist you in any way we can. If the unit does have a firmware update

Is there, or is there not a 1.3 firmware for the TX-47F430S? “Yes” or
“no” please.

and is not showing one currently available, it may have been taken down for maintenance. If a firmware is taken down we will post it again as soon as possible. Is this issue happening on any other HDMI sources?

No, however both of my PS3’s (both at 2.70) exhibit this issue with my
Westinghouse TV, and neither of them exhibit it with my Samsung TV.

Then silence. They completely ignore me, and apparently do not want to answer my “Yes” or “No” question. Almost 20 days later, in a fit of frustration, I tweet:

Westinghouse TV’s = pretty good :) Westinghouse customer service = about as bad as it gets :(

This gets the attention of @WestinghouseTV, who asks me to e-mail him/her the details of my issue. So starts the next e-mail chain. I e-mail him/her with a transcript of all communications so far. Then ten days with no response. I e-mail again, and get back a form letter about their “new state of the art Customer Service Call Center”:

Dear Valued Westinghouse Customer,

On Monday, June 15th at 7:00 AM Central Time Westinghouse Digital Electronics opened its new state of the art Customer Service Call Center. The new call center is designed to allow us to provide you with the service that you are accustomed to when dealing with the Westinghouse brand.

Over the past couple of weeks we have done our best to address our customer issues as they came up, but we realize that we may have missed connecting with a few of our valued customers along the way. We want to ensure that we have provided service to all of our customers; therefore, we are reaching out to you to ensure your need for service has been addressed. If we have not yet had the chance to work with you, please contact us at our new service center by calling 1-800-701-0680.

Our service center is open from 7:00AM until 7:00 PM Central Time, Monday through Friday. Or feel free to email us at service@westinghousedigital.com at any time. Our goal is to return your email inquiry in 24 – 48 hours.

We would like to thank you for you patience as we transitioned to our new call center and we look forward to providing you excellent service in the future.

I e-mail back:

On Fri, Jun 19, 2009 at 8:48 AM, service<service@westinghousedigital.com> wrote:

On Monday, June 15th at 7:00 AM Central Time Westinghouse Digital Electronics opened its new state of the art Customer Service Call Center. The new call center is designed to allow us to provide you with the service that you are accustomed to when dealing with the Westinghouse brand.

I sure hope not. The “service that [I am] accustomed to when dealing with the Westinghouse brand” is being ignored.

Over the past couple of weeks we have done our best to address our customer issues as they came up, but we realize that we may have missed connecting with a few of our valued customers along the way.

I don’t feel very valued. My question has gone unanswered and my issue unaddressed for months now.

We would like to thank you for you patience as we transitioned to our new call center and we look forward to providing you excellent service in the future.

I’ll believe it when I see it. Below, you can find all of my
correspondence so far:

And, since then? Nothing. While I generally like my TV, I will never be buying another Westinghouse TV again. You can simply not trust that they will stand behind their products.

9

SDKs and Deployment Targets

June 23, 2009

Xcode has two build settings that are very important when supporting multiple versions of the OS (whether we’re talking about the Mac or the iPhone, it’s all the same to Xcode) with a single application binary. These settings are SDKROOT (a.k.a Base SDK) and MACOSX_DEPLOYMENT_TARGET[1] (a.k.a. Mac OS X Deployment Target).

Base SDK

Most people are familiar with the Base SDK setting. This setting defines which SDK to build against, and therefore, which APIs are available for your use. If, for instance, you want to build an application that uses an API that was introduced in 10.5, you must have a Base SDK set to macosx10.5 or later[2].

Deployment Target

Were Base SDK the only setting, you would be limited to three options:

  1. Build multiple versions of your application, one fore each OS version that you want to support
  2. Build a single application that uses features from the newer OS, and ignore users of the previous version.
  3. Build a single application that runs on the previous version of the OS, but miss out on the new features of the newer OS.

None of those choices seems particularly appealing. Fortunately, that is where the deployment target setting comes in. The deployment target setting, which seems to confuse people a bit, is much more subtle, and is often overlooked. It tells Xcode the version number of the earliest OS you wish to support, and adjusts the linkage of your application to make it possible.

Take the following example:

  • There are two versions of a hypothetical OS: OS 1.0 and OS 2.0
  • I have an application that I’ve been developing for OS 1.0, but I really want to take advantage of a new, amazing OS 2.0 feature.
  • I have enough users that still run OS 1.0, and I don’t want to deprive them of my application.

All I need to do to accomplish this is to set my Base SDK to “OS 2.0”, which will allow my application to use the new feature, and set my deployment target to “1.0″, which will allow my application to launch on OS 1.0.

At Runtime

But there’s a catch: I can launch on 1.0, but if I use a function, class or method that doesn’t exist (like those required to use the new, amazing feature), my application will crash. So, the last thing that I need do is to check, at runtime, for the availability of the particular function (or class, or method, etc.).

Functions

For functions, I can accomplish this by comparing the address of the function to NULL:

if(APIForAmazingNewFeature != NULL) {
//I can call APIForAmazingNewFeature() here
} else {
//I can't call it here, but I can fallback to doing something sensible
}

Classes

Since Objective-C is more dynamic than C, I can use higher-level constructs when the feature I’m testing for is a class:

Class myClass = NSClassFromString(@"AmazingNewClass");

if(myClass) {
//I can use “myClass” in place of AmazingNewClass when calling class methods:
AmazingNewClass *instance = [[myClass alloc] init];

} else {
//The class doesn’t exist

}

Added 11. Feb, 2010:


If you’re developing for an OS that supports Weak-import classes (currently only iPhone OS 3.1 and later), dealing with classes that may or may not exist is even easier—you can even subclass such classes (something that isn’t possible in previous versions of the Mac and iPhone operating systems).

Methods

…or a method:
if([someObject respondsToSelector: @selector(methodAddedInVersion2)) {
[someObject methodAddedInVersion2];
} else {

}

In Conclusion

Using these two build settings you can easily build a single binary of your application that supports the latest and the greatest, yet gracefully degrades when running on older OSes. The basic rules of thumb:

  • Set the Base SDK to the lowest value that will still support all of the features that you use
  • Set the deployment target to the lowest OS version on which you plan to run.
  • Check, at runtime, for any features that you use that don’t exist in the version of the OS that matches your deployment target.
  1. or IPHONEOS_DEPLOYMENT_TARGET/iPhone OS Deployment Target []
  2. There is one exception to this. If you leave this setting blank, it will build against the host system. So such an application would be properly built if, and only if, you were building it on a Mac running 10.5. Needless to say, it is impossible to build an iPhone application in this manner []
17

4-Way Fat Binaries, 10.4 through 10.5

June 2, 2009
Tags: ,

I’ve seen this question come up several times in the past week: “How do I build a single Cocoa application that runs on both 10.4 and 10.5, and runs 64-bit where possible.”

Easy. Copy and paste the following settings into your project or target settings as appropriate:

SDKROOT = macosx10.5
MACOSX_DEPLOYMENT_TARGET = 10.5
MACOSX_DEPLOYMENT_TARGET[arch=ppc] = 10.4
MACOSX_DEPLOYMENT_TARGET[arch=i386] = 10.4

That’s all you need. In plain English, these build settings mean:

  1. Use the 10.5 SDK
  2. Set the deployment target to 10.5
  3. …except for ppc
  4. … and i386, both of which use a deployment target of 10.4

It’s that simple. The resulting application will run with the “best” architecture, everywhere. The one caveat is that, at least in the 32-bit case, you have to check at runtime if you happen to be using 10.5-only APIs. If you’re sure that you don’t need to use any 10.5-only functionality, and can stick to 10.4-only APIs, you can use the following build settings instead:


SDKROOT = macosx10.5
SDKROOT[arch=ppc] = macosx10.4
SDKROOT[arch=i386] = macosx10.4
MACOSX_DEPLOYMENT_TARGET = 10.5
MACOSX_DEPLOYMENT_TARGET[arch=ppc] = 10.4
MACOSX_DEPLOYMENT_TARGET[arch=i386] = 10.4

These settings mean the same as the previous snippet, except that the ppc and i386 slices use the 10.4 SDK.

1

C99′s VLAs are evil

April 7, 2009
Tags: ,

While, at first glance, the ability to define an array, whose length is determined at runtime from a variable, seems like a good idea. Hey, it’s very clean and easy to understand, and all of the normal array operations work[1]; there is one major flaw—there is no way to deal with errors.

Variable Length Arrays, in C99 are defined just like any other array, except that the length doesn’t need to be a compile-time constant:


void foo(int size) {
    int array[size];
    for(int i=0; i<size; ++i) {
        array[i] = i;
    }
    ...
}

Calling the above function with any reasonable value will do the obvious thing, the array will be sized appropriately, will contain sequential numbers. sizeof(array) will even return size*sizeof(int). For the common case, everything works, and everybody is happy. But what happens when a size is too large to fit on the stack? Who knows.[2]

In the most common implementation of VLAs the compiler literally decrements the stack pointer by size and goes on it’s merry way, without regard to whether or not the stack pointer now points to an invalid address (or worse, a valid address somewhere inside of your program’s heap). If you’re lucky, and the stack pointer points to an invalid address, your program will likely crash. On the other hand, if you’re not so lucky, the seemingly innocuous function above will start trashing things in your program’s memory space; you may not catch it, you may have a strange, untraceable crash hours later, etc.. Needless to say, this can be quite difficult to debug.

The solution is to simply not use this feature of C99. If you’ve got a higher-level abstraction (such as std::vector in C++, NSData or NSArray in Cocoa) use that. If you really want to stick with pure, standard C, use malloc()/free()[3]:


void foo(int size) {
    int *array = malloc(size * sizeof *array);
    
    if(!array) {
        //Error out here
        return;
    }
    
    for(int i=0; i<size; ++i) {
        array[i] = i;
    }
    ...
    
    free(array);
}

  1. Even sizeof works, though that required a distasteful exception to the normal sizeof rules. Before VLAs, sizeof was always evaluated at compile time, and the resulting value was always a compile-time constant. When applied to VLAs, this obviously cannot be. []
  2. I’m not joking. The official term is “undefined behavior”. In such a case, the C standard doesn’t specify anything about what happens. []
  3. Don’t be tempted to use alloca(), it is not a standard C function, and has exactly the same issue that VLAs do []
16

Link errors when mixing C++ with C/Objective-C

February 7, 2009
Tags: ,

Twice in the past week, people have asked questions about getting undefined symbol errors when mixing Objective-C and C++. In both cases, this was a result of C++’s name-mangling. Anytime you want to have a single function that is callable from both C++ and Objective-C (or C, for that matter), you need to disable name mangling for that function.

Name Mangling

Normally, in C, the actual symbol name of a function is simply the function’s name with an underscore prepended; that is, int Foo(int i, float f) becomes simply _Foo. Nice and straightforward.

In C++, on the other hand, the exact same function will be named __Z3fooif[1]. At first glance, this seems like unnecessary complication for complication’s sake, but all becomes clear when you bring function overloading into the picture. Since C++ allows multiple functions with the same name to exist, as long as they accept different parameters, it makes sense that the types of the parameters themselves must somehow be encoded in the symbol name.

This is precisely what __Z3fooif is:

  • __Z means “This is a mangled name”.
  • 3 means “The next part of this name is 3 characters long”.
  • foo is the actual name of the function.
  • if represents the types of the parameters (i.e. “int” and “float”)

This allows foo(int,char) to have a different name than foo(int,float) in the binary.

Now What?

So, now that we know why C and C++ encode their function names differently, what can we do about it. The designers of C++ foresaw this situation, after all C++ would have had a long row to hoe were it not compatible with C. They added the extern "C" directive to the language.

There are two ways to apply this directive; either to an entire block of code, or to a single function declaration. Each has it’s advantages and disadvantages:

  • extern "C" int foo(int,float);

    This disables name mangling on this single function

  • extern "C" { ... }

    This disables name mangling on all functions between the curly braces.

Final Gotcha

So, we’re done, right? Not quite. Since C knows nothing of this “extern "C"” business any of the above declarations will fail to compile when passed to a C or Objective-C compiler. They must be conditionally compiled so that only the C++ compiler sees them.

For the single-function version of the declaration, most people define some kind of macro to hide all of this complexity:

#ifdef __cplusplus
#define MY_EXTERN_C extern "C"
#else
#define MY_EXTERN_C extern
#endif

After this is defined, your function declaration becomes:
MY_EXTERN_C int foo(int i, float f);

And, for the block style, just wrap the beginning and end of the block with #ifdef __cplusplus, like so:

#ifdef __cplusplus
extern "C" {
#endif

...

#ifdef __cplusplus
}
#endif

  1. Note, the exact encoding can vary from compiler to compiler, but the basic principle remains the same []
2

Inspecting Obj-C parameters in gdb

February 4, 2009

Since the addition of i386 and x86_64 to the Mac OS’s repertoire several years back, remembering which registers are used for what has become difficult, and this can complicate the debugging of code for which you have no symbols. So here is my cheat-sheet (posted here, mostly so that I can find it again without google-ing for old mailing list posts; but, I figure someone else may find it useful as well):

arm (before prolog)

  • $r0 ➡ arg0 (self)
  • $r1 ➡ arg1 (_cmd)
  • $r2 ➡ arg2
  • $r3 ➡ arg3
  • *($sp) ➡ arg4
  • *($sp+4) ➡ arg5
  • *($sp+8) ➡ arg6

ppc/ppc64

  • $r3 ➡ arg0 (self)
  • $r4 ➡ arg1 (_cmd)
  • $r5 ➡ arg2
  • $r6 ➡ arg3
  • $r7 ➡ arg4
  • $r8 ➡ arg5

i386 (before prolog)

  • *($esp+4n) ➡ arg(n)
  • *($esp) ➡ arg0 (self)
  • *($esp+4) ➡ arg1 (_cmd)
  • *($esp+8) ➡ arg2
  • *($esp+12) ➡ arg3
  • *($esp+16) ➡ arg4
  • *($esp+20) ➡ arg5

i386 (after prolog)

  • *($ebp+8+4n) ➡ arg(n)
  • *($ebp+4) ➡ Return addr
  • *($ebp+8) ➡ arg0 (self)
  • *($ebp+12) ➡ arg1 (_cmd)
  • *($ebp+16) ➡ arg2
  • *($ebp+20) ➡ arg3
  • *($ebp+24) ➡ arg4
  • *($ebp+28) ➡ arg5
  • *($ebp) ➡ Previous $ebp

x86_64

  • $rdi ➡ arg0 (self)
  • $rsi ➡ arg1 (_cmd)
  • $rdx ➡ arg2
  • $rcx ➡ arg3
  • $r8 ➡ arg4
  • $r9 ➡ arg5

So, if you have a method defined as:
-(id)method:(id)foo bar:(id)bar baz:(id)baz
you can print each of the parameters with:

arm ppc/ppc64 x86_64 i386 (before prolog) i386 (after prolog)
self po $r0 po $r3 po $rdi po *(id*)($esp) po *(id*)($ebp+8)
_cmd p (SEL)$r1 p (SEL)$r4 p (SEL)$rsi p *(SEL*)($esp+4) p *(SEL*)($ebp+12)
foo po $r2 po $r5 po $rdx po *(id*)($esp+8) po *(id*)($ebp+16)
bar po $r3 po $r6 po $rcx po *(id*)($esp+12) po *(id*)($ebp+20)
baz po *(id*)($sp) po $r7 po $r8 po *(id*)($esp+16) po *(id*)($ebp+24)

As Blake mentioned in his comment, on i386, if you’re at the beginning of a function or method, before the prolog has executed (i.e. the bit of code responsible for saving registers, adjusting the stack pointer, etc.), then ebp won’t have been set up for you yet.
So, I’ve amended the above table.

That complexity is another reason I long for the simplicity of PowerPC asm, not to mention M68k asm; at least x86_64 has made the step towards using registers for parameters where possible.

Edited to add: In case it isn’t obvious, these particular stack offsets and registers assignments only make sense when dealing with pointer and integer parameters and return values. When structures and floating point values come into the mix, things can get more complicated.

Edited to add: I’ve added registers/stack offsets for arm. But note that these are for before the prolog has executed. Arm code seems much looser about what happens in its function prologs, so there really isn’t a standard layout post-prolog

15