Quick Quiz #1 - DIV and MOD

Programming language questions
cfbsoftware
Posts: 55
Joined: Wed Sep 18, 2013 10:06 pm
Contact:

Re: Quick Quiz #1 - DIV and MOD

Post by cfbsoftware »

Robert wrote:I don't understand the significance of the "largeint support" comment here. Does it mean this code works with INTEGERs and LONGINTs, or with the latter only?
Only LONGINTs. After more investigation I found CPL486.GenDiv which handles both DIV and MOD for all the smaller integer types.
WARNING: the following extract contains some commented-out code: :shock:

Code: Select all

	PROCEDURE GenDiv* (VAR src: Item; mod, pos: BOOLEAN);
		VAR w, rem: INTEGER;
	BEGIN
		ASSERT(src.mode = Reg);
		IF src.form >= Int32 THEN DevCPE.GenByte(99H) (* cdq *)
		ELSIF src.form = Int16 THEN DevCPE.GenByte(66H); DevCPE.GenByte(99H) (* cwd *)
		ELSE DevCPE.GenByte(66H); DevCPE.GenByte(98H) (* cbw *)
		END;
		CheckSize(src.form, w); DevCPE.GenByte(0F6H + w); GenCExt(38H, src); (* idiv src *)
		IF src.form > Int8 THEN rem := 2 (* edx *) ELSE rem := 4 (* ah *) END;
		IF pos THEN (* src > 0 *)
			CheckSize(src.form, w); DevCPE.GenByte(8 + w); DevCPE.GenByte(0C0H + 9 * rem); (* or rem,rem *)
			IF mod THEN
				DevCPE.GenByte(79H); DevCPE.GenByte(2);	(* jns end *)
				DevCPE.GenByte(2 + w); GenCExt(8 * rem, src); (* add rem,src *)
			ELSE
				DevCPE.GenByte(79H); DevCPE.GenByte(1);	(* jns end *)
				DevCPE.GenByte(48H);					(* dec eax *)
			END
		ELSE
			CheckSize(src.form, w); DevCPE.GenByte(30H + w); GenCExt(8 * rem, src); (* xor src,rem *)
			IF mod THEN
				DevCPE.GenByte(79H);	(* jns end *)
				IF src.form = Int16 THEN DevCPE.GenByte(9); DevCPE.GenByte(66H) ELSE DevCPE.GenByte(8) END;
				DevCPE.GenByte(8 + w); DevCPE.GenByte(0C0H + 9 * rem); (* or rem,rem *)
				DevCPE.GenByte(74H); DevCPE.GenByte(4);	(* je end *)
				DevCPE.GenByte(30H + w); GenCExt(8 * rem, src); (* xor src,rem *)
				DevCPE.GenByte(2 + w); GenCExt(8 * rem, src); (* add rem,src *)
			ELSE
				DevCPE.GenByte(79H);	(* jns end *)
				IF src.form = Int16 THEN DevCPE.GenByte(6); DevCPE.GenByte(66H) ELSE DevCPE.GenByte(5) END;
				DevCPE.GenByte(8 + w); DevCPE.GenByte(0C0H + 9 * rem); (* or rem,rem *)
				DevCPE.GenByte(74H); DevCPE.GenByte(1);	(* je end *)
				DevCPE.GenByte(48H);					(* dec eax *)
			END
(*
			CheckSize(src.form, w); DevCPE.GenByte(3AH + w); GenCExt(8 * rem, src); (* cmp rem,src *)
			IF mod THEN
				DevCPE.GenByte(72H); DevCPE.GenByte(4);	(* jb end *)
				DevCPE.GenByte(7FH); DevCPE.GenByte(2);	(* jg end *)
				DevCPE.GenByte(2 + w); GenCExt(8 * rem, src); (* add rem,src *)
			ELSE
				DevCPE.GenByte(72H); DevCPE.GenByte(3);	(* jb end *)
				DevCPE.GenByte(7FH); DevCPE.GenByte(1);	(* jg end *)
				DevCPE.GenByte(48H);					(* dec eax *)
			END
*)
		END;
		a1.mode := 0; a2.mode := 0
	END GenDiv;
Robert wrote:I can't help observing that the code extract ... contains (at least) two bugs, and their fixes have been previously published:
Yes - but not included here. I should have pointed out that I use an unmodified installation of the official final release of BlackBox 1.6 from Oberon microsystems that was announced on 15 Oct 2013.
User avatar
Robert
Posts: 177
Joined: Sat Sep 28, 2013 11:04 am
Location: Edinburgh, Scotland

Re: Quick Quiz #1 - DIV and MOD

Post by Robert »

This has now beyond my comfort zone.

I speculate that the variable "pos" means that the 'm' value in "a MOD m" or "a DIV m" is known to be a positive constant (surely a common case),
and this leads to much simpler code than the general case as previous posts have surmised.

If you wish to use the "c" semantics I have a couple of routines which are comparatively short and simple:

Code: Select all

PROCEDURE [code] Rmdr* (a : LONGINT; m : INTEGER) : INTEGER
  059H,	(*  pop	m  ->  ecx  *) 
  0F7H, 0F9H,	(*  eax      :=  edx:eax / ecx	=  a  IDIV  m  *) 	(*  edx	=  a  RMDR  m  *)
  08BH, 0C2H;	(*  move  eax, edx	edx  ->  eax   *)


PROCEDURE [code] Quot* (a : LONGINT; m : INTEGER) : INTEGER
  059H,	(*  pop	m  ->  ecx  *)
  0F7H, 0F9H;	(*  eax      :=  edx:eax / ecx	=  a  IDIV  m  *) 	(*  edx	=  a  RMDR  m  *)
These are designed to be used with a & m of type INTEGER. The signature of a is LONGINT to force the compiler to do the required sign extension ; it is an essential part of the algorithm.

Robert
Post Reply