Alright, so I am making this program that is supposed to do four things:
Echo the string back in uppercase, lowercase, normal case, and, for extra credit, reverse. With a newline for each string! Here is my code so far:
.286
.MODEL SMALL
.STACK 4096
.DATA
;---- Any data you need... declared here :)
buffer BYTE "ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopq rstuvwxyz", 0
PSP_CMDLINE_LEN EQU 80h
PSP_CMDLINE EQU 81h
;------------------------------ CODE SEGMENT --------------------------------
.CODE
; - - - - MAIN PROCEDURE - - - - - - - - - - - - - - - - - - - - - - - -
MAIN PROC
.STARTUP ; Startup macro MUST be 1st thing in MAIN proc
XOR AX, AX ; AX = 0
MOV AL, ES:[PSP_CMDLINE_LEN] ; AX = Length of cmd line
MOV SI, PSP_CMDLINE ; SI = offset cmd line data
ADD SI, AX ; SI = offset of END of cmdline
MOV BYTE PTR ES:[SI], 0
MOV SI, (PSP_CMDLINE+1) ; ES:SI PTR BYTE to Cmd line (skip space)
LOOP_TOP:
MOV DL, ES:[SI] ; DL = char at address in ES:SI, Note the ES: Segment override prefix
CMP DL, 0 ; Is DL terminating zero byte?
JE PAST_LOOP ; Skip past end of loop
MOV AH, 2 ; DOS SYSCALL, AH=2 ==> Prints char in DL
MOV AX, OFFSET buffer ;new code, will insert into main procedure when I can keep it from messing up
PUSH AX
CALL upperCase
ADD SP, 4 ;still new code
;INT 21H ; Print DL to std output device (the screen usually)
INC SI ; SI=SI+1, points to next char in Message
JMP LOOP_TOP
PAST_LOOP:
; ---- Using .EXIT Macro makes life MUCH easier.
.EXIT
MAIN ENDP
;-------------------------------------------------------
;upperCase (string alphabet)
;alphabet BP+4
;RA BP+2
;old bp BP+0
;Compares each char to the alphabet seeing if it is equal, and if it is, prints the letter in uppercase.
;If not, the letter is decremented by 20 hex and made capitalized.
;
;
;
;
;
upperCase PROC
PUSH BP
MOV BP, SP
PUSH SI
MOV SI, [BP+4] ;Gets alphabet
topOfLoop:
CMP DL, [SI] ;Compares char in DL with SI
JG SubLoop ;Jumps to Subloop to subtract if DL is greater
INC SI ;gets next char
JMP topOfLoop
SubLoop:
MOV AH, 2
SUB DL, 20h
INT 21h
JMP outtaLoop
outtaLoop:
POP SI
MOV SP, BP
POP BP
RET
upperCase ENDP
;-------------------------------------------------------
;lowerCase (string alphabet)
;alphabet BP+4
;RA BP+2
;old bp BP+0
;Compares each char to the alphabet seeing if it is equal, and if it is, prints the letter in uppercase.
;If not, the letter is decremented by 20 hex and made capitalized.
;
;
;
;
;
lowerCase PROC
PUSH BP
MOV BP, SP
PUSH SI
MOV SI, [BP+4] ;Gets alphabet
topOfLoop:
CMP DL, [SI] ;Compares char in DL with SI to see if it is equal
JG SubLoop ;Jumps to Subloop to subtract
INC SI ;gets next char
JMP topOfLoop
SubLoop:
MOV AH, 2
ADD DL, 20h
INT 21h
JMP outtaLoop
outtaLoop:
POP SI
MOV SP, BP
POP BP
RET
lowerCase ENDP
END
Now I felt pretty happy when I got it to return me everything in all caps (or all lowercase if I simply change that ADD to SUB), but I realized it still subtracts 20h when the original character is capitalized, giving me non-alphanumeric letters off the ASCII table. I've been fumbling to figure out the issue and I'm not really sure how to do it.
Echo the string back in uppercase, lowercase, normal case, and, for extra credit, reverse. With a newline for each string! Here is my code so far:
.286
.MODEL SMALL
.STACK 4096
.DATA
;---- Any data you need... declared here :)
buffer BYTE "ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopq rstuvwxyz", 0
PSP_CMDLINE_LEN EQU 80h
PSP_CMDLINE EQU 81h
;------------------------------ CODE SEGMENT --------------------------------
.CODE
; - - - - MAIN PROCEDURE - - - - - - - - - - - - - - - - - - - - - - - -
MAIN PROC
.STARTUP ; Startup macro MUST be 1st thing in MAIN proc
XOR AX, AX ; AX = 0
MOV AL, ES:[PSP_CMDLINE_LEN] ; AX = Length of cmd line
MOV SI, PSP_CMDLINE ; SI = offset cmd line data
ADD SI, AX ; SI = offset of END of cmdline
MOV BYTE PTR ES:[SI], 0
MOV SI, (PSP_CMDLINE+1) ; ES:SI PTR BYTE to Cmd line (skip space)
LOOP_TOP:
MOV DL, ES:[SI] ; DL = char at address in ES:SI, Note the ES: Segment override prefix
CMP DL, 0 ; Is DL terminating zero byte?
JE PAST_LOOP ; Skip past end of loop
MOV AH, 2 ; DOS SYSCALL, AH=2 ==> Prints char in DL
MOV AX, OFFSET buffer ;new code, will insert into main procedure when I can keep it from messing up
PUSH AX
CALL upperCase
ADD SP, 4 ;still new code
;INT 21H ; Print DL to std output device (the screen usually)
INC SI ; SI=SI+1, points to next char in Message
JMP LOOP_TOP
PAST_LOOP:
; ---- Using .EXIT Macro makes life MUCH easier.
.EXIT
MAIN ENDP
;-------------------------------------------------------
;upperCase (string alphabet)
;alphabet BP+4
;RA BP+2
;old bp BP+0
;Compares each char to the alphabet seeing if it is equal, and if it is, prints the letter in uppercase.
;If not, the letter is decremented by 20 hex and made capitalized.
;
;
;
;
;
upperCase PROC
PUSH BP
MOV BP, SP
PUSH SI
MOV SI, [BP+4] ;Gets alphabet
topOfLoop:
CMP DL, [SI] ;Compares char in DL with SI
JG SubLoop ;Jumps to Subloop to subtract if DL is greater
INC SI ;gets next char
JMP topOfLoop
SubLoop:
MOV AH, 2
SUB DL, 20h
INT 21h
JMP outtaLoop
outtaLoop:
POP SI
MOV SP, BP
POP BP
RET
upperCase ENDP
;-------------------------------------------------------
;lowerCase (string alphabet)
;alphabet BP+4
;RA BP+2
;old bp BP+0
;Compares each char to the alphabet seeing if it is equal, and if it is, prints the letter in uppercase.
;If not, the letter is decremented by 20 hex and made capitalized.
;
;
;
;
;
lowerCase PROC
PUSH BP
MOV BP, SP
PUSH SI
MOV SI, [BP+4] ;Gets alphabet
topOfLoop:
CMP DL, [SI] ;Compares char in DL with SI to see if it is equal
JG SubLoop ;Jumps to Subloop to subtract
INC SI ;gets next char
JMP topOfLoop
SubLoop:
MOV AH, 2
ADD DL, 20h
INT 21h
JMP outtaLoop
outtaLoop:
POP SI
MOV SP, BP
POP BP
RET
lowerCase ENDP
END
Now I felt pretty happy when I got it to return me everything in all caps (or all lowercase if I simply change that ADD to SUB), but I realized it still subtracts 20h when the original character is capitalized, giving me non-alphanumeric letters off the ASCII table. I've been fumbling to figure out the issue and I'm not really sure how to do it.