FindFirstIn

Discussion in 'C Programming' started by jacob navia, May 22, 2014.

  1. jacob navia

    BartC Guest

    I mean, instead of knowing it will always be D0, for example, you need to be
    aware that it might be D0 or A0.

    (I would just have made it D0, but then if you did immediately want to use
    the result as an address, it needs to be copied to an A register. In
    general, an extra nuisance to deal with.)
     
    BartC, May 25, 2014
    #61
    1. Advertisements

  2. No, it was an uncommon convention, precisely because it would have
    broken so many C programs that didn't declare functions like malloc().
    (68k-based workstations became common in the mid 80s, and needed to
    support code originally written for PDP-11s and VAXes.) One or two
    compilers used a0 by default but had pragmas to change that for
    compatibility.

    -- Richard
     
    Richard Tobin, May 25, 2014
    #62
    1. Advertisements

  3. jacob navia

    BartC Guest

    In the same way that a pointer object in a C program isn't being constantly
    dereferenced; mostly it us just being pushed around, copied, passed to a
    function, compared etc. For those purposes, it is just data like everything
    else.

    And would use D registers. A registers are needed for dereferencing. Then
    you have expressions such:

    int** p;

    (*p+i*n+j)

    This dereferences p once, but then you add i*n+j (which internally also need
    scaling) to it. But is the result *p in a D register or an A register? It
    depends on whether the result is going to be assigned elsewhere:

    int* q;
    q=(*p+i*n+j);

    or whether it is going to be dereferenced now:

    int a;
    a=*(*p+i*n+j);

    or whether it's going to be returned from this function which has return
    type int*:

    return (*p+i*n+j);

    In short, it becomes a complete nightmare trying to determine which category
    of register is best to use in any situation.
    It is not a question of interpreting: you *know* a return value type is a
    pointer, but you don't know if the caller is going to *dereference* the
    pointer, which requires the value in an A register.
    It just means more work by compiler writers (I'm doing some code generation
    at the minute. Just the *one* set of registers is difficult enough!)
    If you write p=malloc(n) and a=somefn(b), the data-paths in both cases are
    exactly the same. You don't need the result of malloc() to be passed in A0
    rather than D0. (It would actually be rare to use the result of malloc
    immediately (this would need an intervening cast):

    *(malloc())=0;)
     
    BartC, May 25, 2014
    #63
  4. Ah, I know, yes? To be honest, I didn't. I just compiled it and expected
    it to work. It didn't. Then I looked at the code and saw the reason
    immediately.
    Apparently you have no clue what "portability" means. That's like
    specifying a variant for Itanium assembler and claiming that it's
    "portable" to a Z80.
    You don't say. How clever of you.

    Regards,
    Johannes


    --
    Ah, der neueste und bis heute genialste Streich unsere großen
    Kosmologen: Die Geheim-Vorhersage.
    - Karl Kaos über Rüdiger Thomas in dsa <hidbv3$om2$>
     
    Johannes Bauer, May 25, 2014
    #64
  5. You apparently don't even grasp the difference between a compiler and an
    architecture. The version you posted is not "gcc compatible", that
    doesn't even make any sense.

    Maybe you should stick to writing C code.

    Cheers,
    Johannes

    --
    Ah, der neueste und bis heute genialste Streich unsere großen
    Kosmologen: Die Geheim-Vorhersage.
    - Karl Kaos über Rüdiger Thomas in dsa <hidbv3$om2$>
     
    Johannes Bauer, May 25, 2014
    #65
  6. jacob navia

    jacob navia Guest

    Le 25/05/2014 13:42, Johannes Bauer a écrit :
    Look Mr, I am witing for the intel architecture obviously. But I did not
    specify that in every message I send because I suppose that people here
    do not need to be reminded of everything at each message.


    The version you posted is not "gcc compatible", that
    Well, it will run in Linux and Mac OS X and in all systems that follow
    the gcc ABI calling convention for x86
    Maybe you should turn on your brain before posting.
     
    jacob navia, May 25, 2014
    #66
  7. jacob navia

    jacob navia Guest

    That's an interesting idea Stephan, but I do not think that will make
    any big difference because testing if a character belongs to the set
    needs quite a few instructions: if((( r & t )== t )&&(( r & !b )== 0 )).

    It saves some comparisons of course but addes also some overhead.

    Cost/Benefits aalysis must include also the setup operations
    (determining the set of bits)

    But it could be that I am wrong of course, it would be a matter of
    measuring woth a suitabe text+segt
     
    jacob navia, May 25, 2014
    #67
  8. jacob navia

    Ike Naar Guest

    The test can be simplified to

    if ((r | t) == (r & b))
     
    Ike Naar, May 25, 2014
    #68
  9. jacob navia

    David Brown Guest

    x86/amd64 assembly is the closest you can get - but on modern x86
    processors, it's pretty far away from the real workings of the chip. On
    x86 devices, the hideous x86 instructions are translated into RISC
    micro-ops before execution. And while there is plenty of information
    about these from Intel and AMD, the details vary wildly between
    processor generations and manufacturers, and you can't program at that
    level.
    I'd only bother with the floating point if you are particularly
    interested in it. Working at the assembly level gives you an insight
    into things like rounding modes, conversions between precisions, etc.
    If you want to know about that stuff, then a little assembly is
    educational - but most people can use floating point happily while
    ignoring these details.

    On the other hand, multi-length integer arithmetic in assembly can be
    interesting to learn how these things work within the processor.
    Pre-emptive multi-threaded kernels are almost always written in 95%+ C
    code. There is always a little bit that has to be in assembly, but it
    is usually kept to a minimum (compiler extensions are often used to
    reduce the assembly parts - such extensions are, of course, slightly
    outside of normal C).

    I don't know what is meant by "precisely tracing" garbage collection,
    but I know that garbage collection is not something that an OS should
    get involved in, except in terms of recovering resources owned by a
    process when it dies.
    You must have a very strange definition of "orthogonal" to think that
    the m68k ISA is less orthogonal than x86. The x86 has about a dozen or
    so registers, and all are highly specialised with many operations only
    working on particular register combinations. Later versions of the x86
    instruction set included instruction varieties and prefixes to allow
    more flexibility, but it is as far from "orthogonal" as any large cpu
    architecture has ever been.

    The m68k, on the other hand, has two sets of main registers - data
    registers D0..D7, and address registers A0..A7. To a very large extent,
    instructions can choose freely amongst these. Addressing modes are
    restricted mainly to using the Ax registers, and many arithmetic and
    logic instructions use only the Dx registers - but each can use any of
    the Ax or Dx registers (with a very few exceptions). It was far and
    away the most orthogonal instruction set until RISC became popular.
     
    David Brown, May 25, 2014
    #69
  10. jacob navia

    David Brown Guest

    p is a pointer, as is *p. So you load *p into an A register. i and j
    are data, so you load them into D registers (unless they are
    compile-time constants of small enough size to use directly). The
    arithmetic is done in D registers, or as part of a more complex
    addressing mode, and you use (Ax + Dy) or (Ax + Dy + j) addressing modes
    to access the final data.

    In fact, the 68020 onwards had an addressing mode that would often do
    all this in one instruction. If **p is in Ax, i is in Dy (or Ay), and n
    is 1, 2, 4 or 8, and j is a compile-time constant, then it can access
    *(*(p + offset) + i*n + j) in a single addressing mode.

    No problems, no mixups about address and data.
    By no stretch of the imagination is this "a complete nightmare". I
    think if you need to apply serious thought as to whether something
    should go in an A register or a D register, you have probably screwed up
    the logic of your program (if it ever had any).
    If they are not going to dereference the pointer, it can still happily
    go in an A register! You can do plenty of operations on the A registers
    other than dereferencing - you can load them and store them, and do some
    basic arithmetic such as adding offsets. The operations that you
    /cannot/ do directly on an A register are things like multiplication and
    logic instructions, which don't make sense on addresses.
    What cpu are you targeting? The x86 doesn't have a "set of registers" -
    it has a bunch of individualists. Even the amd64 instruction set is a
    mess, though it is far cleaner than the original x86. Other compiler
    writers considered the m68k ISA to be a dream come true when they
    started working with it.
     
    David Brown, May 25, 2014
    #70
  11. I don't understand why you keep bothering with these morons.
    I don't understand why you keep bothering with these morons.
    I don't understand why you keep bothering with these morons.

    Really, Jacob, you are better than all this tripe.

    As is freely admitted here, none of these jerks has ever written a compiler
    (with, I think, 1 [maybe 2] exception(s) - and, when you get right down to it,
    those 1 [or 2] are not jerks like Mr. Bauer is). You have. This puts you
    so far out of their league that them trying to jerk you around is like an
    ant tugging on an elephant.

    In fact, most of them are PROUD of the fact that they've never written a
    compiler, because it fits in with their general "We know nothing about
    internals or mechanics. Everything we need to know about anything is
    written in the Bible (Oops, I mean 'C standard')" mentality. You can see
    this in a lot of Kiki's (and others) writing; pride in ignorance is a
    pretty common Republican/Christian trait.

    As many other Bible-thumpers are fond of saying, "The Bible is inerrant; it
    says so right here in the Bible."

    BTW, most of what I've just written applies as well to Malcolm. He actually
    discusses concepts and ideas here (Where does he get off doing that???) and
    all he gets in return is BS nit-picking.

    That's the world of CLC...

    --
    "I heard somebody say, 'Where's Nelson Mandela?' Well,
    Mandela's dead. Because Saddam killed all the Mandelas."

    George W. Bush, on the former South African president who
    is still very much alive, Sept. 20, 2007
     
    Kenny McCormack, May 25, 2014
    #71
  12. Them's fightin' words. Data General's Nova? (But maybe I'm forgetting
    all the odd bits).

    <snip>
     
    Ben Bacarisse, May 25, 2014
    #72
  13. jacob navia

    BartC Guest

    Look at the eight core arithmetic operations of the 8086 (ADD, ADC, SUB,
    SBB, AND, OR, XOR, CMP).

    These work with any of the 8 registers (disregarding that the top 4 byte
    registers don't map to the top 4 word registers), using combinations such as
    reg/mem or mem/reg.

    Now look at the same eight on the 68K: largely they will only work on the
    data registers while two of them only seem to work in one direction: EOR and
    CMP. (For CMP it probably doesn't matter, yet the 8086 did allow a
    comparison either way around).

    But then you also have sorts of special, ad-hoc instructions to make some of
    these work with address registers, or between data and address registers,
    and many of the above can't be used at all.

    It *is* a nuisance having two incompatible banks of registers; if they'd had
    an extra couple of bits to be able to specify two lots of 16 registers
    in an instruction field, instead of two lots of 8, would they still have
    done it that way? No!

    (But it's some 30 years since I first looked at the 68K and arrived at my
    conclusion. And since I couldn't persuade my boss to make use of this
    processor (probably too expensive), it didn't really matter.)
     
    BartC, May 25, 2014
    #73
  14. jacob navia

    Ike Naar Guest

    The negation '!' should probably be a bitwise negation '~'.
     
    Ike Naar, May 25, 2014
    #74
  15. jacob navia

    BartC Guest

    No, you load p into an A register, in other to fetch the value of *p. But is
    that result itself also put into an A register, or a D register?

    Assuming you are going to use this pointer value you are constructing, the
    *p value is loaded into an A register too. And assuming the hardware can't
    directly take care of i*n+j, this arithmetic now needs to be performed. But
    while you can add into an A register, you can't multiply using them, so that
    part is done in D registers.

    But if you are only interested in constructing a pointer value to be used
    later (ie. treating it as data), then *p can be loaded into a D register.

    Wouldn't it be have been much simpler though if there wasn't the distinction
    between A and D types of register?
    Suppose you have an 64-bit 'double' value, and need to compare it with
    another. If you're using x64, would it be loaded into R0 (rax), or into the
    FPU?

    If that requires a bit of consideration, does that mean the 'program' is
    screwed up?
    Logic instructions can make sense, if for example your data is 4-byte
    aligned and you want to make use of those two lower bits of a pointer which
    are otherwise
    zero.

    But my point of view is for generating automatic code (for a compiler for
    example). Having to constantly think about A or D or either is a
    distraction.
    The x86-32 model I'm targeting has 6 general 32-bit registers, R0 to R5
    (there is also Rframe and Rstack), as I call them. Plus the FPU (I'm not
    bothering with XMMn and all that for the time being.)

    There are a few instructions which use dedicate registers (DIV and SHL for
    example), but otherwise they are reasonably orthogonal.
     
    BartC, May 25, 2014
    #75
  16. jacob navia

    Stefan Ram Guest

    Yes, thank you!, that was my intention: to mask all bits that
    are not set in any of the characters from the source set and
    see that those are all 0.
     
    Stefan Ram, May 25, 2014
    #76
  17. jacob navia

    Kaz Kylheku Guest

    Machine code does not reveal how a processor works. I coded in 6502
    assembly for years and gained no clue about how instructions are fetched,
    decoded and executed: how the CPU is internally organized.

    Not until I studied digital design, and designed a very simple processor at the
    gate level.
    I should have said "in comparison to doing it in C", but I thought it
    was clear.

    Coding "algorithmic stuff" in assembly language not having to do with detailed
    control over the state of the machine, or taking advantage of precise
    instruction-level exceptions and the like, does not really teach you anything,
    other than perseverence and patience.

    In various machine languages, there are various "bit twiddy things" that
    are not directly available in C, like byte swapping loads in a single
    instruction, or bitfield extracting/injecting instructions and the like, but
    that's not particularly educational. You can write these in C as functions.
     
    Kaz Kylheku, May 25, 2014
    #77
  18. jacob navia

    Stefan Ram Guest

    Sometimes, when the set of characters to be searched for is
    the same for multiple searches, it might be possible that
    the setup operations have to be done only once for several
    texts to be searched later.

    In the case of the test

    (( r & t )== t )&&(( r & ~b )== 0 )

    , sometimes, only the LHS of the && is actually evaluated.
     
    Stefan Ram, May 25, 2014
    #78
  19. jacob navia

    Ian Collins Guest

    As one who moved from PDP11 to 68K, I'd say the PDP11 held that crown.
    When I moved to 68K, I thought of it as a natural extension to PDP11.
    My first encounter with the 8086 architecture was one of those WTF
    moments :)
     
    Ian Collins, May 25, 2014
    #79
  20. [...]

    Perhaps. But the cost would have been either to have half as many
    registers, or to dedicate 4 rather than 3 bits for each register
    reference in an instruction.

    Flexibility is not always free.

    And this isn't really about C, is it?
     
    Keith Thompson, May 25, 2014
    #80
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.
Similar Threads
There are no similar threads yet.
Loading...