# 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