Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

integer input

Status
Not open for further replies.

madmardigan53

Technical User
May 31, 2003
4
US
I have written a function that allows a user to input an integer in base CX that is stored in DX.
Code:
;i:cx=base
;o:dx=number
;m:ax,bx,dx
inumber:
xor dx,dx
mov bx,1
mov ax,030
push ax
inum:
mov ah,1
int 021
cmp al,0d
je crfound
push ax
call inum
crfound:
pop ax
xor ah,ah
sub al,030
push dx
mul bx
pop dx
add dx,ax
mov ax,bx
mul cx
mov bx,ax
ret
When I compile the following program, which is supposed to accept a number and display it using a successful function, with NGASM, the console's behavior is unpredictable after the entry of the number.
Code:
mov cx,0a
call inumber
push dx
mov dl,0a
mov ah,2
int 021
pop ax
call disp_num
int 020
include func.asm
include routines.asm
Code:
;i:ax=number,cx=base
;o:none
;m:ax,dx
DISP_NUM:
  XOR   DX,DX
  DIV   CX
;---------
  PUSH  DX
;---------
  OR    AX,AX
  JZ    dn_done
  CALL  disp_num
DN_DONE:
;---------
  POP   DX
;---------
  ADD   DL,30h
  MOV   AH,2
  INT   21h
  RET
What is the problem?
 
I have corrected some errors with the function, but it still works not.
Code:
;i:cx=base
;o:dx=number
;m:ax,bx,dx
inumber:
xor dx,dx
mov bx,1
mov ax,030
push ax
mov ah,1
call inum
inum:
int 021
cmp al,0d
je crfound
push ax
call inum
pop ax
xor ah,ah
sub al,030
push dx
mul bx
pop dx
add dx,ax
mov ax,bx
mul cx
mov bx,ax
crfound:
ret
 
madmardigan53,

1. Do not use PUSH in the loop routine. Because you have to POP as many as it PUSHed. And you don't know how many times the loop will continue, right? Unless you have the counter for it.

2. Do not use CALL for loop routine. Use CALL for a procedure. Think about it this way:
- routine doesn't have a RET instruction
- procedure must have a RET instruction
Read this thread272-598082 for more explanation

Try again. Good luck

-- AirCon --
 
Thank you, but I have already fixed the error.
Code:
;i:cx=base
;o:dx=number
;m:ax,bx,dx
inumber:
xor dx,dx
mov bx,1
mov ah,1
inum:
int 021
cmp al,0d
je crfound
push ax
call inum
pop ax
xor ah,ah
sub al,030
push dx
mul bx
pop dx
add dx,ax
push dx
mov ax,bx
mul cx
mov bx,ax
pop dx
crfound:
ret
 
I think you don't get it yet :)

What I mentioned before is because of your code use PUSH and CALL in your loop. Look at this part:
Code:
inum:
  int 021
  cmp al,0d
  je crfound
  [b]push ax     ; #1
  call inum   ; #2[/b]

Do not use that kind of logic! Please read the thread (links) I've posted. It has an explanation why you must not do things like that.

-- AirCon --
 
1. Do not use PUSH in the loop routine. Because you have to POP as many as it PUSHed. And you don't know how many times the loop will continue, right? Unless you have the counter for it.
For every digit, inumber PUSHes and CALLs once. After the carriage return, it RETurns, then POPs and RETurns repeatedly; this shall return to the initial CALLing procedure on the last RET. This way, no counter is needed. If this strategy did not work, then neither would my function. PS: I based this strategy on the third block of code in my initial post, which, as evidenced by the capitalization, came with NGASM and is altered only to include more bases. This function, DISP_NUM, employs pushing and calling and works.
 
Have you read the thread I pointed to you?

1. CALL also save/store/PUSH the value to the stack! So even if you input it for once time, POP will get the value from the last value it saved, which is come from CALL.

2. for every digit it inputs, how many times it PUSHed, depends on how many characters it will get an inputs until a CR. And you only POPed it once!

Do you get that? Run debugger if you want to know exactly how it runs.


-- AirCon --
 
PS: I based this strategy on the third block of code in my initial post

Disregard my last post. I owe you apology, a BIG ONE! [blush]

Sorry I didn't noticed that your last code has been fixed the first PUSH instruction. So you are absolutely right, it works that way.

What I wanted to say from the beginning is you should be careful playing with CALL-RET, PUSH-POP tricks.

Sorry again
Regards

-- AirCon --
 
Yup, it may work, but it's a very over-complicated way to handle the problem. Is there any particular reason for avoiding a more conventional loop? If it's simply to avoid a counter when you're short of registers, remember you could have put the counter on the stack, using a single word, instead of repeated pushes and calls, which use more words. Call and ret are also quite slow instructions, not very important in this case, but worth bearing in mind for time-critical code.

And as you've discovered, bugs are a lot harder to trace in unconventional code...
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top