I'm learning assembly and I have to write a procedure (function) which gets a number and returns 1
if it's an even number and 0
if it's not.
I have to return the answer not via a register or flags, but via the stack (e.g. I can't put the answer in bx
or ax
and check their value in the main program). How can I do that?
Next program was made with EMU8086 Intel syntax (just copy, paste and run), this is what it does : displays a message, captures a number from keyboard, converts the number from string to numeric, checks if number is even or odd, stores '1' or '0' in stack, and displays a message depending on '1' or '0'. Here it is, plenty of comments to help you understand :
.stack 100h
;------------------------------------------
.data
msj1 db 13,10,'Enter the number: $'
msj2 db 13,10,'The number is even$'
msj3 db 13,10,'The number is odd$'
str db 6 ;MAX NUMBER OF CHARACTERS ALLOWED (5).
db ? ;LENGTH (NUMBER OF CHARACTERS ENTERED BY USER).
db 6 dup (?) ;CHARACTERS ENTERED BY USER.
;------------------------------------------
.code
;INITIALIZE DATA SEGMENT.
mov ax, @data
mov ds, ax
;DISPLAY MESSAGE.
call clear_screen ;DECLARED AT THE END OF THIS CODE.
mov ah, 9
mov dx, offset msj1
int 21h
;CAPTURE NUMBER FROM KEYBOARD AS STRING.
mov ah, 0Ah
mov dx, offset str
int 21h
;CONVERT CAPTURED NUMBER FROM STRING TO NUMERIC.
mov si, offset str ;PARAMETER FOR STRING2NUMBER.
call string2number ;NUMBER RETURNS IN BX.
;CALL PROC TO FIND OUT IF NUMBER IS EVEN OR ODD. THE INSTRUCTION
;"CALL" WILL PUSH IN STACK THE ADDRESS OF THIS INSTRUCTION, THAT'S
;HOW IT KNOWS HOW TO COME BACK HERE TO CONTINUE EXECUTION.
call even_or_odd
;GET RESULT FROM STACK.
pop ax
;DISPLAY RESULT.
cmp al, '1'
je even_number
;IF NO JUMP, AL == '0'.
mov ah, 9
mov dx, offset msj3
int 21h
jmp wait_for_key ;SKIP "EVEN_NUMBER".
even_number:
mov ah, 9
mov dx, offset msj2
int 21h
;WAIT FOR USER TO PRESS ANY KEY.
wait_for_key:
mov ah,7
int 21h
;FINISH THE PROGRAM.
mov ax, 4c00h
int 21h
;------------------------------------------
;THIS PROCEDURE RETURNS '1' IN STACK IF THE NUMBER
;IS EVEN OR '0' IF IT'S ODD.
;ASSUME THE NUMBER COMES IN BX.
proc even_or_odd
;DIVIDE NUMBER BY 2.
mov ax, bx
mov bl, 2
div bl ;AX / BL (NUMBER / 2). RESULT : QUOTIENT=AL, REMAINDER=AH.
;IF REMAINDER IS 0 THEN NUMBER IS EVEN, ELSE IT'S ODD.
cmp ah, 0
je its_even
;IF NO JUMP, IT'S ODD.
mov ax, '0' ;VALUE TO STORE IN STACK.
jmp finish ;SKIP "ITS_EVEN".
its_even:
mov ax, '1' ;VALUE TO STORE IN STACK.
finish:
;STORE VALUE IN STACK. IMPORTANT: WHEN THIS PROCEDURE
;WAS CALLED, THE RETURN ADDRESS WAS PUSHED IN STACK. TO
;RETURN THE VALUE IN STACK IT'S NECESSARY TO RETRIEVE
;THE RETURN ADDRESS FIRST, PUSH THE VALUE ('0' OR '1')
;AND PUSH THE RETURN ADDRESS BACK.
pop bx ;RETRIEVE RETURN ADDRESS FROM THE CALL.
push ax ;VALUE TO RETURN ('0' OR '1').
push bx ;PUT RETURN ADDRESS BACK.
ret ;THIS "RET" POPS THE RETURN ADDRESS. THIS IS HOW
endp ;IT KNOWS HOW TO RETURN WHERE THE PROC WAS CALLED.
;------------------------------------------
;CONVERT STRING TO NUMBER IN BX.
;SI MUST ENTER POINTING TO THE STRING.
proc string2number
;MAKE SI TO POINT TO THE LEAST SIGNIFICANT DIGIT.
inc si ;POINTS TO THE NUMBER OF CHARACTERS ENTERED.
mov cl, [ si ] ;NUMBER OF CHARACTERS ENTERED.
mov ch, 0 ;CLEAR CH, NOW CX==CL.
add si, cx ;NOW SI POINTS TO LEAST SIGNIFICANT DIGIT.
;CONVERT STRING.
mov bx, 0
mov bp, 1 ;MULTIPLE OF 10 TO MULTIPLY EVERY DIGIT.
repeat:
;CONVERT CHARACTER.
mov al, [ si ] ;CHARACTER TO PROCESS.
sub al, 48 ;CONVERT ASCII CHARACTER TO DIGIT.
mov ah, 0 ;CLEAR AH, NOW AX==AL.
mul bp ;AX*BP = DX:AX.
add bx,ax ;ADD RESULT TO BX.
;INCREASE MULTIPLE OF 10 (1, 10, 100...).
mov ax, bp
mov bp, 10
mul bp ;AX*10 = DX:AX.
mov bp, ax ;NEW MULTIPLE OF 10.
;CHECK IF WE HAVE FINISHED.
dec si ;NEXT DIGIT TO PROCESS.
loop repeat ;COUNTER CX-1, IF NOT ZERO, REPEAT.
ret
endp
;------------------------------------------
proc clear_screen
mov ah,0
mov al,3
int 10H
ret
endp
Notice the variable "str", used to capture the number from keyboard, uses the 3-DB format: the first DB specifies the max length (plus one for the ending chr(13)), another DB for the length of the string entered by user, and the third DB for the string itself.
Jester's is another solution for the problem. There's even a third solution : shifting the number to the right (instruction SHR), the dropped bit is stored in carry flag, then we can check if carry flag is 0 or 1 with instructions JC or JNC.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With