//----------------------------------------------------------------- // nybbles.s // // This program prints out the full sequence of 4-bit binary // numbers, which all assembly language programmers probably // will have memorized by the time they have finished taking // a college course like this one! Quite a few fundamentals // of the x86 environment are illustrated with this example, // such as use of the CPU's 64-bit general registers and its // stack, use of the carry-flag, array-addressing, character // codes versus numeric values, nesting of loops, and system // calls to the Linux kernel for standard output and program // termination; otherwise this is a stand-alone application. // // assemble with: $ as nybbles.s -o nybbles.s // and link with: $ ld nybbles.o -o nybbles // execute using: $ ./nybbles // // programmer: ALLAN CRUSE // written on: 21 JAN 2009 //----------------------------------------------------------------- .equ dev_STDOUT, 1 .equ sys_WRITE, 1 .equ sys_EXIT, 60 .section .data hex: .quad 0x123456789ABCDEF # the sixteen nybbles msg: .ascii "\n" # start of the output buf: .ascii "xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx " .ascii "xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx\n\n" len: .quad . - msg # length of the output .section .text _start: # use nested-loops to convert nybbles to 4-digit strings mov hex, %rax # fetch the 16 nybbles mov $buf, %rbx # setup buffer pointer mov $16, %rcx # outer-loop iterations nxnyb: push %rcx # save outer-loop count mov $4, %rcx # inner-loop iterations nxbit: mov $'0', %dl # character code for '0' add %rax, %rax # double the RAX value adc $0, %dl # add the carry-out to DL mov %dl, (%rbx) # and store the character inc %rbx # advance buffer pointer dec %rcx # decrement loop-counter jnz nxbit # again for 'inner-loop' pop %rcx # recover outer-loop count inc %rbx # skip past a blank space dec %rcx # decrement loop-counter jnz nxnyb # again for 'outer-loop' # display our message-string mov $sys_WRITE, %rax # system-call ID-number mov $dev_STDOUT, %rdi # device-file ID-number mov $msg, %rsi # address of the message mov len, %rdx # length of the message syscall # invoke Linux service # terminate this program mov $sys_EXIT, %rax # system-call ID-number mov $0, %rdi # use zero as exit-code syscall # invoke Linux service .global _start # make entry-point public .end # tell assembler to stop