The "register" keyword has been effectively deprecated in decent mainstream compilers since the late 80s or thereabouts. By that time, compiler optimization had been implemented such that the compiler could do a better job of register allocation than the user could guide with the register keyword, which has been nothing more than an historical oddity for a very, very long time. It is typical for "register" to be completely ignored, and seeing it in code written in the last couple of decades should cause both eyebrows to raise, because it indicates either (a) something strange is going on and register is not being ignored, or (b) the programmer doesn't know what he's doing.
As for passing function arguments in registers, that is implementation-defined behavior. Usually, there are a number of "calling conventions" that define how arguments are passed, and when passed on the stack, the order in which they're pushed. In general, there can be more arguments than registers, and the stack will be a fallback mechanism even in register-based calling conventions. When the stack is used, there's also the question of who cleans it up, the caller or callee, and that too is defined by the calling convention.
The register keyword is genuine trivia, and calling conventions are something the application programmer can usually ignore. However, the latter can still be important mainly when interfacing with code written in different languages or more generally, code that uses different calling conventions than is the default for the current compiler.