first ! the code's function: Conversion a character from small letter to capital letter 
  ds: point string's first address
  save result to es:
 
data segment
db "Beginner's All-Purpose Symbolic Instruction Code.",0
data ends
stackseg segment
db 0 dup(60)
stackseg ends
code segment
start:
mov ax,data
mov ds,ax
mov si,0
mov ax,stackseg
mov es,ax
mov di,0
sub ax,ax
mov cx,0ffffh
call letterc

mov ax,4c00h
int 21h
letterc:
push ax
push si
push di
push cx
sends:
cmp byte ptr ds:,61h
jb next
cmp byte ptr ds:,7ah
ja next
mov al,ds:
and al,11011111b
mov es:,al
inc si
inc di
mov cl,al
jcxz endps
jmp short sends
next:
mov al,ds:
mov cl,al
jcxz endps
mov es:,al
inc si
inc di
jmp short sends
endps:
pop cx
pop di
pop si
pop ax
ret
code ends
end start


I check my code again and again
but No problem there!
  but ,when I run this program
  error happend!  he told us:"CPU encountered an invalid command"
so I debug it by "debug" a very strange error!
you can see this error in following code

:sad: :sad: :sad: :sad: :sad:

AX=004C  BX=0000  CX=FF4C  DX=0000  SP=FFF6  BP=0000  SI=001D  DI=001D
DS=13CA  ES=13CE  SS=13CA  CS=13CE  IP=0038   NV UP EI PL NZ NA PE NC
13CE:0038 EBE7          JMP     0021   *********here
-t

AX=004C  BX=0000  CX=FF4C  DX=0000  SP=FFF6  BP=0000  SI=001D  DI=001D
DS=13CA  ES=13CE  SS=13CA  CS=13CE  IP=0021   NV UP EI PL NZ NA PE NC
13CE:0021 803C61        CMP     BYTE PTR ,61                   DS:001D=69
-t

AX=004C  BX=0000  CX=FF4C  DX=0000  SP=FFF6  BP=0000  SI=001D  DI=001D
DS=13CA  ES=13CE  SS=13CA  CS=13CE  IP=0024   NV UP EI PL NZ NA PO NC
13CE:0024 7214          JB      003A
-t

AX=004C  BX=0000  CX=FF4C  DX=0000  SP=FFF6  BP=0000  SI=001D  DI=001D
DS=13CA  ES=13CE  SS=13CA  CS=13CE  IP=0026   NV UP EI PL NZ NA PO NC
13CE:0026 803C7A        CMP     BYTE PTR ,7A                   DS:001D=69
-t

AX=004C  BX=0000  CX=FF4C  DX=0000  SP=FFF6  BP=0000  SI=001D  DI=001D
DS=13CA  ES=13CE  SS=13CA  CS=13CE  IP=0029   NV UP EI NG NZ AC PO CY
13CE:0029 770F          JA      003A
-



AX=004E  BX=0000  CX=FF4E  DX=0000  SP=FFF6  BP=0000  SI=0022  DI=0022
DS=13CA  ES=13CE  SS=13CA  CS=13CE  IP=0038   NV UP EI PL NZ NA PE NC
13CE:0038 EBE7          JMP     0021
-t

AX=004E  BX=0000  CX=FF4E  DX=0000  SP=FFF6  BP=0000  SI=0022  DI=0022
DS=13CA  ES=13CE  SS=13CA  CS=13CE  IP=0021   NV UP EI PL NZ NA PE NC
13CE:0021 4E            DEC     SI *******here
-t

AX=004E  BX=0000  CX=FF4E  DX=0000  SP=FFF6  BP=0000  SI=0021  DI=0022
DS=13CA  ES=13CE  SS=13CA  CS=13CE  IP=0022   NV UP EI PL NZ NA PE NC
13CE:0022 3C61          CMP     AL,61
-t

AX=004E  BX=0000  CX=FF4E  DX=0000  SP=FFF6  BP=0000  SI=0021  DI=0022
DS=13CA  ES=13CE  SS=13CA  CS=13CE  IP=0024   NV UP EI NG NZ NA PE CY
13CE:0024 7214          JB      003A
-t

AX=004E  BX=0000  CX=FF4E  DX=0000  SP=FFF6  BP=0000  SI=0021  DI=0022
DS=13CA  ES=13CE  SS=13CA  CS=13CE  IP=003A   NV UP EI NG NZ NA PE CY
13CE:003A 8A04          MOV     AL,                            DS:0021=6E
-


why the code is differernt of previous!!! so strange
Posted on 2008-12-11 21:12:48 by dapro
The code modifies itself after several iterations.

mov cl,al
jcxz endps

CX is never zero at this point. The code keeps modyfying itself until it crashes.

Additionally, I don't understand why you call a piece of memory "stack segment" if you don't use it as stack.
Posted on 2008-12-11 21:54:21 by ti_mo_n
ti_mo_n  you are right! the same happens with MOV CS,AX

(crashes app)
Posted on 2008-12-30 14:20:05 by kernal32.dll
The main problem in that the ES segment register is probably the same as the CS segment register at the opening of the program. The DS register is correctly adjusted for pointing to the data area but the ES register is not modified in any way.

If I remember right, in 16-bit DOS mode, the use of the DI register defaults to the ES segment unless a segment override is specified. In the above code trace, it is clear that ES is the same as the CS code segment and data is being stored where DI is pointing inside the code segment.

Solution: Forget about using a "stack" area for storing data. USE THE DATA AREA. In addition, modify the ES register in the same way as the DS segment register.
Posted on 2008-12-30 20:37:29 by Raymond
ES is being set to the area called "stack" (look closely). It's not being used as stack, but it's just a (here confusing) name. CX is never 0 at the point I scpecified. That's why the code does not end and eventually it overwrites itself (by default, assemblers create sections exactly as they are specified in the source, so the sections named 'data' and 'stack' are right before the code).

The overwriting is shown by the author of the thread. For example 13CE:0021 holds "CMP    BYTE PTR ,61" as intended, but after (too many) iterations it holds "DEC    SI". The loop needs about 60 iterations to start modyfying the code.
Posted on 2008-12-30 22:03:21 by ti_mo_n
ES is being set to the area called "stack" (look closely).


I saw that. However, if you look at the trace, ES=CS. Even if he corrects that instruction to end the loop properly, his test string is long enough to overwrite that code section because his destination register DI is defaulting to ES which is the code section (look closely).

The loop needs about 60 iterations to start modyfying the code.


His code started to be modified as soon as he entered the loop and stored his first upper case letter. It only showed when the top of the loop "started" to be modified by the 33rd letter of the string (21h) which so happens to be the letter N which has 4Eh as its binary representation.
Posted on 2008-12-31 00:32:24 by Raymond
Tried assembling it? takes a couple of seconds, so does linking, but:
LINK : warning L4021: no stack segment

You can call it stackseg, but it ain't a stack segment...and "db 0 dup(60)" assembled to a zero-sized segment, that's why ES=CS.
Posted on 2008-12-31 01:10:39 by sinsi
Yes, but there is no problem with no stack segment (that's why it's just a warning), because in DOS you always have some default stack. The program works, but it crashes right after it overwrites itself. The problem is with the loop itself. making CH equal to 0 should solve the issue.
And there is no problem with ES being equal with CS. Segments just point to things. And it's normal (esp. in so called "tiny" programs) for segment registers to be equal.
Posted on 2008-12-31 07:02:17 by ti_mo_n
Posted on 2008-12-31 12:15:31 by Raymond
No I dont need to remember that, I can search for it now, lol
Posted on 2008-12-31 22:17:24 by Homer
As long as you never use it to write blindly within that segment which happens to be the code segment. You must remember that under DOS, ES is the default segment when using DI as an offset!!!!!!!!!

True, but it's not the problem of this code! :)
Posted on 2009-01-01 01:01:11 by ti_mo_n

As long as you never use it to write blindly within that segment which happens to be the code segment. You must remember that under DOS, ES is the default segment when using DI as an offset!!!!!!!!!

True, but it's not the problem of this code! :)


If you look closely at the code posted at the start of this thread, you will find the following instruction after the letter is converted to uppercase:

Posted on 2009-01-01 22:13:07 by Raymond
Maybe it's supposed to be

stackseg segment
db 60 dup(0)
stackseg ends

But the "mov cx,ffff" and the later "jcxz" mean it doesn't work anyway.
Posted on 2009-01-01 22:28:21 by sinsi
But the "mov cx,ffff" and the later "jcxz" mean it doesn't work anyway.


Those instructions would be perfectly correct if only the "mov cl,al" would have been "mov cx,ax".

You will notice that AX was rezeroed before the loop (sub ax,ax). Since only the AL register is used within the loop, AX returns back to 0 when the terminating NULL of the string is processed in AL. The code would thus allow the processing of null-terminated strings of variable sizes without the need of determining the actual size.

Obviously, similar results can be obtained with various other instructions (which would be considered more efficient by our optimization gurus) such as:

test al,al
jnz top_of_loop
Posted on 2009-01-01 22:49:16 by Raymond
Yeah, well "mov si,0" is wrong, "mov cx,ffff" is not needed, there's a lot wrong here.
Maybe the original poster can reply?
Posted on 2009-01-01 23:15:10 by sinsi
(...)

Raymond, I just wanted to point the author to the solution by showing him/her the fact that the code is overwriting itself. The pointers themselves are of little importance because the main problem of the code is the infinite loop (because of CH equal to 0xff). BUT I see that all this is irrelevant now because the author apparently is not interested in knowing the answer ^^'

/edit
corrected some typos
Posted on 2009-01-02 00:52:06 by ti_mo_n
With his apparently very limited knowledge of assembly instructions, I still think that he needs to be commended for at least thinking of a novel way to end the loop with a null-terminated string using jcxz, although his application of it was somewhat faulty.

And, I still think he is following this thread and learning a few more things in the process. Let's give him the benefit of the doubt at this point.
Posted on 2009-01-02 21:36:59 by Raymond