;----------------------------------------------- ; BIOS routines: INIT32: equ #006F CHGET: equ #009f CHPUT: equ #00A2 CLS: equ #00C3 ; Other constants: MAX_DIGITS: equ 6 ;----------------------------------------------- org #4000 ;----------------------------------------------- ; ROM header: db "AB" ; ROM signature dw execute ; start address db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ;----------------------------------------------- execute: call INIT32 ; Switch to SCREEN 1 video mode call CLS ; Clear the screen ; Request the first number: ld hl, prompt_first_number call print_string call request_number ld bc, input_buffer call convert_ascii_to_integer ld (number1), hl ; Request the second number: ld hl, prompt_second_number call print_string call request_number ld bc, input_buffer call convert_ascii_to_integer ld (number2), hl ; Add the two numbers together: ld hl,(number1) ld bc,(number2) add hl,bc ; Convert he result to ASCII to show in the screen: ld bc,result_buffer call integer_to_ascii ; Show the result in the screen: ld hl, prompt_result call print_string ld hl,result_buffer call print_string ; Skip a couple of lines ld hl,end_of_line call print_string ld hl,end_of_line call print_string ld hl,prompt_restart call print_string wait_for_return_loop: call CHGET cp 13 ; carriage return jr z, execute ; restart jr wait_for_return_loop ;----------------------------------------------- ; Prints a 0-terminated string to screen using the CHPUT BIOS call. print_string: ld a,(hl) cp 0 ret z push hl call CHPUT pop hl inc hl jr print_string ;----------------------------------------------- ; Gets a number from the user, and stores the digits in "input_buffer" request_number: ld hl, input_buffer ld b, MAX_DIGITS request_number_loop: push hl push bc call CHGET pop bc pop hl ; only accept numbers or carriage return: cp 13 ; carriage return jr z, request_number_done cp '0' jr c, request_number_loop ; invalid character (lower than '0') cp '9' + 1 jr nc, request_number_loop ; invalid character (higher than '9') request_number_valid_character: ld (hl), a inc hl push hl call CHPUT ; echo the character that was entered pop hl djnz request_number_loop ; only iterate for at most MAX_DIGITS request_number_done: ld (hl), 0 ; terminate the input string with a 0 ld hl, end_of_line call print_string ; print a line feed and a carriage return to move to the next line ret ;----------------------------------------------- ; input: ; - bc: pointer to the 0 terminated string with the digits to convert ; output: ; - hl: the resulting integer convert_ascii_to_integer: ld hl, 0 convert_ascii_to_integer_loop: ld a, (bc) cp 0 ret z ; If we have reached the end of the string, we are done ; Multiply by 10 the current integer: call multiply_hl_by_10 ; Add the current digit ld a, (bc) sub '0' ld d, 0 ld e, a add hl, de inc bc jr convert_ascii_to_integer_loop ;----------------------------------------------- ; Multiply hl by 10: multiply_hl_by_10: push bc add hl,hl ; times 2 ld b, h ld c, l ; store hl * 2 in bc add hl,hl ; times 4 add hl,hl ; times 8 add hl,bc ; add bc (so, now it's hl*8 + hl*2 = hl*10) pop bc ret ;----------------------------------------------- ; input: ; - hl: 16 bit number to convert ; - bc: pointer where to store the ascii representation of the number integer_to_ascii: ld a, 0 ld (bc), a ; We start by terminating the string with a 0 integer_to_ascii_loop: push bc call divide_hl_by_10 pop bc ; shift all the string one position to the right, to insert the new digit at the beginning: push hl push bc ld hl, MAX_DIGITS add hl, bc ld d, h ld e, l ; de = bc + MAX_DIGITS (pointing to the end of the string) dec hl ; hl = bc + MAX_DIGITS - 1 (pointing one byte before the end of the string) ld bc, MAX_DIGITS lddr pop bc pop hl add a, '0' ld (bc), a ; Check if we are done (if hl == 0): ld a, h or l jr nz, integer_to_ascii_loop ret ;----------------------------------------------- ; Divide "hl" by "10", output is: ; - division result in "hl" ; - remainder in "a" divide_hl_by_10: push bc ld a, 0 ld b, 16 ; length in bits of the dividend divide_hl_by_10_loop: add hl, hl ; next bit rla cp 10 jp c,divide_hl_by_10_next_bit sub 10 inc l divide_hl_by_10_next_bit: djnz divide_hl_by_10_loop pop bc ret ;----------------------------------------------- end_of_line: db 10, 13, 0 prompt_first_number: db "Enter the first number:", 10, 13, 0 ; 10 and 13 are used to start a new line prompt_second_number: db "Enter the second number:", 10, 13, 0 prompt_result: db "And the result is: ", 10, 13, 0 prompt_restart: db "Press enter to restart", 10, 13, 0 ds #8000 - $ ; fill the ROM all the way until #8000, so, the cartridge is 16KB ;----------------------------------------------- ; RAM area org #c000 input_buffer: ds virtual MAX_DIGITS + 1 result_buffer: ds virtual MAX_DIGITS + 1 number1: ds virtual 2 ; variables to store the two integers as 16 bit numbers (2 bytes) number2: ds virtual 2