# For i386 Linux. You'll have to run this through cpp and gas;
# easiest way is to put it in a file whose name ends in .S and say
# gcc -m32 -nostdlib -static -o printstring printstring.S
#include <asm/unistd.h>
.section .rodata
mystr: .asciz "ABCDE is a string"
.data
byte: .byte 0
.text
.globl _start
_start: mov $mystr, %eax
call printchars
mov $'\n, %eax
call printchar
mov $__NR_exit, %eax
mov $0, %ebx
int $0x80
printchars: # args: %eax points to string
xor %ebx, %ebx
loop: mov (%eax), %bl
inc %eax
push %eax
push %ebx
movzbl %bl, %eax
call printnumspc
pop %ebx
pop %eax
and %ebx, %ebx # nul-terminated string
jnz loop
ret
printnumspc: # args: %eax is number to print
call printnum # number must be nonnegative
mov $32, %eax # space char
jmp printchar # tail-call
printnum: # args: %eax is number to print
mov $10, %ebx
mov $'0, %ecx
and %eax, %eax
jnz printnonzero
mov $'0, %eax
jmp printchar # tail-call
printnonzero: # args: %eax is number to print
# number must be nonnegative
xor %edx, %edx # %ebx is base (nonclobbered)
idiv %ebx # %ecx is zero digit
# (nonclobbered)
and %eax, %eax
jz done
push %edx
call printnonzero
pop %edx
done: add %ecx, %edx
push %eax
push %ebx
push %ecx
mov %edx, %eax
call printchar
pop %ecx
pop %ebx
pop %eax
ret
printchar: # args: %al is char to print
mov %al, byte
mov $__NR_write, %eax
mov $1, %ebx # stdout
mov $byte, %ecx
mov $1, %edx # length
int $0x80
ret