otacon14112
Experienced Member
I slowly keep adding more functionality to my single board computer. The most recent subroutine I wrote converts AL from binary to two ASCII characters representing the two hexadecimal digits of AL. However, when I try to print the newly-converted ASCII characters, my PrintChar subroutine doesn't do its job on the physical system.
The funny thing is, when I step through the program in DOS DEBUG, it works exactly as I intend it to. During debug, it correctly converts the two nibbles into two ASCII hex digits, and stores them in AX. The PrintChar subroutine only cares about AL. Anything can be in AH, because it only sends what's in AL out the IO ports. It correctly steps through everything until it gets to the infinite loop. But not on the physical system.
What would make a subroutine that works earlier in the program not work later? Could any flags cause this? Still, like I said, it works the way I intend it to in debug. After returns, it goes to the next instruction in the program.
Here's a picture of my computer: http://i.imgur.com/9IFvTIi.jpg
You can see that it correctly prints "Hi:", but it won't print text after ToHex8Bit is called.
I can provide a link to the bin so that you can step through the same bin I'm stepping through if you want. Just don't sue me!
Here's my NASM code:
I'm really curious what ideas anyone may have for why it works in debug but not in the physical system. Thanks guys
The funny thing is, when I step through the program in DOS DEBUG, it works exactly as I intend it to. During debug, it correctly converts the two nibbles into two ASCII hex digits, and stores them in AX. The PrintChar subroutine only cares about AL. Anything can be in AH, because it only sends what's in AL out the IO ports. It correctly steps through everything until it gets to the infinite loop. But not on the physical system.
What would make a subroutine that works earlier in the program not work later? Could any flags cause this? Still, like I said, it works the way I intend it to in debug. After returns, it goes to the next instruction in the program.
Here's a picture of my computer: http://i.imgur.com/9IFvTIi.jpg
You can see that it correctly prints "Hi:", but it won't print text after ToHex8Bit is called.
I can provide a link to the bin so that you can step through the same bin I'm stepping through if you want. Just don't sue me!
Here's my NASM code:
Code:
; ************************************************
; * *
; * Convert a byte to hex, then print it *
; * *
; ************************************************
;
; Subroutines in this program:
; ***************************
; ToHex8Bit
; InitDelay
; CharDelay
; LatchDelay
; PrintChar
; LatchCMD
; ClearPort2
; InitPorts
; InitLCD
USE16
section .data
_1KB equ 1024
_2KB equ 2048
_32KB equ 32*_1KB
_128KB equ 128*_1KB
_256KB equ 256*_1KB
PORT1 equ 0x01
PORT2 equ 0x02
ROM_SIZE equ _128KB ; Set size of ROM here
org 0x100
section .text
start:
; Set stuff up
mov sp,0xFFFF ; Initialize the stack pointer to 64KB.
; This is 384KB in memory, 64KB
; above the SS
mov bx, ss ; Initialize BX to 0, since SS hasn't
; changed yet
mov ax,0x5000 ; Initialize SS to be at 320KB,
mov ss,ax ; 64KB below the end of RAM
call InitPorts ; Set up the 8255
call InitDelay ; Give the LCD time to self-initialize
call InitLCD ; Run the initialization sequence
mov al,"H"
call PrintChar
mov al,"i"
call PrintChar
mov al, ":"
call PrintChar
mov al, 11010111b
call ToHex8Bit
mov bx, ax
mov al, ah
call PrintChar
mov al, bl
call PrintChar
jmp $
ToHex8Bit:
push bx ; Save the registers
push ax
ParseLoNibble: shl al, 4 ; Get rid of the high nibble
shr al, 4 ; Get the low nibble
cmp al, 0x09 ; Is the nibble numeric or alpha?
jle BToHLoNibNum ; If numeric, go here
jg BToHLoNibAlpha ; If alpha, go here
ParseHiNibble:
mov bl, al ; Store low hex nibble in BL
pop ax ; Get the original byte back
shr al, 4 ; Get rid of the low nibble
cmp al, 0x09 ; Is the nibble numeric or alpha?
jle BToHHiNibNum ; If numeric, go here
jg BToHHiNibAlpha ; If alpha, go here
ExitToHex8Bit:
mov bh, al ; Store high nibble in BH
mov ax, bx ; Put both hex digits in AX
pop bx ; Get back whatever was in BX
ret
BToHLoNibNum: add al, 48 ; Convert the number to ASCII
jmp ParseHiNibble
BToHLoNibAlpha: add al, 55 ; Convert the alpha char to ASCII
jmp ParseHiNibble
BToHHiNibNum: add al, 48 ; Convert the number to ASCII
jmp ExitToHex8Bit
BToHHiNibAlpha: add al, 55 ; Convert the alpha char to ASCII
jmp ExitToHex8Bit
InitDelay: mov word [bx],0x01FF; Set the countdown timer.
StartInitDel: dec word [bx] ; Decrement it by 1 each time.
cmp word [bx],00h ; If the timer has counted down
; all the way, return to the
; 'nextloop' label so that it
; can move on to the next hex
; value to display on the LEDs.
jnz StartInitDel ; If the counter hasn't counted
; down to 00h yet, keep going.
ret
CharDelay: mov word [bx],0x001F; Set the countdown timer.
StartCharDel: dec word [bx] ; Decrement it by 1 each time.
cmp word [bx],00h ; If the timer has counted down
; all the way, return to the
; 'nextloop' label so that it
; can move on to the next hex
; value to display on the LEDs.
jnz StartCharDel ; If the counter hasn't counted
; down to 00h yet, keep going.
ret
LatchDelay: mov word [bx],0x002F; Set the countdown timer.
StartDel: dec word [bx] ; Decrement it by 1 each time.
cmp word [bx],00h ; If the timer has counted down
; all the way, return to the
; 'nextloop' label so that it
; can move on to the next hex
; value to display on the LEDs.
jnz StartDel ; If the counter hasn't counted
; down to 00h yet, keep going.
ret
PrintChar:
push ax ; Save the ASCII character
mov al,0x02 ; Make RS high, E low
out PORT2,al
pop ax ; Get the ASCII character back
out PORT1,al ; Send the character to the display
mov al,0x06 ; Make E and RS high
out PORT2,al
call CharDelay
mov al,0x02 ; Make RS high, E low
out PORT2,al
call CharDelay
ret
LatchCMD:
mov al,0x04 ; Make E high to latch the data
out PORT2,al
call LatchDelay
call ClearPort2
call LatchDelay
ret
ClearPort2:
mov al,0x00 ; Clear the port
out PORT2,al
ret
InitPorts:
mov al,0x90 ; This sets the 8255 to operate
out 0x03,al ; in Mode 0 (basic I/O)
; Input Output
; ***** ******
; Port 0 Ports 1, 2
ret
InitLCD:
; Reset sequence 1
mov al,0x30
out PORT1,al
call LatchCMD
; Reset sequence 2
mov al,0x30
out PORT1,al
call LatchCMD
; Reset sequence 3
mov al,0x30
out PORT1,al
call LatchCMD
; 8-bit, 2 lines, 5x8 characters
mov al,0x38
out PORT1,al
call LatchCMD
; End of step 1
; Increment, and no display shift
mov al,0x06
out PORT1,al
call LatchCMD
; Turn display on, cursor on, and do not blink the
; character at cursor
mov al,0x0C
out PORT1,al
call LatchCMD
; Clear the display
mov al,0x01
out PORT1,al
call LatchCMD
; DDRAM address set to home, position top left most character
mov al,0x80
out PORT1,al
call LatchCMD
ret
times ((ROM_SIZE-16) - ($-$$)) db 0
db 0xEA ; far jump
dw start ; Sets the offset IP value
dw 0x10000-(ROM_SIZE/16)-0x10; Target CS value
times ROM_SIZE - ($-$$) db 0
I'm really curious what ideas anyone may have for why it works in debug but not in the physical system. Thanks guys
Last edited: