# ;; basename.s # # #include .data eoln: .string "\n" slash: .string "/" period: .string ".\n" # # # .file "basename.s" .text .globl basename basename: cmp $1,(%rsp) # check to see if there are no arguments je done xor %r10,%r10 # we'll use %r10 for our "zero" register xor %r12,%r12 # we'll use %r12 as a "found" flag ; 0 = not found, 1 = found mov 16(%rsp),%rbx # %rbx now has pointer to beginning of first argument (should make sure that # argc is big enough ... ) mov 16(%rsp),%rdx # %rdx also has the beginning for now, but if we find a slash, we update %rdx to the location of the slash movb slash,%cl # put slash into %cl so we can make comparison name_loop: cmpb %r10b,(%rbx) # is the byte a zero? then we are finished looking at the command je found_zero_byte cmpb %cl,(%rbx) # is it a slash? then we save our position je found_a_slash inc %rbx jmp name_loop found_a_slash: mov %rbx,%rdx # save position in %rdx inc %rbx # increment %rbx inc %r12 # set %r12 as a flag that we found it jmp name_loop found_zero_byte: # save %rbx in %r15 --- that's the last (zero) byte mov %rbx,%r15 # did we find it? if not, then output whole original argument cmp $0,%r12 jne found_last_slash mov 16(%rsp),%rsi # okay, send out original argument mov $1,%rdi call writestr # save first byte in %r14 mov 16(%rsp),%r14 jmp check_for_suffix found_last_slash: # save first byte in %r14 mov %rdx,%r14 inc %r14 check_for_suffix: cmp $3,(%rsp) # well, we have another argument, it must indicate a suffix that we want to try to remove jl done # let's find that zero byte! cld # go forward mov $0,%al # put zero in %al mov 24(%rsp),%rdi # put our pointer from the stack into %rdi mov $1000,%rcx # arbitrarily cap this... repne scasb jne done # we give up if we didn't find a zero byte in 1000 bytes... (That would be a very unusual suffix!) dec %rdi # scasb actually puts us one byte beyond sub 24(%rsp),%rdi # take the difference sub %rdi,%r15 # now take that difference to reduce %r15 # finally, do a comparison of %r15 and 24(%rsp) cld mov %rdi,%rcx # remember, the difference (i.e., the number of bytes in arg3) # was left in %rdi mov 24(%rsp),%rsi # now arrange arg3 pointer into %rsi mov %r15,%rdi # and put the "beginning" of bytes into %rdi rep cmpsb jne done movb $0,(%r15) # terminate string at the beginning of the suffix done: mov %r14,%rsi # now point %rsi back to slash + 1 mov $1,%rdi call writestr lea eoln,%rsi # don't forget to send an eoln also mov $1,%rdi call writestr mov $0, %rdi # and exit with a zero status mov $__NR_exit,%rax # syscall = 60 is exit syscall