8088 Assembly issues.

Incinerator

Limp Gawd
Joined
Aug 31, 2005
Messages
252
I'm using Borland Turbo Assembler (have to for this class) and the purpose of this program is to take in two ints, a limit and a divisor. Then, starting from one (lets call it count) to test whether count is divisible by 2 or the user defined divisor. If count is NOT divisible by 2 or the divisor, print that number out to the screen. This should continue until count reaches the user defined limit.

Here is the code that I have and I've tried tracing through it multiple times but I just cant seem to find the problem. If you have any ideas, let me know. thanks.

Code:
; Program 5
; program reads given number of integers from user
; the program should output the sum of all integers entered

	.MODEL SMALL
	.STACK 100H
	.DATA

	limit		DW 0
	divisor		DW 0
	;some		DW 0

	.CODE

	GLOBAL ioputch:PROC, iocrlf:PROC, iowrdec:PROC, ioputs:PROC
	GLOBAL iogets:PROC, ioscanch:PROC, ioscandec:PROC

MAIN PROC

	MOV AX,@DATA
	MOV ES,AX
	MOV DS,AX

	CALL iogets		; get input
	
	CALL ioscandec		; reads first part of input
	MOV divisor, AX		; moves first input into limit used for "limit"
	
	CALL ioscandec		; reads second part of input 
	MOV limit, AX		; moves second input into divisor used for "divisor"

	MOV CX, 1		; initializes the counter to 1

mainloop:CMP CX, limit		; compares to "limit"
	JE exit			; exit program if limit and CX are holding equal values

        MOV AX, CX		; get ready for division (by "divisor")
	CWD
	IDIV divisor

	CMP DX, 0		; use modulo to see if even division or not
	JE elseloop		; jump if divisible by divisor	

	MOV BX, 2
	
	MOV AX, CX		; get ready for division by 2
	CWD
	IDIV BX
	
	CMP DX, 0
	JE elseloop

	MOV AX, CX		; prepare for iowrdec
	CALL iowrdec		; writes answer as integer

	INC CX			; increment counter variable
	CALL iocrlf		; cariage return, line feed
	JMP mainloop

elseloop:INC CX			; increments variable
	JMP mainloop		; start loop over


exit:	MOV AH,04CH		; exit program
	INT 21H 			

MAIN ENDP

END MAIN
 
why not just check to see if the final number is a 0, 2, 4, 6, 8. any number that ends in one of those is divisible by 2.
 
as far as checking to see if it is divisible by 2, no division is necessary. think about all the instructions you have available to you and what they do, especially the ones that operate on the accumulator(s). in math, how do you know if a number is divisible by 2? if it's even, right? in binary, how do you know if a number is even?....that is pretty much the answer for that part.


..what have you got so far for the second part? describe your algorithm.
 
What's wrong with the program? I don't think we have the library you're linking to, and even if we did, we don't know what it's called or if we have the same version.
 
I found the problem, it was printing out close to the right values but it was printing when divisor AND 2 when it was supposed to be printing for divisor OR 2. (bad explanation) not much changed but here is what I finished with, just in case you were curious.

(I'm pretty sure I could have just checked against divisor*2 and it would have been simpler, but I got it working so I dont care)

Code:
; Program 5

	.MODEL SMALL
	.STACK 100H
	.DATA

	limit		DW 0
	divisor		DW 0

	.CODE

	GLOBAL ioputch:PROC, iocrlf:PROC, iowrdec:PROC, ioputs:PROC
	GLOBAL iogets:PROC, ioscanch:PROC, ioscandec:PROC

MAIN PROC

	MOV AX,@DATA
	MOV ES,AX
	MOV DS,AX

	CALL iogets		; get input
	
	CALL ioscandec		; reads first part of input
	MOV divisor, AX		; moves first int into divisor
	
	CALL ioscandec		; reads second part of input 
	MOV limit, AX		; moves second int into limit

	MOV CX, 1		; initializes the counter to 1

mainloop:CMP CX, limit		; compare counter to limit
	JG exit			; is counter and limit are equal, end prog

        MOV AX, CX		; get ready for division (by "divisor")
	CWD
	IDIV divisor

	CMP DX, 0		; use modulo to see if even division or not
	JE else2		; jump if divisible by divisor	

	MOV AX, CX		; prepare for iowrdec
	CALL iowrdec		; writes answer as integer

	INC CX			; increment counter variable
	CALL iocrlf		; cariage return, line feed
	JMP mainloop

else2:	MOV BX, 2
	
	MOV AX, CX		; get ready for division by 2
	CWD
	IDIV BX
	
	CMP DX, 0
	JE elseloop

	MOV AX, CX		; prepare for iowrdec
	CALL iowrdec
	CALL iocrlf		; writes answer as integer

elseloop:INC CX			; increments variable
	JMP mainloop		; start loop over


exit:	MOV AH,04CH		; exit program
	INT 21H 			

MAIN ENDP

END MAIN
 
i think you've got some logic wrong.
Code:
mainloop:CMP CX, limit		; compare counter to limit
	JG exit

your counting is off, depending upon what JG does. according to your comments, you're off by one.

Code:
        MOV AX, CX		; get ready for division (by "divisor")
	CWD
	IDIV divisor

	CMP DX, 0		; use modulo to see if even division or not
	JE else2		; jump if divisible by divisor

integer division always results in a zero remainder. are you sure your output is valid for all possible input?

am i just pretty terrible with this instruction set, or is this student wrong with his logic?
 
The IDIV op does not truncate the remainder. divisor is a WORD, so the 16-bit IDIV will divide DX:AX by divisor and put the quotient in AX and the remainder in DX. I think the problem is that garbage is in DX for the division register.

IDIV is expensive; there are much cheaper ways to see if a number is divisible by two. I expect it doesn't matter for this application, but learning better techniques sooner might matter to the student.
 
Code:
TEST AX,1
JE DivisbleBy2
JNE NotDivisibleBy2
 
Back
Top