//---------------------------------------------------------------- // reverse.s // // This program shows how the stack can be used to rearrange // characters that are stored in an array in backward order. // (This idea is useful when you write a high-level language // compiler or when you convert a number to a digit-string.) // // assemble using: $ as reverse.s -o reverse.o // and link using: $ ld reverse.o -o reverse // // programmer: ALLAN CRUSE // written on: 03 FEB 2005 // revised on: 31 JAN 2009 -- for Linux's x86_64 environment //---------------------------------------------------------------- # manifest constants .equ stdin_ID, 0 # input-device (keyboard) .equ stdout_ID, 1 # output-device (screen) .equ sys_read, 0 # ID-number for 'read' .equ sys_write, 1 # ID-number for 'write' .equ sys_exit, 60 # ID-number for 'exit' .section .data msg1: .ascii "\nPlease type a sentence on the line below: \n" len1: .quad . - msg1 msg2: .ascii "\nHere is what you typed in backward order: \n" len2: .quad . - msg2 msg3: .ascii "\n" len3: .quad . - msg3 inbuf: .space 80 maxin: .quad . - inbuf .section .text _start: # request user input mov $sys_write, %rax # service ID-number mov $stdout_ID, %rdi # device ID-number lea msg1, %rsi # message address mov len1, %rdx # message length syscall # enter the kernel # receive user input mov $sys_read, %rax # service ID-number mov $stdin_ID, %rdi # device ID-number lea inbuf, %esi # buffer address mov maxin, %rdx # buffer length syscall # enter the kernel mov %eax, maxin # save input count # push characters onto stack lea inbuf, %rsi # point ESI to buffer mov maxin, %rcx # setup ECX for count dec %rcx # but omit final byte nxch1: mov (%rsi), %al # load next character push %rax # and push onto stack inc %rsi # advance array-pointer loop nxch1 # then back for another # pop characters from stack lea inbuf, %rdi # point EDI to buffer mov maxin, %rcx # setup ECX for count dec %rcx # but onlt final byte nxch2: pop %rax # pop next character mov %al, (%rdi) # and store in buffer inc %rdi # advance array-pointer loop nxch2 # then back for another # announce program output mov $sys_write, %rax # service ID-number mov $stdout_ID, %rdi # device ID-number lea msg2, %rsi # message address mov len2, %rdx # message length syscall # enter the kernel # display program output mov $sys_write, %rax # service ID-number mov $stdout_ID, %rdi # device ID-number lea inbuf, %rsi # message address mov maxin, %rdx # message length syscall # enter the kernel # output one blank line mov $sys_write, %rax # service ID-number mov $stdout_ID, %rdi # device ID-number lea msg3, %rsi # message address mov len3, %rdx # message length syscall # enter the kernel # terminate this program mov $sys_exit, %rax # service ID-number mov $0, %rdi # setup exit-code syscall # enter the kernel .global _start # visible entry-point .end # no more to assemble