############################################################# # function to convert string to URL encoding # # Alphanumeric: unchanged # # Space --> '+' # # All else: %xx where xx is the hexadecimal value # # example: "X + 1" --> "X+%2B+1" # ############################################################# .text .globl __start # First, some utility functions: ############################################################# # boolean function AlphaNumeric (ch) # $a0: argument ch, unchanged # $v0: boolean value output # Uses registers t5, t6, t7, t8 ############################################################# AlphaNumeric: # Evaulate boolean expression for ApphaNumeric: # (ch >= 'A' and ch <= 'Z') or (ch >= 'a' and ch <= 'z') # or (ch >= '0' and ch <= '9') # # using "set" instructions, which store 1 (true) or 0 (false) in Rdest # ch in $a0 sge $t5,$a0,'A' sle $t6,$a0,'Z' and $t7,$t5,$t6 #(ch >= 'A' and ch <= 'Z') #--- the assembled machine code is incredible! # I have left it here so you can see the difference to the modification below. #--- the machine instruction is only slt, if we recast the expression: # (ch > 'A'-1 and ch < 'Z'+1) or (ch > 'a'-1 and ch <= 'z'+1) 0x7B # or (ch >= '0' and ch <= '9'+1) sgt $t5,$a0,0x40 #ch > 'A'-1 slt $t6,$a0,'Z'+1 #ch < 'Z'+1 and $t7,$t5,$t6 #(ch >= 'A' and ch <= 'Z') sgt $t5,$a0,0x60 # ch < 'a'-1 slt $t6,$a0,'z'+1 and $t8,$t5,$t6 #(ch >= 'a' and ch <= 'z') or $t8, $t8,$t7 # $t8 = big or small letter sgt $t5,$a0,0x2f # ch > '0'-1 slt $t6,$a0,'9'+1 and $t7,$t5,$t6 #(ch >= '0' and ch <= '9') or $v0, $t8,$t7 # $v0 = AlphaNumeric jr $ra # char bin2hex (binary) converts 4 bits (least significant) of input to an # ASCII character giving the hex value. '0'-'9' or 'A'-'F' # registers: # $a0, input argument, unchanged # $v0, char value returned # no other registers used bin2hex: andi $v0, $a0, 0x0f # mask off 4 lower bits ori $v0, $v0, 0x30 # make it ASCII digit ble $v0, '9', numeric #if hex value A..F, then add $v0, 7 # add 7, since there are 7 characters numeric: # between '9' and 'A' jr $ra # RETURN #--------------------------------------------------------------------------- URLencode: # function URLencode (plain, encoded, maxlength) # arguments: # a0 pointer to plain string to be encoded # a1 pointer to space to store URL encoded string # a2 space available for that string. Do not exceed ######## entry code: save registers ## PUSH return address sub $sp, 4 #space for new top of stack entry sw $ra, ($sp) #put something there sub $sp, 4 # PUSH a0 sw $a0, ($sp) #be nice, restore callers register ######################## move $t0, $a0 # t0 -> plain working string pointers move $t1, $a1 # t1 -> encoded # t2 current character # limit = encode + maxlen - 4; /* need to store 3 chars and a zero */ add $t3, $a1,$a2 # t3 -> limit of storage (as address) sub $t3, 4 # need room for 3 chars and null byte loop: lb $t2, ($t0) # get character from plain add $t0, 1 # increment pointer beqz $t2, endloop # End of String???? # IF ch=space, store a '+' beq $t2,' ', plus # else if (AlphaNumeric (ch)) move $a0, $t2 jal AlphaNumeric # ---- then store as is bnez $v0, as_is # else STORE "%hh", hh being two character hexadecimal value li $t4,'%' sb $t4, ($t1) add $t1, 1 # * encode ++ = bin2hex (ch >> 4); /*shift right for left nibble*/ srl $a0, $t2, 4 jal bin2hex sb $v0, ($t1) add $t1, 1 # * encode ++ = bin2hex (ch); /* right nibble */ move $a0, $t2 jal bin2hex sb $v0, ($t1) add $t1, 1 j endif plus: li $t2, '+' as_is: sb $t2, ($t1) #store character in result string add $t1, 1 endif: # end if-else if - else } #---------------------------------------- # test for enough space before looping # if (encode > limit){ ble $t1, $t3, loop sb $0, ($t1) # /* still room to terminate string */ li $v0, -1 #/* return value indicates error */ j endURL #----------------------------------------- endloop: sb $0, ($t1) # /* terminate string */ sub $v0, $t1, $a1 # return count of characters */ ############ exit code: restore registers, POP in reverse order to PUSH endURL: lw $a0, ($sp) # POP start of string addr add $sp, 4 lw $ra,($sp) # POP return address add $sp, 4 jr $ra ##### return #============================MAIN for TEST ============================== __start: la $a0, mystring #address of test data li $v0, 4 #write it syscall la $a1, encodedstr #point to space for result li $a2, 50 #space available jal URLencode # do it! move $s0, $v0 # save return value (# chars) la $a0, endl # new line li $v0, 4 syscall la $a0, encodedstr li $v0, 4 # write result syscall la $a0, endl # new line li $v0, 4 syscall move $a0, $s0 #write return value li $v0, 1 syscall la $a0, endl # new line li $v0, 4 syscall li $v0, 10 syscall .data mystring: .asciiz "This is my string, $2.95!" encodedstr: .space 50 endl: .asciiz "\n"