Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories

Procedure length?

so I have this working procedure that is basically like function 09h of int 21h except it terminates at 00h, and it uses 01h-04h as control characters that determine the style of the text.

I wrote it in the main procedure of a test program to get it working, and then I put it in its own procedure in a larger program. When I run it from the larger program, I get this error:

"title: 16 bit MS-DOS Subsystem

Command Prompt - cmp
NTVDM has encountered a System Error
Access is denied.
Choose 'Close' to terminate the application
Close | Ignore"

I can't really ignore it. Anyways, I narrowed the cause of this error down to a procedure without a "RET" statement. But it has a return statement at the end. If I just put RET in the procedure, it runs, if I put all of the code back into the test program (main procedure), it runs. So I'm thinking maybe there's a maximum size for a procedure that is called? It is quite long, I haven't tried to slim it down at all, I'm not sure if I really can. Anyway, here's the procedure:

[code]
outp proc

push cx
push bx
xor cx,cx
xor bx,bx
nexch: mov si,dx
push dx
add si,cx
push cx
mov al,[si]
cmp al,00h
jnz nndpr
jmp endpr
nndpr: cmp al,0dh ;LINE FEED
jnz not0d
mov ah,03h
int 10h
cmp dh,24d
jz scwin
inc dh
mov ah,02h
int 10h
jmp gnext
scwin: mov ax,0601h
xor cx,cx
mov dh,24d
mov dl,79d
mov bl,attrWHT
int 10h
jmp gnext
not0d: cmp al,0ah ;CARRIAGE RETURN
jnz not0a
mov ah,03h
int 10h
mov dl,00h
mov ah,02h
int 10h
jmp gnext
not0a: cmp al,01h ;WHITE
jnz not01
mov bl,attrWHT
mov attrCUR,bl
jmp gnext
not01: cmp al,02h ;GREEN
jnz not02
mov bl,attrGRN
mov attrCUR,bl
jmp gnext
not02: cmp al,03h ;YELLOW
jnz not03
mov bl,attrHLT
mov attrCUR,bl
jmp gnext
not03: cmp al,04h ;EDIT/HEADER
jnz not04
mov bl,attrEDT
mov attrCUR,bl
jmp gnext
not04: mov ah,09h
mov bl,attrCUR
mov cx,01h
int 10h
mov ah,03h
int 10h
inc dl
mov ah,02h
int 10h
gnext: pop cx
pop dx
inc cx
jmp nexch
endpr: pop bx
pop cx
ret
[/code]

I'm using TASM, and the model of the program is small... I tried making it "Large" and "Huge" to see how that would affect it but it said there was a problem with my call statement in the main procedure (Forward reference needs override). Has anyone run into something similar to this? How can I fix it and make it work?

Oh, and I tried doing something like this:

[code]
outp proc

jmp strprc
endprc: ret
strprc: ...
...
...
...
jmp endprc

outp endp
[/code]

the procedure did its job but it wouldn't return afterward, the cursor just sat there blinking and I couldn't input anything (text, ctrl-c, etc)

Comments

  • carsonmyerscarsonmyers Member Posts: 6
    so I figured out if I pop the stack into ax at the very beginning of the procedure (the return pointer), move that value into a variable I have saved, then push it back, then at the end of the procedure, move the variable into ax and push it again, then it will return properly, so I suppose I'm just not unwinding the stack correctly... Still I wonder why access to the procedure is denied if the RET statement is too far away? I'd like to just put it at the end and save all those unnecessary jumps
  • AtexAtex Member Posts: 268
    : so I figured out if I pop the stack into ax at the very beginning of
    : the procedure (the return pointer), move that value into a variable
    : I have saved, then push it back, then at the end of the procedure,
    : move the variable into ax and push it again, then it will return
    : properly, so I suppose I'm just not unwinding the stack correctly...
    : Still I wonder why access to the procedure is denied if the RET
    : statement is too far away? I'd like to just put it at the end and
    : save all those unnecessary jumps
    :
    Calling the int 10h interrupt destroys the bp ( base pointer ) and that's what is pointing at the stack... try: push bp as first line in your proc and pop bp at the end. Or you could modify your code to write directly into the video memory at 0800h:0, very simple to implement, need no stack management, no interrupt calls, way less clock cycles therefore way faster.
  • carsonmyerscarsonmyers Member Posts: 6
    : : so I figured out if I pop the stack into ax at the very beginning of
    : : the procedure (the return pointer), move that value into a variable
    : : I have saved, then push it back, then at the end of the procedure,
    : : move the variable into ax and push it again, then it will return
    : : properly, so I suppose I'm just not unwinding the stack correctly...
    : : Still I wonder why access to the procedure is denied if the RET
    : : statement is too far away? I'd like to just put it at the end and
    : : save all those unnecessary jumps
    : :
    : Calling the int 10h interrupt destroys the bp ( base pointer ) and
    : that's what is pointing at the stack... try: push bp as first line
    : in your proc and pop bp at the end. Or you could modify your code to
    : write directly into the video memory at 0800h:0, very simple to
    : implement, need no stack management, no interrupt calls, way less
    : clock cycles therefore way faster.
    :

    I'd like to learn to do that, but I'm afraid to get that far into it yet. I'm just learning, and getting used to assembly--but I haven't really had a problem with bp... it's just that the return address got buried in the stack, and I didn't unwind it properly. now, I'm just curious about why RET can't be at the end of my procedure

  • AtexAtex Member Posts: 268
    : : : so I figured out if I pop the stack into ax at the very beginning of
    : : : the procedure (the return pointer), move that value into a variable
    : : : I have saved, then push it back, then at the end of the procedure,
    : : : move the variable into ax and push it again, then it will return
    : : : properly, so I suppose I'm just not unwinding the stack correctly...
    : : : Still I wonder why access to the procedure is denied if the RET
    : : : statement is too far away? I'd like to just put it at the end and
    : : : save all those unnecessary jumps
    : : :
    : : Calling the int 10h interrupt destroys the bp ( base pointer ) and
    : : that's what is pointing at the stack... try: push bp as first line
    : : in your proc and pop bp at the end. Or you could modify your code to
    : : write directly into the video memory at 0800h:0, very simple to
    : : implement, need no stack management, no interrupt calls, way less
    : : clock cycles therefore way faster.
    : :
    :
    : I'd like to learn to do that, but I'm afraid to get that far into it
    : yet. I'm just learning, and getting used to assembly--but I haven't
    : really had a problem with bp... it's just that the return address
    : got buried in the stack, and I didn't unwind it properly. now, I'm
    : just curious about why RET can't be at the end of my procedure
    :
    :
    RET must be at the and, you right, I meant pop bp to be before... I got some code somewhere about direct memory writing, will be posting it soon
  • AtexAtex Member Posts: 268
    This will print a character @ x,y with a given text attribute

    mov ax, $b800
    mov es, ax
    xor bh, bh
    mov bl, x_position ;1 based
    dec bx
    shl bx, 1
    mov di, bx
    xor dh, dh
    mov dl, y_position ;1 based
    dec dx
    mov bx, dx
    shl dx, 7
    shl bx, 5
    add dx, bx
    add di, dx
    mov al, character ;any character
    mov ah, text_attribute ;upper nibble = background color, lower nibble=text olor
    stosw

  • carsonmyerscarsonmyers Member Posts: 6
    Thanks a lot, I saved that and I'll definitely learn to manipulate the screen that way in the future.
    Also, I'm finding that RET doesn't HAVE to be at the end at all, I've put it at the beginning, and placed a jump to it at the end of the procedure (and a jump over it at the beginning) and it seems to work fine. If I place it at the end of the procedure my computer generates an error when it is run. It's strange.
    Anyways, thanks for the help
  • BretBret Member Posts: 114
    Just a side note here. This code assumes that you have a color video system (not monochrome), and that the screen has 80 columns. In a testing or completely controlled environment, this is OK. However, in a "real" program, neither one of these assumptions would necessarily be true, and would need to be verified before trying to run the code as it stands.
  • carsonmyerscarsonmyers Member Posts: 6
    : Just a side note here. This code assumes that you have a color
    : video system (not monochrome), and that the screen has 80 columns.
    : In a testing or completely controlled environment, this is OK.
    : However, in a "real" program, neither one of these assumptions would
    : necessarily be true, and would need to be verified before trying to
    : run the code as it stands.

    thanks for the input, much appreciated.
    I sort of want to get my hands on a machine from a time when such verification would be necessary... it would make the programming feel more "real" rather than just toying with an older and somewhat obsolete language (in comparison with newer languages like C++ or even Visual Basic for Windows systems).
  • BretBret Member Posts: 114
    Although ASM is old, it will never be obsolete. Granted, very few people write entire programs in ASM any more, but many people use it for optimization, specialized subroutines, etc. There are some things that are either so inefficient or so confusing or just downright impossible to do in a higher level language that you really have no choice but to use ASM. The closer you get to the hardware (such as writing Device Drivers or BIOS routines), the more likely you are to need ASM.
  • carsonmyerscarsonmyers Member Posts: 6
    : Although ASM is old, it will never be obsolete. Granted, very few
    : people write entire programs in ASM any more, but many people use it
    : for optimization, specialized subroutines, etc. There are some
    : things that are either so inefficient or so confusing or just
    : downright impossible to do in a higher level language that you
    : really have no choice but to use ASM. The closer you get to the
    : hardware (such as writing Device Drivers or BIOS routines), the more
    : likely you are to need ASM.

    well, I just meant it's avoided like the plague for any regular programming project, and for passively learning a language it's not the greatest choice.
Sign In or Register to comment.