Placeholders in assembly: How is it done?

Programming the 6502 microprocessor and its relatives in assembly and other languages.
User avatar
N2TheRed
Posts: 24
Joined: 11 May 2016
Location: Texas

Placeholders in assembly: How is it done?

Post by N2TheRed »

Placeholders in assembly: How is it done?

C#

Code: Select all

SomeMethod("Point A[{0},{1}], B[{2},{3}]", a.x, a.y, b.x, b.y)
If you wanted a function that takes a string with placeholders and some data and have it build a new string, would that be complicated?
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: Placeholders in assembly: How is it done?

Post by BigEd »

Anything's possible - but it does sound like it would take a little thought.

(A more old fashioned example of the same thing would be C's
printf("one: %d two: %d", a, b)
)

First problem: you need to pass a list of parameters, and the 6502 has no simple calling convention. Perhaps some kind of parameter block would work out: set X and Y to the two bytes of the address of the block, and in the block you'd have
- the address of the string
- the values to be inserted, as a list

Then your print routine just walks down the string, printing characters until it sees the formatting character, at which point it calls a subroutine to print the appropriate value.
User avatar
N2TheRed
Posts: 24
Joined: 11 May 2016
Location: Texas

Re: Placeholders in assembly: How is it done?

Post by N2TheRed »

BigEd wrote:
Anything's possible - but it does sound like it would take a little thought.

(A more old fashioned example of the same thing would be C's
printf("one: %d two: %d", a, b)
)

First problem: you need to pass a list of parameters, and the 6502 has no simple calling convention. Perhaps some kind of parameter block would work out: set X and Y to the two bytes of the address of the block, and in the block you'd have
- the address of the string
- the values to be inserted, as a list

Then your print routine just walks down the string, printing characters until it sees the formatting character, at which point it calls a subroutine to print the appropriate value.
That's almost like what I've come up with, except I didn't think of the second function. I was thinking that I'd have to convert integer values to their ASCII equivalent and that could be another function.

I haven't figured out how to deal with a variable amount of arguments/placeholders. As a side note, I'm trying in x86 before replicating it in 6502.

So are walking through this string, you have be looking for the placeholder strings. I was thinking that you could be looking for "{", and if you find one, you can check the next character to see if it's a valid index, and if it is, check the third character for the closing "}".

Is that how you would check for it?
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: Placeholders in assembly: How is it done?

Post by BigEd »

With the {n} syntax, it becomes a parsing problem. I think I'd call a handler as soon as I see the "{", whose job is to process the {n} and to return an error (somehow) if the syntax is wrong.

In the case of printf, if you want to print an actual % you use %%. Again, the handler can do that. Indeed, if you have %r and that happens to make no sense, the handler must complain, so there's no big difference with the {n} notation.
User avatar
N2TheRed
Posts: 24
Joined: 11 May 2016
Location: Texas

Re: Placeholders in assembly: How is it done?

Post by N2TheRed »

BigEd wrote:
With the {n} syntax, it becomes a parsing problem. I think I'd call a handler as soon as I see the "{", whose job is to process the {n} and to return an error (somehow) if the syntax is wrong.

In the case of printf, if you want to print an actual % you use %%. Again, the handler can do that. Indeed, if you have %r and that happens to make no sense, the handler must complain, so there's no big difference with the {n} notation.
What's a handler? You mean a function that handles check the syntax of a placeholder? That makes sense to me at least.
Last edited by N2TheRed on Thu Aug 03, 2017 11:01 pm, edited 1 time in total.
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: Placeholders in assembly: How is it done?

Post by BigEd »

Yes, something like that. I'm quite sure that any approach I might sketch out would be modified if I actually sat down to try to write the code.

By handler I just meant a subroutine. In fact, with your problem as stated, you need to turn the ASCII digits into a number, as well as checking that the braces match, so perhaps both can be done by the same routine.
User avatar
N2TheRed
Posts: 24
Joined: 11 May 2016
Location: Texas

Re: Placeholders in assembly: How is it done?

Post by N2TheRed »

BigEd wrote:
Yes, something like that. I'm quite sure that any approach I might sketch out would be modified if I actually sat down to try to write the code.

By handler I just meant a subroutine. In fact, with your problem as stated, you need to turn the ASCII digits into a number, as well as checking that the braces match, so perhaps both can be done by the same routine.
Thanks Ed, you have given me much to think about.

I'm going to see what I can do with it now.
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: Placeholders in assembly: How is it done?

Post by BigEd »

It will be interesting to see what you come up with.
dwight
Posts: 213
Joined: 08 Jun 2004

Re: Placeholders in assembly: How is it done?

Post by dwight »

I'm not of much help here but are you talking about
making an assembler to parse strings or just
writing some code with embedded subroutines?
It looks like you are writing an assembler.
Dwight
User avatar
GARTHWILSON
Forum Moderator
Posts: 8773
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: Placeholders in assembly: How is it done?

Post by GARTHWILSON »

N2TheRed wrote:
Placeholders in assembly: How is it done?

C#

Code: Select all

SomeMethod("Point A[{0},{1}], B[{2},{3}]", a.x, a.y, b.x, b.y)
If you wanted a function that takes a string with placeholders and some data and have it build a new string, would that be complicated?
I would inline the string, and use a macro to put the string and the command all on one line, like this:

Code: Select all

        SomeMethod   "'Point A[{0},{1}], B[{2},{3}]', a.x, a.y, b.x, b.y"
as discussed about a quarter of they way down the 6502 stacks treatise page on inlining data, and then have a parser routine like Ed suggested. Actually, you might be able to have the assembler itself do most of the parsing in the macro, rather than burdening the processor so much at run time. You might have to modify the quotes method slightly to work with most macro assemblers, but it could be done. A super long macro definition doesn't necessarily lay down much machine code, if a lot of the macro is tests and decisions made at assembly time, and conditional assembly whose conditions aren't met in the particular invocation.

Macros allow raising the level of the language a lot, and we can make it imitate, to some extent, the way something would be done in a HHL. In many cases, trying to do a direct translation doesn't work nearly as well as taking a different approach to the problem though, an approach that suits the particular processor better. A really smart macro might be able to do some of this—but there are limits.
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
whartung
Posts: 1004
Joined: 13 Dec 2003

Re: Placeholders in assembly: How is it done?

Post by whartung »

Here's a straight forward stab in basic C.

It "works", that is it compiles and builds and runs, and should convey the concepts. It doesn't use any library functions (save printf for the example).

Most routines that accept variable numbers of arguments represent those arguments as an array, that's what I do here.

I also assume no negative numbers. The % is the mod operator.

Simply, it copies each character to the destination. If it encounters the {, then it converts the following digits to a number, and indexes the argument list array to get the actual value, then it converts that to a string and copies it in to the destination buffer. I don't call routines, as there's different issues with sharing variables and what not, and it's not the point of the exercise.

Note that during the numeric conversion, it works backwards in memory.

It has some "error checking", where it simply silently fails (noted by the returns). Error checking is left as an exercise for the reader.

Code: Select all

#include <stdio.h>

#define ARG_SIZE 10

void print_pattern(char *pattern, int* arglist, int argcount) {
    char *p;
    char argbuf[ARG_SIZE];
    char *argp;
    char linebuf[128];
    char *lbp;
    int arg;


    p = pattern;
    lbp = linebuf;
    while(*p) {
        if (*p != '{') {
            *lbp++ = *p++;
        } else {
            p++; /* skip brace */

            /* copy the argument string to the arg buffer */
            argp = argbuf;
            while (*p >= '0' && *p <= '9') {
                *argp++ = *p++;
            }
            *argp++ = '\0';
            if (*p != '}') {
                /* syntax error */
                return;
            }
            p++; /* skip closing } */

            /* convert arg to int */
            arg = 0;
            argp = argbuf;
            while (*argp) {
                arg = arg * 10 + *argp++ - '0';
            }
            arg = arg - 1;
            if (arg >= argcount) {
                /* argument to large error */
                return;
            }
            arg = arglist[arg];

            /* convert value to string */
            argp = argbuf + ARG_SIZE - 1;
            *argp-- = '\0';
            if (arg == 0) {
                *argp = '0';
            } else {
                while (arg > 0) {
                    *argp-- = '0' + arg % 10;
                    arg /= 10;
                }
                argp++;
            }

            /* copy arg to line */
            while (*argp) {
                *lbp++ = *argp++;
            }
        }
        *lbp = '\0';
    }

    printf("%s\n", linebuf);
}

int main() {
    int args[3];
    args[0] = 11;
    args[1] = 0;
    args[2] = 23;

    print_pattern("this {1} that {2} and the other {3}", args, 3);
}
User avatar
N2TheRed
Posts: 24
Joined: 11 May 2016
Location: Texas

Re: Placeholders in assembly: How is it done?

Post by N2TheRed »

whartung wrote:
Here's a straight forward stab in basic C.

It "works", that is it compiles and builds and runs, and should convey the concepts. It doesn't use any library functions (save printf for the example).

Most routines that accept variable numbers of arguments represent those arguments as an array, that's what I do here.

I also assume no negative numbers. The % is the mod operator.

Simply, it copies each character to the destination. If it encounters the {, then it converts the following digits to a number, and indexes the argument list array to get the actual value, then it converts that to a string and copies it in to the destination buffer. I don't call routines, as there's different issues with sharing variables and what not, and it's not the point of the exercise.

Note that during the numeric conversion, it works backwards in memory.

It has some "error checking", where it simply silently fails (noted by the returns). Error checking is left as an exercise for the reader.
I'm going to refrain from looking at that until I fail or succeed at what I've come up with. However, I will be coming back to read your full post very soon.
User avatar
N2TheRed
Posts: 24
Joined: 11 May 2016
Location: Texas

Re: Placeholders in assembly: How is it done?

Post by N2TheRed »

dwight wrote:
I'm not of much help here but are you talking about
making an assembler to parse strings or just
writing some code with embedded subroutines?
It looks like you are writing an assembler.
Dwight
I'm just a noob, but I have big dreams!

I'm learning x86 and 6502, so writing an assembler is like a newborn running a marathon. Though, that would be an interesting sight!
User avatar
N2TheRed
Posts: 24
Joined: 11 May 2016
Location: Texas

Re: Placeholders in assembly: How is it done?

Post by N2TheRed »

BigEd wrote:
It will be interesting to see what you come up with.

It has turned out rather challenging.
Last edited by N2TheRed on Thu Aug 03, 2017 11:02 pm, edited 2 times in total.
whartung
Posts: 1004
Joined: 13 Dec 2003

Re: Placeholders in assembly: How is it done?

Post by whartung »

The only real problem with pushing the elements on the stack is that it's not really a viable option on the 6502, not on the system stack at least, and especially not string values. You can push them on A stack (Forth uses the top of Zero page and indexes with X), but that's using X as your stack pointer, vs the systems. You also still have the problem with stack scarcity for something large like a string.

You could still use the stack if you just push addresses (address of the pattern string, address of the list of arguments (which can be 2 byte integers, or pointers), and the address of the destination buffer).
Post Reply