Lab 3
1. Description: This program is a calculator implemented in hla without using loops or if statements. The program performs Roman numeral conversion, addition, subtraction, multiplication and exponentiation. The multiplication routine includes optimization which exploits the commutative property to minimize the number of loop iterations.
2. Code:
//Program to implement a Calculator in HLA //Author: Jason Warren //Date: 10/09/13 program lab2; #include( "stdlib.hhf" ); static tmp_ecx: int32; tmp_edx: int32; ret_address: int32; ret_address_lvl2: int32; begin lab2; menu: stdout.put("Enter your operation:", nl); stdout.put("1 - Convert to Roman numeals", nl); stdout.put("2 - Addition", nl); stdout.put("3 - Subtraction", nl); stdout.put("4 - Multiplicattion", nl); stdout.put("5 - Exponentiation", nl); stdout.put("9 - Exit", nl); stdout.put("> "); stdin.getu8(); //If command was '1' - Convert to Roman cmp(eax, 1); jne skipcmd1; stdout.put("Enter number to covert to Roman: "); stdin.getu32(); //Store user input in eax mov(&cmd1_ret0, ret_address); //Store return address jmp ToRoman; cmd1_ret0: stdout.put(nl); jmp menu; skipcmd1: //If command was '2' or '3' - Add or Sub cmp(eax, 2); je cmd2; cmp(eax, 3); jne skipcmd3; cmd2: mov(eax, ecx); mov(&cmd2_ret0, ret_address); //Store return addres. jmp GetOperands; cmd2_ret0: stdout.putu16(bx); //If we are adding. cmp(ecx,2); jne print_sub; stdout.put("+"); jmp end_print; //else we are subtracting. print_sub: stdout.put("-"); end_print: stdout.putu16(ax); stdout.put("="); //If we are adding. cmp(ecx, 2); jne do_sub; add(ebx, eax); jmp end_add_sub; //Else subtract. do_sub: sub(eax,ebx); mov(ebx, eax); end_add_sub: stdout.puti32(eax); stdout.put(nl); jmp menu; //endif Add or Sub skipcmd3: //If multiply command cmp(eax,4); jne skipcmd4; mov(&cmd4_ret0, ret_address); //Store return address jmp GetOperands; cmd4_ret0: stdout.putu16(bx); stdout.put("*"); stdout.putu16(ax); stdout.put("="); mov(&cmd4_ret1, ret_address); //Store return address jmp Mult; cmd4_ret1: stdout.putu32(eax); stdout.put(nl); jmp menu; //Endif multiply skipcmd4: //If Exp command cmp(eax, 5); jne skipcmd5; mov(&cmd5_ret0, ret_address); //Store return address jmp GetOperands; cmd5_ret0: stdout.putu16(bx); stdout.put("^"); stdout.putu16(ax); stdout.put("="); mov(&cmd5_ret1, ret_address_lvl2); jmp Exp; cmd5_ret1: stdout.putu32(eax); stdout.put(nl); jmp menu; //Endif Exp skipcmd5: //Else exit. stdout.put("Goodbye.",nl); jmp EndLab2; //Module:GetOperands //Description: Gets left and right operands from user and ensures that the //values can be represented with 16bits. //Parameters: //Modifies: eax, ebx //Returns: ebx - left operand, eax -right operand GetOperands: stdout.put("Enter the left operand: "); stdin.getu32(); //Temporarily Store left operand in eax //while left op >= 65536 l_test: cmp(eax, 65536); jl skipwarn; stdout.put("Left operand must be < 65536: "); stdin.getu32(); jmp l_test; //End while skipwarn: mov(eax, ebx); //Copy left operand to ebx. stdout.put("Enter the right operand: "); stdin.getu32(); //Store right operand to eax //while right op is greater than or equal to 65536 r_test: cmp(eax, 65536); jl skipwarn2; stdout.put("Right operand must be < 65536: "); stdin.getu32(); jmp r_test; //endwhile skipwarn2: jmp(ret_address); //End GetOperands //Module:Mult //Description: Multiplies two numbers. //Parameters: ebx - left operand, eax - right operand //Modifies: eax //Returns: eax - value of multiplication Mult: mov(ecx, tmp_ecx); mov(edx, tmp_edx); mov(0, edx); //if left op is less than or equal to right op cmp(ebx, eax); jg alt_loop; //loop for left op times. mov(0,ecx); forROp: cmp(ecx,ebx); jge endLoops; add(eax,edx); inc(ecx); jmp forROp; //endfor; //else right op is less than left op alt_loop: //loop for right op times. mov(0,ecx); forLOp: cmp(ecx,eax); jge endLoops; add(ebx,edx); inc(ecx); jmp forLOp; //endfor; //endif endLoops: mov(edx, eax); //Move result to eax (for code consistancy) mov(tmp_ecx, ecx); mov(tmp_edx, edx); jmp(ret_address); //End Mult //Module:Exp //Description: Raises a number in ebx to the power of eax //Paramenters: ebx - base number, eax - exponent //Modifies: eax, ecx, edx //Returns: eax - result Exp: //if(eax != 0) then cmp(eax,0); je pow0; mov(eax, edx); //edx will store number of mult operations mov(ebx, eax); //Base will be mult by itself. mov(1,ecx); expLoop: cmp(ecx,edx); jge endExp; mov(&exp_ret, ret_address); jmp Mult; exp_ret: inc(ecx); jmp expLoop; //endfor; pow0: //else mov(1, eax); //endif; endExp: jmp(ret_address_lvl2); //End Exp //Module:ToRoman //Displays a Roman numeral representation of the value in eax. //Parameters: //eax - Number to convert to Roman numerals. //Modifies: eax ToRoman: roman_loop: //while eax is greater than 0 cmp(eax,0); jle end_roman; //if(eax is greater than or equal to 1000) then cmp(eax, 1000); jl roman_D; stdout.put("M"); sub(1000, eax); jmp roman_loop; //if result is between 500(inclusive) and 1k(exclusive) roman_D: //if(eax is greater than or equal to 500) then cmp(eax,500); jl roman_C; //if(eax is greater than or equal to 900) then cmp(eax,900); jl rom_D_l; stdout.put("CM"); sub(900,eax); jmp rom_D_end; rom_D_l: //else stdout.put("D"); sub(500, eax); //endif; rom_D_end: jmp roman_loop; //if result is between 100(inc) and 500(exclusive) roman_C: //if(eax is greater than or equal to 100) then cmp(eax,100); jl roman_L; //if(eax is greater than or equal to 400) then cmp(eax,400); jl rom_C_l; stdout.put("CD"); sub(400, eax); jmp rom_C_end; rom_C_l: //else stdout.put("C"); sub(100, eax); //endif; rom_C_end: jmp roman_loop; //if result is between 50(inclusive) and 100(exclusive) roman_L: //if(eax is greater than or equal to 50) then cmp(eax,50); jl roman_X; //if(eax is greater than or equal to 90) then cmp(eax,90); jl rom_L_l; stdout.put("XC"); sub(90, eax); jmp rom_L_end; rom_L_l: //else stdout.put("L"); sub(50, eax); //endif; rom_L_end: jmp roman_loop; //if result is between 10(inclusive) and 50(exclusive) roman_X: //if(eax is greater than or equal to 10) then cmp(eax,10); jl roman_V; //if(eax is greater than or equal to 40) then cmp(eax,40); jl rom_X_l; stdout.put("XL"); sub(40, eax); jmp rom_X_end; rom_X_l: //else stdout.put("X"); sub(10, eax); //endif; rom_X_end: jmp roman_loop; //if result is between 5(inclusive) and 10(exclusive). roman_V: //if(eax is greater than or equal to 5) then cmp(eax,5); jl roman_I; //if(eax = 9) then cmp(eax,9); jne rom_V_ne; stdout.put("IX"); sub(9, eax); jmp rom_V_end; rom_V_ne: //else stdout.put("V"); sub(5, eax); //endif; rom_V_end: jmp roman_loop; roman_I: //else //if(eax == 4) then cmp(eax,4); jne rom_I_ne; stdout.put("IV"); sub(4, eax); jmp rom_I_end; rom_I_ne: //else stdout.put("I"); sub(1, eax); rom_I_end: //endif; //endif; jmp roman_loop; //endwhile end_roman: jmp(ret_address); //Return to calling code. //End ToRoman EndLab2: end lab2;
3. Screenshots
Leave a Reply