as -o foo.o  foo.s
If you have a .S, normally that means you want to run it through the C preprocessor before assembling.  The gcc and clang front-ends will do that for you: gcc -c foo.S (default output filename foo.o, instead of a.out).  If your .S doesn't actually have any CPP directives like #if or #define, though, you can just assemble it with as.
a.out is the default name for the output of as, but it is an object file like you'd get from gcc -c foo.s, not a linked executable!  GNU Binutils as does not produce linked executables.
(The default output filename for ld foo.o or gcc / clang without -c is also a.out, but don't be fooled by the name.)
You can use gcc -v -c foo.s to show the as command line it uses, including the -o option.  (clang has a built-in assembler, so it won't run a separate as command, but the gcc front-end truly does just run as to assemble asm source files.  And without -c, then runs ld (via collect2) to link the object file into an executable.)
e.g. on my x86-64 GNU/Linux system:
$ cat > foo.s
mov $231, %eax             # __NR_exit_group
syscall
$ as foo.s
$ file a.out
a.out: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
$ ld a.out -o exit
ld: warning: cannot find entry symbol _start; defaulting to 0000000000401000
$ ls -l exit a.out 
-rw-r--r-- 1 peter peter  664 Mar 22 08:23 a.out
-rwxr-xr-x 1 peter peter 4632 Mar 22 08:23 exit
$ file exit
exit: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped
$ ./a.out
bash: ./a.out: Permission denied
$ ./exit
$ strace ./exit 
execve("./exit", ["./exit"], 0x7ffc72823fc0 /* 55 vars */) = 0
exit_group(0)                           = ?
+++ exited with 0 +++
$ as --version
GNU assembler (GNU Binutils) 2.35.1
...
This assembler was configured for a target of `x86_64-pc-linux-gnu'.
$ ld --version
GNU ld (GNU Binutils) 2.35.1
...