Discussion:
How to access stack-based data (strings) when SS <> DS ?
(too old to reply)
R.Wieser
2021-12-04 07:56:24 UTC
Permalink
Hello all,

As an assembly programmer I never needed to write *big* programs, and
therefore always used the "tiny" memory model where CS = DS = SS.

Though at some point I realized that not having SS equal to DS creates its
own problems - when trying to access stack-based data (strings).

A "lea dx,[Stack-based item]" will work, but, for example, using it with
"mov ah,09h", "int 21h" will ofcourse fail, as DX is not pointing into DS.

My question :
Does anyone know how this is solved ? Other than (manually!) wrapping all
such calls in a "push ds", "mov ax,ss", "mov ds,ax" .... "pop ds" sequences
I mean.

Regards,
Rudy Wieser
Kerr-Mudd, John
2021-12-04 12:47:41 UTC
Permalink
On Sat, 4 Dec 2021 08:56:24 +0100
Post by R.Wieser
Hello all,
As an assembly programmer I never needed to write *big* programs, and
therefore always used the "tiny" memory model where CS = DS = SS.
Though at some point I realized that not having SS equal to DS
creates its own problems - when trying to access stack-based data
(strings).
A "lea dx,[Stack-based item]" will work, but, for example, using it
with "mov ah,09h", "int 21h" will ofcourse fail, as DX is not
pointing into DS.
Does anyone know how this is solved ? Other than (manually!)
wrapping all such calls in a "push ds", "mov ax,ss", "mov ds,ax" ....
"pop ds" sequences I mean.
No, sorry. Why would I put strings in the stack space?
--
Bah, and indeed Humbug.
R.Wieser
2021-12-04 14:57:16 UTC
Permalink
John,
Post by Kerr-Mudd, John
No, sorry. Why would I put strings in the stack space?
Lol ! Go troll someone else, will you.

Regards,
Rudy Wieser
R.Wieser
2021-12-04 17:41:26 UTC
Permalink
John,
Post by R.Wieser
Lol ! Go troll someone else, will you.
I'm sorry, it wasn't meant as a troll.
Phew ! Thank {deity} for that.
If ss<>ds then to load /dx/ with a saved string pointer
I'm sorry, are you /sure/ you aren't trolling ? Since when does "lea" load
something that was saved ?
I'd use the 'pop' instruction.
No you wouldn't.

I can ofcourse explain to you how "lea" works, but I always got the idea you
knew more about programming than I ever will. IOW, whats going on here ?
I presume you're after something like /mov dx,[ss:stack+offset]/
Definitily not.

Regards,
Rudy Wieser
Kerr-Mudd, John
2021-12-04 20:28:14 UTC
Permalink
On Sat, 4 Dec 2021 18:41:26 +0100
Post by R.Wieser
John,
Post by R.Wieser
Lol ! Go troll someone else, will you.
I'm sorry, it wasn't meant as a troll.
Phew ! Thank {deity} for that.
If ss<>ds then to load /dx/ with a saved string pointer
I'm sorry, are you /sure/ you aren't trolling ? Since when does
"lea" load something that was saved ?
I'd use the 'pop' instruction.
No you wouldn't.
I can ofcourse explain to you how "lea" works, but I always got the
idea you knew more about programming than I ever will. IOW, whats
going on here ?
You are very kind; no I think befuddlement is setting in here. OTOH I
rarely use /lea/.
Post by R.Wieser
I presume you're after something like /mov dx,[ss:stack+offset]/
Definitily not.
OK I'll bow out, I'm clearly not understanding your requirement.
--
Bah, and indeed Humbug.
R.Wieser
2021-12-05 07:56:51 UTC
Permalink
John,
OTOH I rarely use /lea/.
In a nutshell : "lea" returns a pointer to somewhere. "mov" copies to/from
somewhere.

Although "lea ax,address" and "mov ax,offset address" return the same thing,
"lea"s strength lies in that it can accept a relative part in the form of a
register.

Like "lea ax, [si+4]". Load ax with the address four bytes beyond what SI
is pointing at.
OK I'll bow out, I'm clearly not understanding your requirement.
I posted a small addendum. My mistake was that I assumed that "[stack
based]" would be understood as referring to a procedure-local variable or
buffer. IOW, "[stack based]" translates, for my example, to "[bp-xxxx]"

To be honest, I have not ever heard someone storing / retrieving data using
absolute adressing inside the SS segment. Instead always relative to either
BP or SP.

Code example :
- - - - - - - - - - - - - - - - - -

MyProc:
push bp
mov bp,sp
sub sp,0100h ;<- create a local buffer.

...

lea dx,[bp-0100h] ;<- Point to the buffer
mov ah,09h
int 21h

- - - - - - - - - - - - - - - - - -

Now imagine that you're using a memory model where DS <> SS. The problem
than is that in the above code DX is relative to SS, but int 21, ah=09h
expects it to be relative to DS.

What I was wondering is how this would be handled by/in professional
software (compilers).


Than again, I think I painted myself in a corner. :-|

Although I was thinking of some code which would allocate a stack segment
and initialise SS:SP to it (causing SS to become different from DS), when I
this morning looked at the different memory models Borlands Tasm offers I
could only find one which /doesn't/ set up SS equal to DS. and that one,
"TPASCAL", isn't even a standard one. I wonder why that is. :-)

Its like having 20/20 vision looking back. If only I had something like
that beforehand ...

Regards,
Rudy Wieser
R.Wieser
2021-12-05 12:11:44 UTC
Permalink
John,
I think that's it; the answer is "don't do that" (Sebastian!);
:-) Yep. Not because it cannot work, but because it just costs too much
work.

The thing is that I knew a way to deal with it (the wrapper code I mentioned
in my first post), but wanted to know if there would be a simpler approach,
making a SS <> DS setup feasable to use.
It still seems to me you were trying to use stack space to store strings.
:-) Not only trying, but have done so for quite a number of years now.

Are you trying to tell me that you have never used procedure-local variables
?

Regards,
Rudy Wieser
Kerr-Mudd, John
2021-12-05 12:21:57 UTC
Permalink
On Sun, 5 Dec 2021 13:11:44 +0100
Post by R.Wieser
John,
I think that's it; the answer is "don't do that" (Sebastian!);
:-) Yep. Not because it cannot work, but because it just costs too much
work.
The thing is that I knew a way to deal with it (the wrapper code I mentioned
in my first post), but wanted to know if there would be a simpler approach,
making a SS <> DS setup feasable to use.
It still seems to me you were trying to use stack space to store strings.
:-) Not only trying, but have done so for quite a number of years now.
Are you trying to tell me that you have never used procedure-local variables
?
Yes. I'm not the whizz programmer you thought I was!
--
Bah, and indeed Humbug.
R.Wieser
2021-12-05 13:59:00 UTC
Permalink
John,
Post by Kerr-Mudd, John
Post by R.Wieser
Are you trying to tell me that you have never used procedure-local
variables ?
Yes. I'm not the whizz programmer you thought I was!
I think you are /at least/ knowledgable, but with a different interrest in
programming than I have.

I've been programming Assembly for ... ages now, and have actually written
code as I posted in the grandparent post (three-and-half hours ago).

That was before I found out that Borlands Tasm allowed some syntactic sugar
to make usage of procedures and local variables (and stack-based, pushed
arguments!) /much/ easier.

And as you might have noticed, I still do not know everything about it
(might already have forgotten a thing or two too). And I hope it stays that
way - otherwise I have to find myself another hobby... :-)

Regards,
Rudy Wieser
JJ
2021-12-05 07:27:59 UTC
Permalink
Post by R.Wieser
Hello all,
As an assembly programmer I never needed to write *big* programs, and
therefore always used the "tiny" memory model where CS = DS = SS.
Though at some point I realized that not having SS equal to DS creates its
own problems - when trying to access stack-based data (strings).
A "lea dx,[Stack-based item]" will work, but, for example, using it with
"mov ah,09h", "int 21h" will ofcourse fail, as DX is not pointing into DS.
Does anyone know how this is solved ? Other than (manually!) wrapping all
such calls in a "push ds", "mov ax,ss", "mov ds,ax" .... "pop ds" sequences
I mean.
Regards,
Rudy Wieser
Well, you'll have to change the segment register to the correct segment when
using interrupts which only accept offset(s).

As for general use... Is segment override not applicable? e.g.

mov ax, ss:[bx]
mov dx, ds:[sp]
R.Wieser
2021-12-05 11:43:33 UTC
Permalink
JJ,
Post by JJ
As for general use... Is segment override not applicable? e.g.
For "general use" as in what I write myself ? Ofcourse.

The problem is that most system calls (like for example int 21h, AH=09h -
display a string) are hard-tied to using the DS segment when they access the
data that is pointed to. No override possible.

But, it looks I painted myself in a corner here.

Although you certainly /can/ create a program where DS and SS are set to
different segments, none of the memory models (tiny, small, etc.) you can
chose do that.

Probably for a good reason. The reason I bumped into. Its simply /way/ to
cumbersome to have to deal with a SS <> DS setup. :-)

Regards,
Rudy Wieser
Mateusz Viste
2021-12-06 08:30:32 UTC
Permalink
Lastly, perhaps you should be using segmented memory or you could
generate code by some means other than the assembler and more higher
level.
That's an excellent advice. There's a very good instructional video
about exactly that on youtube:


Mateusz
Herbert Kleebauer
2021-12-06 18:01:39 UTC
Permalink
:-) I like Assembly because it /doesn't/ hide all kinds of stuff from me.
But nearly no PC can execute 16 bit code directly these days. That's like
writing a novel in ancient Greek. So what sense does it make to still write
16 bit code? And 32 bit code also has the advantage, that you don't have to
mess around with segments.
R.Wieser
2021-12-06 20:16:50 UTC
Permalink
Herbert,
Post by Herbert Kleebauer
But nearly no PC can execute 16 bit code directly these days.
For starters, why including a restriction like "directly" ? How does that
matter ?

And for seconds, how does "nearly no PC" matter as long as mine does ?
Post by Herbert Kleebauer
So what sense does it make to still write 16 bit code?
What sense does it make for anyone to have a hobby ? Its a waste of time,
not bringing any money on the table.
Post by Herbert Kleebauer
And 32 bit code also has the advantage, that you don't have to
mess around with segments.
True. But why "mess around" with it /at all/ ? I'm sure there are lots of
well-payed professional programmers which can deliver much better quality in
a much shorter time.

But a question : why are you (still?) in this newsgroup, which is all about
an OS that has been obsolete for over 20 years and, listening to you, likely
won't even be able to run on any of your computers ...

Regards,
Rudy Wieser
Mateusz Viste
2021-12-07 08:31:13 UTC
Permalink
A program is written in order to be executed. To write a program
which can be executed on nearly none of the current computers
(without first installing additional software like DOSBox) doesn't
make much sense.
In this line of thoughts, writing Java doesn't make sense, because it
requires installing a JRE first. Writing JavaScript doesn't make sense
because it requires a browser, even PHP is stupid because it is not
stand-alone executable code...
Because normally a program is not only executed once. And if the
code still can be useful in a few years, it shouldn't be written
for a system which is obsolete already now.
16-bit code has bigger chances of being useful in a few years than a
"modern" code has, given that libraries change, operating systems
change, etc. DOS is one of the very few "APIs" that are stable, while
the rest of the IT ecosystem is a moving target. Nowadays it is easy to
run a 16-bit program in a browser. Try doing the same with any other
executable program.
Even if done as a hobby, the result should be something useful.
Ah, I only noticed the name now... A German. Should've guessed earlier.

Mateusz
R.Wieser
2021-12-08 09:16:46 UTC
Permalink
Herbert,
A program is written in order to be executed. To write a program
which can be executed on nearly none of the current computers
(without first installing additional software like DOSBox) doesn't
make much sense. And therefore it doesn't also make much sense for a
"starter" to start with 16 bit coding instead of the much easier
32 bit coding.
1) In relation to "without first installing additional software ". Most
programming languages need you to install software and configure it. Heaps
of it. To create 16-bit programs al you need are three executables (an
editor, the assembler and the linker) and *perhaps* (something like) DOSBox.

2) Its "much easier 32 bit coding" was, IIRC related to having all segments
ontop of each other. Funny thing that, as that is exactly what the "tiny"
memory model does for a 16-bit program. Yes, because it makes things
simple (my question was just about me thinking "outside the box").

As for using 32-bit (or 64-bit) coding instead of 16-bit ? I don't think
it matters much - though I think that the best way to learn actual
programming is /not/ to have too much support from libraries and the like.

When you have it becomes too easy to create monstrocities instead of the way
more apropriate (smaller, faster) processor commands. One example I still
remember is how someone using a higher language isolated a bit in a value :
(SomeValue & 2^SomeBit) <> 0. Yuck.

Bottom line : When learning to really program* I think that using a "dumb"
target is best. 16-bit DOS programming would be a good choice, both because
it offers only basic I/O support as well as most people nowerdays have
computers and thus can do it anywhere (school as well as at home).

*as opposed to slap-dashing some scripting / high-level language together.

Though I think that programming machine code on a micro controller, possibly
mounted on a model car or a robotic something, would be even better : most
people need, especially when starting, to see a direct result of what they
have put their energy into.

In other words : Its not about which language or platform you use, as long
as it teaches you what makes the bottom layer (the processor and I/O) tick,
as well as makes you aware that everything comes with a cost (execution time
and/or resource wise). Those are lessons that should be learned early on.

I hope that answers your (second, new) question.

Regards,
Rudy Wieser
Kerr-Mudd, John
2021-12-08 17:37:29 UTC
Permalink
On Wed, 8 Dec 2021 17:39:07 +0100
A program is written in order to be executed. To write a program
Why is 16-bit DOS programming a good choice in the year 2021?
The code below reads from stdin, converts any upper case to lower
loop: bsr.l getc ; get char from stdin
cmpq.l #-1,r0 ; EOF
bne.b _10 ; branch if not
andq.l #0,r0
bsr.l exit
_10: cmp.b #'A',r0
blo.b _20
cmp.b #'Z',r0
bhi.b _20
add.b #'a'-'A',r0
_20: bsr.l putc ; write char to stdout
br.b loop ; go on
Is this 16 bit DOS or 32 bit Windows programming or is it even
a LINUX program?
[]
Now the answer to the above question, it is neither a DOS, Windows or Linux code,
it is all three at the same time. Just set OS to 0,1 or 2 and the assembler
will generate an executable for the selected OS from the same source code.
Not even a single byte is generated by the assembler or a linker which is
not explicitly specified in the source code.
[]
Wonderful stuff, but it's not a standard language. I suspect you also need am assembler/compiler that isn't available (without installing) on any of the OS's.

So why dis anyone doing their own thing?

(16bit x86 asm DOS for me, if you noticed my attempt at a tetris update)
--
Bah, and indeed Humbug.
Herbert Kleebauer
2021-12-08 21:31:50 UTC
Permalink
Post by Kerr-Mudd, John
I suspect you also need am assembler/compiler that isn't available (without installing) on any of the OS's.
As I already said, it doesn't matter what you have to install
to create a program. But the created program should run without
the need of additional software/libraries which are not part of
a standard OS installation. The assembler I use is a single exe
file and doesn't need to be "installed". And the C source of the
assembler (also only a single C file) can be compiled with any
C compiler.
Post by Kerr-Mudd, John
So why dis anyone doing their own thing?
Because I learned more about assembly programming writing the
assembler than writing assembly programs using the assembler.
Post by Kerr-Mudd, John
(16bit x86 asm DOS for me, if you noticed my attempt at a tetris update)
I know, but I can't test the programs because they don't run in
64 bit Windows. Why not do it with 1024 byte 32 bit exe files instead
of 256 byte 16 bit com files?
Kerr-Mudd, John
2021-12-09 21:43:14 UTC
Permalink
On Wed, 8 Dec 2021 22:31:50 +0100
Post by Herbert Kleebauer
Post by Kerr-Mudd, John
I suspect you also need am assembler/compiler that isn't available (without installing) on any of the OS's.
As I already said, it doesn't matter what you have to install
to create a program. But the created program should run without
the need of additional software/libraries which are not part of
a standard OS installation. The assembler I use is a single exe
file and doesn't need to be "installed". And the C source of the
assembler (also only a single C file) can be compiled with any
C compiler.
Post by Kerr-Mudd, John
So why dis anyone doing their own thing?
Because I learned more about assembly programming writing the
assembler than writing assembly programs using the assembler.
That's worthy, but it isn't everyone's path.
Post by Herbert Kleebauer
Post by Kerr-Mudd, John
(16bit x86 asm DOS for me, if you noticed my attempt at a tetris update)
I know, but I can't test the programs because they don't run in
64 bit Windows. Why not do it with 1024 byte 32 bit exe files instead
of 256 byte 16 bit com files?
Sorry.

'cos I'm stuck in the past? I'm late to the demoscene!
1k - ridiculous overhead!
--
Bah, and indeed Humbug.
R.Wieser
2021-12-08 21:19:34 UTC
Permalink
Herbert,
It doesn't matter how much software you have to install to create a
program.
But once created, it should be possible to execute the program on a
standard Windows installation without first installing additional
software.
It doesn't work that way for Windows programs ...
It is always frustrating if you copy a program on an USB drive
to use it on a different PC and then all what you get is: This program
can't be executed because ......
... and reading from the above you know it.

But if that is your yardstick I guess thats the end of the story. Its
over, curtains close, you all can go home now.


It has to be said though : where I can run those 16-bit DOS programs on any
Win32 'puter and with the help of DOSBox also on a Win64 machine, your own
64-bit programs won't have it that easy. Apart from those dependancies they
will never run on a Win32 machine, and they might also barf on an earlier
version of Windows.
No, that's not the reason. I always used .com programs in DOS so I never
had to mess around with segment registers.
lol. You are disagreeing with while agreeing with me. The only difference
is that you look at the COM model, while I thought of the EXE one.
To use 32 bit addressing modes has nothing to do with libraries.
In that case, might I maybe have ment something else ? And if so, what ?
Maybe I was referring to something we already spoke of ? Do remember that
I also said "(or 64-bit)". Does that perhaps ring a bell ?

Playing dumb doesn't score you any points. It just shows what kind of
person you want to be.
This tells the compiler what he has to do, not how it has to be down.
Its hard isn't it ? Understanding the point of an example ? I've also
made no mention of a language, or if it would be compiled or not. Funny
how you seem know exactly what I've must have ment when it benefits you, but
have lots of trouble figuring it out when it doesn't ...
Why is 16-bit DOS programming a good choice in the year 2021?
Why are you ignoring that I also mentioned other possible platforms ?
Is this 16 bit DOS or 32 bit Windows programming or is it even
a LINUX program?
Your point ?
Post by R.Wieser
*as opposed to slap-dashing some scripting / high-level language together.
I would even go a step further and directly generate all bytes in
the executable file, this way you can see how the interface to the OS
works.
It looks like what you said has something to do with what you quoted there,
but heaven knows what.

And no, you would not be able to do that. Or you would need to drop the
"the OS" and be more specific than that.
If it doesn't matter which platform you use, then there is no advantage
in using an obsolete platform instead of a current platform.
And you have been refusing to listen to what I've been telling you, only
taking your own circumstances into account. On multiple points.
But it is a big disadvantage if the generated code can't be executed on a
current platform.
And water is still wet ?
Now the answer to the above question, it is neither a DOS, Windows or
Linux code,
it is all three at the same time.
:-) Yeah, if you massage it enough I'm sure that you will be able to get
something runnable outof it. Just have to either replace those "getc" and
"putc" pseudos with code outof some library, wrap some target-environment
specific initialisation and finalisation code around it and sure it will do
something.

You will have no clue what is actually executed though.

Heck, maybe that compiler you mentioned earlier wil just replace it with
something else altogether !
Just set OS to 0,1 or 2 and the assembler will generate an executable for
the selected OS from the same source code.
"You keep using that word, Assembler. I don't think it means what you think
it means."
-- The princes bride.

As for that listing below it ? Nope, its not. Its several programs -
which do not even need to be doing the same* - pushed together and using the
preprocessor to filter the selected parts out - and ofcourse some of the
above mentioned massaging of its pseudos.

*and if youre not /very/ carefull *will* do something different. Perhaps
even on purpose ...

But hey, if your thing is to "prove" that you can have some program that
will work on multiple platforms than you failed. Before you can run it
you first need to pull it thru that "Assembler" of yours, and than it looses
all of its multi-platform capabilities.


But lets draw the line here.

You've shown that for you only your own circumstances matter (even ignoring
that I mentioned other environments and languages), as well as rather
quickly deviating from the subject to something else you think you can
control.

So, goodbye. Have a good life.

Regards,
Rudy Wieser

P.s.
I did not actually try to look at that lengthy code. Your description made
clear that you tried to do the "assembly" equivalent of a "portable" C
program. And thats old hat.
Loading...