//----------------------------------------------------------------- // betaworm.s // // This Linux program is intended for use in a demonstration // of multitasking or multiprocessing, in which we will want // to see continuous screen-output being produced by several // independent instances of this program-code running either // concurrently in a timesharing setting or in parallel on a // collection of separate system processors. This program's // output occupies only part of a single display-line, so it // could write to several dozen non-overlapping video areas. // // to assemble: $ as --32 betaworm.s -o betaworm.o // and to link: $ ld -melf_i386 betaworm.o -o betaworm // and execute: $ ./betaworm // // programmer: ALLAN CRUSE // written on: 16 NOV 2008 //----------------------------------------------------------------- .equ sys_NANOSLEEP, 162 .equ sys_SIGNAL, 48 .equ sys_WRITE, 4 .equ sys_EXIT, 1 .equ dev_STDOUT, 1 .equ sig_SIGINT, 2 .section .data tm: .long 0, 80000000 # time-value for delay init: .ascii "\033[H\033[J\033[?25l" # initial ANSI-command lenI: .int . - init # length of the string cmdH: .ascii "\033[04;01H" # to reposition cursor char: .byte 'A' # and output character lenH: .int . - cmdH # length of the string show: .ascii "\033[05;01H\033[?25h" # ending ANSI-command lenS: .int . - show # length of the string xmax: .int 30 # the uppermost column xmin: .int 10 # the lowermost column xnow: .int 20 # the 'current' column xinc: .int 1 # direction to advance .section .text _start: .code32 # install our own signal-handler for -C mov $sys_SIGNAL, %eax # system-call ID-number mov $sig_SIGINT, %ebx # unix-signal ID-number lea exit, %ecx # signal-handling entry int $0x80 # invoke kernel service # write ANSI control-string to the console mov $sys_WRITE, %eax # system-call ID-number mov $dev_STDOUT, %ebx # device-file ID-number lea init, %ecx # address of the string mov lenI, %edx # length of the string int $0x80 # invoke kernel service # begin an endless program-loop to draw to the screen again: # convert column-number to a two-digit decimal string mov xnow, %eax # current x-coodinate mov $10, %bl # decimal-system base divb %bl # generate digit-pair or $0x3030, %ax # format two numerals mov %ax, cmdH+5 # and put into string # write ANSI cursor-position and current character mov $sys_WRITE, %eax # system-call ID-number mov $dev_STDOUT, %ebx # device-file ID-number lea cmdH, %ecx # address of the string mov lenH, %edx # length of the string int $0x80 # invoke kernel service # advance the column-number (either forward or backward) mov xnow, %eax # current column-number add xinc, %eax # add current increment # check whether current direction needs to be reversed cmp xmax, %eax # new x-value above xmax? jae doflip # yes, flip the direction cmp xmin, %eax # new x-value below xmin? jbe doflip # yes, flip the direction jmp dokeep # else retain new x-value doflip: # reverse the direction and advance the character negl xinc # change increment's sign incb char # advance alphabet letter cmpb $'Z', char # has 'Z' been exceeded? jle dokeep # no, retain new letter movb $'A', char # else start over at 'A' dokeep: mov %eax, xnow # store the new x-value # wait until the prescribed time-delay has expired mov $sys_NANOSLEEP, %eax # system-call ID-number lea tm, %ebx # address of 'timespec' xor %ecx, %ecx # old timespec discarded int $0x80 # invoke kernel service jmp again # then continue drawing exit: # write ANSI command-string to the console mov $sys_WRITE, %eax # system-call ID-number mov $dev_STDOUT, %ebx # device-file ID-number lea show, %ecx # address of the string mov lenS, %edx # length of the string int $0x80 # invoke kernel service # terminate this program, and return to command-shell mov $sys_EXIT, %eax # system-call ID-number mov $0, %ebx # use zero as exit-code int $0x80 # invoke kernel service .global _start # make entry-point public .end # no more to be assembled