Well, the question isn't so much "how do we print in asm?" as "how do we print in my OS?"
You've got 32-bit code there, but ld and gcc on your (evidently) 64-bit system are expecting to build 64-bit code, by default. To tell ld we want 32-bit code, "-m elf_i386". On my old brain-dead ld, I get 32-bit code by default, but I need to tell it which dynamic linker (interpreter) to use. By default, it looks for /lib/ld-linux.so.1 - which does not exist on my system. This results in a "file not found" error message when I try to run my masterpiece - even though I can see it right there! Quite confusing, until someone gave me the clue to specify ...so.2. I have no idea what your ld will be looking for by default, or where to find what it really wants. In any case, we will need to tell ld "-lc" so it'll link against the C library... where it will find "printf".
To tell gcc we want 32-bit code, just "-m32". This is simpler, since gcc knows what to tell ld.
You may encounter another difficulty... apparently not all distros come with the 32-bit C libraries. There's an "apt-get" command to add 'em - "comb-libs" or something... I forget...
I'm surprised that you get as far as a segfault. I wouldn't expect the file to exist at all. Apparently that's just a "warning" about "incompatible with x86-64" and it goes ahead and builds... something. I can't imagine what, since "push eax" is invalid in 64 bit code (I understand).
The latest version of your code looks about right. You haven't got any "tokens" in your format string, so the number you push will be ignored, but you clean up the stack properly - I'd expect it to print "value" and exit cleanly. (haven't tried it) See if adding "-m32" to gcc's command line helps, or if that causes more complaints.
This "works for me" with command lines as given in the comments...
; nasm -f elf32 myprog.asm
; ld -o myprog myprog.o -I/lib/ld-linux.so.2 -lc -m elf_i386
global _start
extern printf
section .data
matrix dd 3, 6, 9,\
4, 8, 12,\
5, 15, 20
; note back-apostrophes!
fmt db `%u, %u, %u\n%u, %u. %u\n%u, %u, %u\n\0`
section .text
_start:
call print_matrix ; just to prove we can
mov eax, 1
xor ebx, ebx
int 0x80
;--------------------
;-------------------
print_matrix:
; these should probably be parameters...
mov ebx, matrix
mov ecx, 9
.top:
; push parameters, last first
dec ecx
js .end
push dword [ebx + ecx * 4]
jmp .top
.end:
push fmt ; format string pushed last
call printf
add esp, 4 * 10 ; caller cleans up stack!
ret ; just to prove stack is right
;-----------------------
I don't know if that'll help, or just create more confusion. Less source code than my last attempt to print a matrix, if nothing else!
Best,
Frank