First off, thanks for blowing my mind. When I first looked at your code, I didn't believe it would work at all. Then I tried it and reproduced your results. Now it makes perfect sense to me, albeit in a twisted way. :-) I'll try to explain it.
First, let's look at the more sane way to achieve this. Define a string in the data portion of the ASM file:
string: db "Hey, is this thing on?", 0
Then push the address of that string on the stack before calling printf:
So, that first parameter to printf (last parameter pushed on the stack before the call) is the pointer to the format string. What your code did was push the string on the stack, followed by the stack pointer which then pointed to the string.
Next, I'm going to replace your strings so that they are easier to track in disassembly:
Assemble with nasm, and then disassemble with objdump:
nasm string.s -f elf32 -o string.o
objdump -d -Mintel string.o
When you push, e.g., '123', that gets converted to a 32-bit hex digit-- 0x333231 in this case. Note that the full 32 bits are 0x00333231.
3: 68 35 36 37 00 push 0x373635
8: 68 31 32 33 00 push 0x333231
d: 54 push esp
Pushing onto the stack decrements the stack pointer. Assuming an initial stack pointer of 0x70 (contrived for simplicity), this is the state of the stack before calling printf:
64: 68: 6c: 70:
68 00 00 00 31 32 33 00 35 36 37 00 ...
So, when print is called, it uses the first parameter as the string pointer and starts printing characters until it sees a NULL (0x00).
That's why this example only prints "123" ("sud" in your original).
So let's push "1234" instead of "123". This means we are pushing the value 0x34333231. When calling printf the stack now looks like:
64: 68: 6c: 70:
68 00 00 00 31 32 33 34 35 36 37 00 ...
Now there is no NULL gap between those 2 strings on the stack and this example will print "1234567" (or "sudobor" in your original).
Implications: Try pushing "5678" instead of "567". You will probably get a segmentation fault because printf will just keep reading characters to print until it tries to read memory it doesn't have permission to read. Also, try pushing a string that is longer than 4 characters (e.g., "push '12345'"). The assembler won't let you because it can't convert that to a 32-bit number.