The irresistable source.

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

Screenshot from 2013-11-01 16:31:28

Leave a Reply

Your email address will not be published. Required fields are marked *