Just what did you do with this, neurophobos? Ending in "ret" as it does, it is apparently intended to be called from something. Lacking a caller, I tried assembling and linking it "freestanding". As expected, ld warns about not finding an entrypoint, and guesses at one. This entrypoint is not called ("argc" is the very first thing on the stack), so ending in "ret" segfaults, as expected. Before doing so, it prints the expected text, so it "kinda works".
To get rid of the segfault, either replace the "ret" with an exit:
; ret
mov eax, 1
mov ebx, 0
int 80h
... or call it from something, and do something sensible (like exit) after it returns. This caller could be part of the same file, or could be a separate module. If the latter, you'll want to declare your function "global" (in this file) and "extern" in the calling file. (C may assume this, if you're calling it from C)
To keep it simple...
; nasm -f elf32 myfile.asm
; ld -o myfile myfile.o -m elf_i386
global _start ; tell ld about this so it won't have to guess
section .text
_start:
nop ; may help gdb
call myfunc
exit:
mov eax, 1 ; sys_exit
xor ebx, ebx ; claim no error
int 80h
; -------------------
;---------------------
myfunc:
push ebx
xor ebx, ebx
mov ebx, 4
write_hex:
mov byte bh, bl
shr byte bl, 4
add byte bl, 0x30
cmp byte bl, 0x3a
jb short .number_1
add byte bl, 0x07
.number_1:
mov byte [hex_number], bl
and byte bh, 0x0f
add byte bh, 0x30
cmp byte bh, 0x3a
jb short .number_2
add byte bh, 0x07
.number_2:
mov byte [hex_number + 1], bh
mov dword eax, 4
mov dword ebx, 1
mov dword ecx, hex_text
mov dword edx, 9
int byte 0x80
pop ebx
ret
section .data
hex_text: db "ebx: "
hex_number: db "00h", 10
If you tell us more about how you want to use this, we may be able to help more...
Best,
Frank