What is the best way of producing an error here?
Paul,
What is the best way of producing an error here?That depends on 1) what kind of error you want (run or assmble time) 2) the assembler you're using.
Looking at the example code it looks to me you want #2. In that case you could check if your assember has something like "@err" (for errors) and "@out" (for warnings).
And a suggestion : when one of the blocks contains an program (error) exit than you do not need to use an "else". Just make sure that the error-exit
is in the first, main block :
- - - - - - - - - -
if not @DataSize
error you must use a model with far data pointers
endif
push ds
- - - - - - - - - -
notice the "not" after the "if"
Yes, I am after an assembly error.
But neither @err nor not seem to work on masm or wasm.
@err gives an error and "not" seems to be used as a variable
which is false.
On the subject of small and medium memory model -...
how is it possible for them to work?
Those are different address spaces.
On the subject of small and medium memory model -...
how is it possible for them to work?
Those are different address spaces.
I had the same thoughts/problem. Its almost impossible to use stack-based structures/strings when DS and SS are not the same. As such they are most always (made) the same.
If you want to store data in / retrieve from the code segment of your
program (you should not, but its your choice) than you have no other option than to make sure that all three segment registers are the same (locking you into the smaller memory models).
That, or special functions that override the pointers default segment with one of your own choice (for example, mov al,[cs:si] ).
What do you mean by "smaller memory models"?
But from memory small was the default memory model for
DOS C compilers.
How did they manage to make it work?
Paul,
What do you mean by "smaller memory models"?The ones that keep DS and SS (and possibly CS) the same.
Which is the reason that, when I'm writing Assembly, I seldom (if ever) feel the need to pick a memory model where SS is different from DS. :-)
There is no choice in that case - tiny is the only one.
So long as you use far data pointers, ie compact, large and
huge, it should all be fine.
Paul,
What do you mean by "smaller memory models"?
The ones that keep DS and SS (and possibly CS) the same.
But from memory small was the default memory model for
DOS C compilers.
How did they manage to make it work?
As long as they kept SS the same as DS that one is easy - as long as you do not put (directly accessed) data in the CS segment. No extra work is
needed
If not ? Well, they would have to use segment-register overrides a lot.
Assume that SS differs from DS and you have some "local string variable" (on the stack) which you want to display. You can't use INT 21h AH=09h
directly, as it expects the string to be in the data segment.
So, you have to either write funtions which grab a byte a time while overriding the default segment for that register (mov dl,[ss:dx]), or wrap the call into a bit of code which sets DS to be the same as SS and
afterwards restores it. (push ds | mov ax,ss | mov ds,ax | .... | pop ds).
Ofcourse, if you have DS different from CS and put strings into the code segment which you want to display you would have the same problem. Heck,
the same happens when you allocate memory and want to access it : you mostly have to juggle DS and ES around to get the "movs" instruction to do its thing. :-)
In other words : Its not a rocket science needing problem, but its solution is one that needs to be applied rigorously and correctly *all the time*.
Which is the reason that, when I'm writing Assembly, I seldom (if ever) feel the need to pick a memory model where SS is different from DS. :-)
Paul,
There is no choice in that case - tiny is the only one.As you have not mentioned anything about your requirements there is no way for me to agree or disagree with the above I'm afraid ...
So long as you use far data pointers, ie compact, large andAnd create the replacement or wrapper functions for INT 21h (and other) "one segment only" calls.
huge, it should all be fine.
As I said, its not rocket science. But you might find programming Assembly
in those models becoming tiresome rather quickly.
I'm wondering how a C "hello world" could have worked in small
memory model C compiler (any vendor) when the "hello world"
string could come from either a buffer on the stack or a data
variable.
It somehow magically worked.
I'm wondering how a C "hello world" could have worked in small
memory model C compiler (any vendor) when the "hello world"
string could come from either a buffer on the stack or a data
variable.
It somehow magically worked.
I didn't need to stuff around in my hello world application program -
someone else magically dealt with that.
Now I'm trying to understand magic.
Thanks. Paul.George
I'm wondering how a C "hello world" could have worked in small
memory model C compiler (any vendor) when the "hello world"
string could come from either a buffer on the stack or a data
variable.
It somehow magically worked.
I may be mis-remembering [it has been a long time], but I believe the
"small" model was 64K code, 64K data, DS = SS.
On Thursday, November 17, 2022 at 1:34:48 AM UTC+8, George Neuner wrote:
I'm wondering how a C "hello world" could have worked in small
memory model C compiler (any vendor) when the "hello world"
string could come from either a buffer on the stack or a data
variable.
It somehow magically worked.
I may be mis-remembering [it has been a long time], but I believe the
"small" model was 64K code, 64K data, DS = SS.
Thanks, that was the secret!
Does this code look right to you (it is working, but that
doesn't necessarily mean I have adjusted sp correctly):
(btw, "ifn @DataSize" didn't work)
https://sourceforge.net/p/pdos/gitcode/ci/master/tree/pdpclib/dosstart.asm#l70
; It appears that in the tiny memory model, you are still required
; to set ds to the same as cs yourself, presumably because ds is
; pointing to the PSP while cs is probably pointing to the beginning
; of the executable. DGROUP may also get the correct value, presumably
; zero. es is set to ds a bit later. And you need to set ss to that
; value too
if @Model eq 1
mov dx, cs
else
mov dx,DGROUP
endif
mov ds,dx
; In tiny, small and medium memory models, you need to set
; ss to ds (MSDOS will have set them to different values
; when it loaded the executable).
; ds and ss are the same so that
; near pointers can refer to either stack or data and still work
if @DataSize
else
mov bx,ss
mov ax,ds
sub bx,ax
mov cl,4
shl bx,cl
mov bp, sp
sub bp, bx
mov ss, dx
mov sp, bp
; And that null PSP thing needs to be redone
mov ax, 0
push ax
endif
My testing suggests that there is a problem with tiny memory
model, but the other memory models seem to work.
if @DataSize
else
mov bx,ss
mov ax,ds
sub bx,ax
mov cl,4
shl bx,cl
mov bp, sp
sub bp, bx
mov ss, dx
mov sp, bp
; And that null PSP thing needs to be redone
mov ax, 0
push ax
endif
My testing suggests that there is a problem with tiny memory
model, but the other memory models seem to work.
Tiny is the one used by all .COM files, in those the binary has no
relocation info, it is just block copied into a newly allocated 64KB
block of memory, at offset 100h, and with those first 256 bytes (the
PSP) initialized by the OS.
In this model all segment registers are the same, i.e. CS=DS=ES=SS
because the OS and CPU are pretending to be a Z80 with no support for extended/segmented memory addressing.
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 497 |
Nodes: | 16 (2 / 14) |
Uptime: | 00:27:57 |
Calls: | 9,766 |
Calls today: | 7 |
Files: | 13,747 |
Messages: | 6,186,327 |