Enlightened



  • @gąska said in Enlightened:

    I did.

    Before typing it the first time.

    I'm done with this.


  • Banned

    @blakeyrat look. In my social circles, FFI is an obvious acronym, like LOL, WTF, USA, P2P. I don't have to explain those four to anyone because everyone I interact with already knows what they mean, so I never even stop to think if I should explain them this time. I've also never had to explain FFI until today.



  • @gąska said in Enlightened:

    look. In my social circles, FFI is an obvious acronym

    You need to get out more. Jesus Christ.


  • Banned

    @blakeyrat obviously I meant people who I talk about FFI with. I don't explain what FFI means to people I don't talk about FFI with because why would I? I don't explain WTF to my parents either.



  • @gąska said in Enlightened:

    @jaloopa maybe if people actually asked for clarification instead of being jackasses and assuming the meaning they are absolutely sure I didn't mean, I would answer it.

    Where's the fun in that? Assuming a silly meaning is far more fun and communicates the same point.



  • @gąska said in Enlightened:

    If you type Chinese it looks like gibberish to me too, but it doesn't mean it IS gibberish.

    If I typed Chinese it would be.

    Filed under: It's all Greek to me.


  • Banned

    @hardwaregeek not all combinations of Chinese letters are Chinese text.



  • @pie_flavor Okay, so in Rust I can just declare a big chunk of memory and poke about in it without the compiler trying to interfere?



  • @blakeyrat said in Enlightened:

    You're missing my point entirely.

    I'm not sure I'm even seeing your point. C is a far better programming language than any of the other very high level languages that attempt to compete with it. Why would you want all the cruft that they bring along?


  • Impossible Mission - B

    @dkf said in Enlightened:

    paper's DOI is

    For some reason I really want to find a word beginning with D that can make this acronym read as the opposite of "ROI"... :P



  • @masonwheeler said in Enlightened:

    word beginning with D

    Debit 🤷♂


  • Impossible Mission - B

    @zecc said in Enlightened:

    While on the subject of FFI, today I learned the main antagonist in the first Final Fantasy game is named like one of those things you put on x-mas trees, apparently.

    See also: FFIX


  • Discourse touched me in a no-no place

    @zecc said in Enlightened:

    Psst, @dkf, did you mean Digital Object Identifier?

    Yes. Exactly that.


  • Discourse touched me in a no-no place

    @djls45 said in Enlightened:

    C++ could be a good choice.

    Except that it has a larger basic runtime than C, especially if you use either exceptions or RTTI. There's a few other bits and pieces too; I forget the full list.

    Floating point is another thing that you have to really watch out for, but that's true in C as well as C++ or any other language. The issue is that the libraries for float support — when it isn't baked into the hardware, of course — can run to several kilobytes, and it's very easy to slip up and write code that uses them. And soft float support tends to be slow and energy-expensive (well, one typically follows from the other). Several kB isn't much in a desktop app, but it's vast in an embedded one.


  • Discourse touched me in a no-no place

    @gordonjcp said in Enlightened:

    Okay, so in Rust I can just declare a big chunk of memory and poke about in it without the compiler trying to interfere?

    I believe you can, but only if you declare your whole program to be unsafe or unclean or something like that, like a medæval leper hobbling along, tolling a bell to ward off normal god-fearing folk.


  • Banned

    @gordonjcp said in Enlightened:

    @pie_flavor Okay, so in Rust I can just declare a big chunk of memory and poke about in it without the compiler trying to interfere?

    There are some caveats, like immutable pointers absolutely* having to be immutable, but generally yes. Rust has the unsafe blocks which basically tell the compiler to take the guards off and let you do whatever*. The thing is, a great majority of code doesn't have to be in unsafe blocks, and this part gets all the benefits of borrow checker. This is what differentiates Rust the most from every other language in embedded space - you get memory safety wherever you can, and absolute freedom where you need it.


  • Discourse touched me in a no-no place

    @gąska said in Enlightened:

    This is what differentiates Rust the most from every other language in embedded space - you get memory safety wherever you can, and absolute freedom where you need it.

    But programs in embedded space are typically either small enough that they can be completely verified, or sufficiently complex (because of asynchronicity due to hardware interrupts and the demands of real time processing) that Rust wouldn't help. The problems that Rust focuses on solving simply aren't the ones that are challenging in the embedded area.



  • @Gąska said in Enlightened:

    @blakeyrat said in Enlightened:

    For some reason, people all agree about that point when it comes to COBOL, but there's always a ton of programmers on boards like this one who think everybody should still learn C.

    Probably because so much of our current technology requires knowledge of C. Not writing C, but knowledge of C. It's mostly low level stuff, but still.

    I think this is not really C so much as the low-level stuff that C uses. A knowledge of the particular hardware's assembly language would be equivalently helpful.


  • Java Dev

    @djls45 I imagine they want to teach certain low-level concepts, like how memory works, and C is the best way they know how.


  • Banned

    @dkf you seem to grossly overestimate how much code needs to be unsafe. Let me show an example: finvsqrt - something that's all about breaking aliasing rules - in idiomatic Rust:

    use std::mem::transmute;
    
    fn finvsqrt(x: f32) -> f32 {
        let x_int: u32 = unsafe { transmute(x) };
        let wtf = 0x5f3759df - (x_int >> 1);
        let y: f32 = unsafe { transmute(wtf) };
        y * (1.5 - (0.5 * x * y * y))
    }
    

    The body is 114 non-whitespace characters, and only 42 characters are unsafe code - including the unsafe keyword, twice! That's the power of Rust - you can be EXTREMELY granular in your unsafe blocks, and everything else is guaranteed to be memory safe.

    If you want to see a more real-life example on a large scale project, look at Redox kernel. It's not the entire OS - it's just the kernel: the part that deals with hardware and other low-level bits the most. It's about 15KLOC of Rust, and only a few hundred lines of unsafe code (64 occurences of the word "unsafe"). The rest of this definitely very low level piece of software is guaranteed to be memory safe. If you bother to look at how unsafe blocks are used, you'll see that most of them wrap only a single function call or operation, just like the code above.


  • Banned

    @djls45 said in Enlightened:

    @Gąska said in Enlightened:

    @blakeyrat said in Enlightened:

    For some reason, people all agree about that point when it comes to COBOL, but there's always a ton of programmers on boards like this one who think everybody should still learn C.

    Probably because so much of our current technology requires knowledge of C. Not writing C, but knowledge of C. It's mostly low level stuff, but still.

    I think this is not really C so much as the low-level stuff that C uses.

    Also a fair bit of C itself. C types, C function prototypes, C ownership semantics, common C practices you need to remember when dealing with C libraries and wrappers for them (most wrappers are very bad at abstracting away C quirks).

    A knowledge of the particular hardware's assembly language would be equivalently helpful.

    Equally, yes. Equivalently, not at all.



  • @gąska said in Enlightened:

    @heterodox said in Enlightened:

    @blakeyrat said in Enlightened:

    @gąska said in Enlightened:

    From now on, I'm never going to assume anything is easily googlable even if it is for me and I've never heard the word/acronym used in any other way.

    Notice how when Blakeyrat says something, Blakeyrat is a stupid, moron, idiot, etc. But when other people say the exact same thing suddenly it's "oh dear I'm so sorry, I'll never assume again!"

    Just pointing it out.

    You're reading his response as sincere, which it was not.

    Though in all honesty. Google is so fucked up currently with its adaptive personalized searches that it's literally impossible to determine how visible a particular result is to others. I'm seriously stunned that Foreign Function Interface wasn't in top 3 results for everyone here. I have no trust at all that anyone can find anything there anymore. So I'm really going to expand all my acronyms.

    Or at least <abbr> tag them. :)



  • @Gąska said in Enlightened:

    @HardwareGeek not all combinations of Chinese letters are Chinese text.

    Yeah, sometimes it's Japanese.

    Filed under: Hiragana, Katakana, Kanji


  • Banned

    @djls45 is there some achievement for misinterpreting my posts everyone is trying to unlock? It's getting really annoying.



  • @Gąska said in Enlightened:

    @djls45 said in Enlightened:

    @Gąska said in Enlightened:

    @blakeyrat said in Enlightened:

    For some reason, people all agree about that point when it comes to COBOL, but there's always a ton of programmers on boards like this one who think everybody should still learn C.

    Probably because so much of our current technology requires knowledge of C. Not writing C, but knowledge of C. It's mostly low level stuff, but still.

    I think this is not really C so much as the low-level stuff that C uses.

    Also a fair bit of C itself. C types, C function prototypes, C ownership semantics, common C practices you need to remember when dealing with C libraries and wrappers for them (most wrappers are very bad at abstracting away C quirks).

    C types are assembler types, but with some different names. C function prototypes are for simplifying compilers so they don't have to backtrack through the code to find all function calls in order to connect the declarations/prototypes to the definitions and for header files in order to use library functions. C ownership semantics and common C practices are the same in assembly because C is basically a "badly abstracted" wrapper over assembly.

    What other sorts of quirks does C have that don't also apply to the assembler/hardware level operation of the code?



  • @Gąska Sorry. No, it's just funny that you misinterpreted his post, so I was just joining in with the red herrings.


  • Discourse touched me in a no-no place

    @gąska said in Enlightened:

    If you want to see a more real-life example on a large scale project, look at Redox kernel. It's not the entire OS - it's just the kernel

    It's largely missing most of the devices I'd expect in an embedded kernel. However, there's one device of some interest:

    How are the reads and writes of the memory-mapped hardware guaranteed to not be optimised out?


  • Banned

    @djls45 said in Enlightened:

    @Gąska said in Enlightened:

    @djls45 said in Enlightened:

    @Gąska said in Enlightened:

    @blakeyrat said in Enlightened:

    For some reason, people all agree about that point when it comes to COBOL, but there's always a ton of programmers on boards like this one who think everybody should still learn C.

    Probably because so much of our current technology requires knowledge of C. Not writing C, but knowledge of C. It's mostly low level stuff, but still.

    I think this is not really C so much as the low-level stuff that C uses.

    Also a fair bit of C itself. C types, C function prototypes, C ownership semantics, common C practices you need to remember when dealing with C libraries and wrappers for them (most wrappers are very bad at abstracting away C quirks).

    C types are assembler types, but with some different names.

    Assembler has signedness? Pointers? Structs? Arrays?

    C function prototypes are for simplifying compilers so they don't have to backtrack through the code to find all function calls in order to connect the declarations/prototypes to the definitions and for header files in order to use library functions.

    And the second part is why it's important to be able to read C prototypes when dealing with C libraries even if your own code isn't in C.

    C ownership semantics and common C practices are the same in assembly because C is basically a "badly abstracted" wrapper over assembly.

    Semantics, yes. Common practices... that's more difficult to say, since I never dealt with large codebases written in assembly. But I'd imagine it would work quite a bit differently.

    What other sorts of quirks does C have that don't also apply to the assembler/hardware level operation of the code?

    Again, I never worked with pure assembly, but I'd imagine it would involve less guessing of struct paddings and enum sizes. Of course you could replicate C code in assembly exactly, but I doubt the API of idiomatic assembly code would turn out identical to the API of idiomatic C code.


  • Java Dev

    @djls45 said in Enlightened:

    What other sorts of quirks does C have that don't also apply to the assembler/hardware level operation of the code?

    Undefined behaviour.



  • @gąska said in Enlightened:

    @djls45 said in Enlightened:

    @Gąska said in Enlightened:

    @djls45 said in Enlightened:

    @Gąska said in Enlightened:

    @blakeyrat said in Enlightened:

    For some reason, people all agree about that point when it comes to COBOL, but there's always a ton of programmers on boards like this one who think everybody should still learn C.

    Probably because so much of our current technology requires knowledge of C. Not writing C, but knowledge of C. It's mostly low level stuff, but still.

    I think this is not really C so much as the low-level stuff that C uses.

    Also a fair bit of C itself. C types, C function prototypes, C ownership semantics, common C practices you need to remember when dealing with C libraries and wrappers for them (most wrappers are very bad at abstracting away C quirks).

    C types are assembler types, but with some different names.

    Assembler has signedness? Pointers? Structs? Arrays?

    Yes. Yes. Yes. Yes. Understanding how C uses any of those on your given architecture means you also know how assembler uses them, and vice versa.

    C function prototypes are for simplifying compilers so they don't have to backtrack through the code to find all function calls in order to connect the declarations/prototypes to the definitions and for header files in order to use library functions.

    And the second part is why it's important to be able to read C prototypes when dealing with C libraries even if your own code isn't in C.

    But knowing how to use the prototypes isn't a C-specific skill. You need that same exact skill for reading the API for any library that isn't (or even is) in the same language as the one you're currently using.

    C ownership semantics and common C practices are the same in assembly because C is basically a "badly abstracted" wrapper over assembly.

    Semantics, yes. Common practices... that's more difficult to say, since I never dealt with large codebases written in assembly. But I'd imagine it would work quite a bit differently.

    Well, okay, true. Common practices are likely a bit different, but they're different in the same way that common practices in any pair of languages are different.

    What other sorts of quirks does C have that don't also apply to the assembler/hardware level operation of the code?

    Again, I never worked with pure assembly, but I'd imagine it would involve less guessing of struct paddings and enum sizes.

    Usually those're explicitly defined in the assembly code. And C has methods for explicitly defining them, too, although it's implementation-defined, so again, it depends on knowledge of the architecture rather than specific knowledge of C itself.

    Of course you could replicate C code in assembly exactly, but I doubt the API of idiomatic assembly code would turn out identical to the API of idiomatic C code.

    Well, sure. That's what the C compiler does. As for the idioms, the C compiler usually has flags to optimize for code size or speed, and will thereby output different asm/machine code. The API for the resulting library code would be the same, though.


  • Discourse touched me in a no-no place

    @gąska said in Enlightened:

    I never dealt with large codebases written in assembly.

    It usually seems to be written by people who feel that they need to take a stand on preventing the great vowel shortage, and to keep identifiers as short as possible. pkt_tx_kdc is pretty typical of the sort of thing you see (though that particular example comes from C, I happen to know that it was written by someone who was only ever happy with assembler. And Perl. 🤢) and it's going to be rather difficult to understand from its name (the first and second parts are probably not too hard, but the third bit is really obscure) without actually looking the code up.


  • Banned

    @djls45 said in Enlightened:

    @gąska said in Enlightened:

    @djls45 said in Enlightened:

    @Gąska said in Enlightened:

    @djls45 said in Enlightened:

    @Gąska said in Enlightened:

    @blakeyrat said in Enlightened:

    For some reason, people all agree about that point when it comes to COBOL, but there's always a ton of programmers on boards like this one who think everybody should still learn C.

    Probably because so much of our current technology requires knowledge of C. Not writing C, but knowledge of C. It's mostly low level stuff, but still.

    I think this is not really C so much as the low-level stuff that C uses.

    Also a fair bit of C itself. C types, C function prototypes, C ownership semantics, common C practices you need to remember when dealing with C libraries and wrappers for them (most wrappers are very bad at abstracting away C quirks).

    C types are assembler types, but with some different names.

    Assembler has signedness? Pointers? Structs? Arrays?

    Yes. Yes. Yes. Yes.

    You misunderstood me. I'm not asking if you can have things working like that in assembly. I'm asking if you can actually denote that these particular variables are these particular types - which restricts what operations can be performed on them and affects results of other operations.

    Understanding how C uses any of those on your given architecture means you also know how assembler uses them

    You know that C works on an unspecified abstract machine, and only the compiler turns it into code that runs on the particular architecture?

    and vice versa.

    Nope. C is higher level than assembly, and thus assembly can't represent it faithfully.

    C function prototypes are for simplifying compilers so they don't have to backtrack through the code to find all function calls in order to connect the declarations/prototypes to the definitions and for header files in order to use library functions.

    And the second part is why it's important to be able to read C prototypes when dealing with C libraries even if your own code isn't in C.

    But knowing how to use the prototypes isn't a C-specific skill.

    Knowing how to use C prototypes is absolutely C-specific skill.

    You need that same exact skill for reading the API for any library that isn't (or even is) in the same language as the one you're currently using.

    And every form of API requires a separate skill. The thing is, almost all cross-language APIs (outside virtual machines like JVM or CLR) are in form of C headers. And I mean it literally - it's not C-compatible, it's in C.

    C ownership semantics and common C practices are the same in assembly because C is basically a "badly abstracted" wrapper over assembly.

    Semantics, yes. Common practices... that's more difficult to say, since I never dealt with large codebases written in assembly. But I'd imagine it would work quite a bit differently.

    Well, okay, true. Common practices are likely a bit different, but they're different in the same way that common practices in any pair of languages are different.

    Exactly! That's why when connecting together two languages together, you need at least basic understanding of both. And in almost every case (except with VMs), the other language is C.

    What other sorts of quirks does C have that don't also apply to the assembler/hardware level operation of the code?

    Again, I never worked with pure assembly, but I'd imagine it would involve less guessing of struct paddings and enum sizes.

    Usually those're explicitly defined in the assembly code.

    Explicitly, or implicitly?

    And C has methods for explicitly defining them, too, although it's implementation-defined, so again, it depends on knowledge of the architecture rather than specific knowledge of C itself.

    I'd say it depends on both the knowledge of C and the architecture. Or in other words, the knowledge of the particular implementation of C.

    Of course you could replicate C code in assembly exactly, but I doubt the API of idiomatic assembly code would turn out identical to the API of idiomatic C code.

    Well, sure. That's what the C compiler does. As for the idioms, the C compiler usually has flags to optimize for code size or speed, and will thereby output different asm/machine code. The API for the resulting library code would be the same, though.

    By idiomatic, I mean standard practices when working in a particular language/environment. In C, you usually have the return value reserved for success status (with error data delegated to some global variable accessible with separate function), function output written to the provided pointer, and input passed either by copy or by pointer depending on size. In C++, you usually have the function output passed through return value and errors communicated via "bad" objects or exceptions, depending on decade you're in. In Python, exceptions are commonly used for flow control, which is a big no-no in C#. I find it hard to imagine that the idiomatic hand-written assembly would be 1:1 replica of what C programmers do.


  • Considered Harmful

    @gordonjcp said in Enlightened:

    @pie_flavor Okay, so in Rust I can just declare a big chunk of memory and poke about in it without the compiler trying to interfere?

    Yes.


  • Discourse touched me in a no-no place

    @gąska said in Enlightened:

    In C, you usually have the return value reserved for success status (with error data delegated to some global variable accessible with separate function)

    Depends on the API more than you'd think, and those “global” variables are actually quite often really thread-local variables. What tends to be uncommon though is returning structures from (non-inlined) functions, a legacy of some truly terrible implementations of that through the 1980s…

    In Python, exceptions are commonly used for flow control, which is a big no-no in C#.

    And Java is between the two, having less of a horror of using them than C#, but not being as keen on using exceptions for control flow as Python. (Whether that matters depends on exactly how the exceptions are defined and implemented; there's subtleties in there.)

    But overall I agree; idioms most definitely do vary between languages.


  • Considered Harmful

    @dkf said in Enlightened:

    @gąska said in Enlightened:

    If you want to see a more real-life example on a large scale project, look at Redox kernel. It's not the entire OS - it's just the kernel

    It's largely missing most of the devices I'd expect in an embedded kernel. However, there's one device of some interest:

    How are the reads and writes of the memory-mapped hardware guaranteed to not be optimised out?

    ... Why would they be optimized out? You're clearly writing to memory.


  • Banned

    @dkf said in Enlightened:

    @gąska said in Enlightened:

    In C, you usually have the return value reserved for success status (with error data delegated to some global variable accessible with separate function)

    Depends on the API more than you'd think

    This is prevalent idiom in almost every C library with complex failure modes. At least from the libraries I used. And I used a lot. Granted, I never coded for anything other than x86 (with some J2ME and Android in college).

    and those “global” variables are actually quite often really thread-local variables.

    Details.



  • @pie_flavor said in Enlightened:

    @dkf said in Enlightened:

    @gąska said in Enlightened:

    If you want to see a more real-life example on a large scale project, look at Redox kernel. It's not the entire OS - it's just the kernel

    It's largely missing most of the devices I'd expect in an embedded kernel. However, there's one device of some interest:

    How are the reads and writes of the memory-mapped hardware guaranteed to not be optimised out?

    ... Why would they be optimized out? You're clearly writing to memory.

    Because compilers see things like writing to the same address multiple times with no reads in between, and optimizing away all but the last one, because it's the only one with visible effect. That's absolutely not acceptable when writing or reading memory mapped hardware, because the writes, and even reads, can have side effects the compiler knows nothing of.


  • Considered Harmful

    @hardwaregeek Well, the same is true in C, isn't it? If you don't declare your pointers as volatile, you'll get that exact behavior. The equivalent in Rust is core::ptr::read_volatile/write_volatile .


  • Banned

    @dkf said in Enlightened:

    @gąska said in Enlightened:

    If you want to see a more real-life example on a large scale project, look at Redox kernel. It's not the entire OS - it's just the kernel

    It's largely missing most of the devices I'd expect in an embedded kernel.

    That's because it's desktop kernel. And AFAIK they went with microkernel architecture. Also, much of core stuff is separated into side libraries. But that's besides the point.

    However, there's one device of some interest:

    How are the reads and writes of the memory-mapped hardware guaranteed to not be optimised out?

    Much of the unsafe Rust code relies on similar compiler intrinsics. But I don't see it as a bad thing.



  • @pie_flavor said in Enlightened:

    The equivalent in Rust is core::ptr::read_volatile/write_volatile .

    Fair enough. I assumed from the fact that @dkf asked about it that there wasn't such an explicit declaration.

    BTW, is there a way to declare a pointer as both? Because some hardware is both.



  • @gąska a pet peeve of mine is seeing the original constant instead of the refined one:

    Lomont then searched for a constant optimal even after one and two Newton iterations and found 0x5F375A86, which is more accurate than the original at every iteration stage


  • Banned

    @hardwaregeek said in Enlightened:

    BTW, is there a way to declare a pointer as both? Because some hardware is both.

    They are functions. They work on anything.


  • Banned

    @lb_ said in Enlightened:

    @gąska a pet peeve of mine is seeing the original constant instead of the refined one:

    Lomont then searched for a constant optimal even after one and two Newton iterations and found 0x5F375A86, which is more accurate than the original at every iteration stage

    If I ever saw this function actually used in anything newer than 2005, I'd develop a pet peeve of unimaginable proportions. As long as it's never used, who cares about the constant there?


  • Considered Harmful

    @hardwaregeek said in Enlightened:

    @pie_flavor said in Enlightened:

    The equivalent in Rust is core::ptr::read_volatile/write_volatile .

    Fair enough. I assumed from the fact that @dkf asked about it that there wasn't such an explicit declaration.

    BTW, is there a way to declare a pointer as both? Because some hardware is both.

    Types are PascalCase. read_volatile and write_volatile are functions.


  • Impossible Mission - B

    @pie_flavor said in Enlightened:

    Gah! If they wanted to avoid C++'s mistakes, they could have started by leaving out the colon::cancer! 🤢


  • Considered Harmful

    @masonwheeler said in Enlightened:

    @pie_flavor said in Enlightened:

    Gah! If they wanted to avoid C++'s mistakes, they could have started by leaving out the colon::cancer! 🤢

    why? It's a very simple concept: . refers to member access, :: refers to static access.

    let mut string = String::new();
    string.push("Hello world!");
    

  • Impossible Mission - B

    @pie_flavor and::yet_it::looks::really::ugly!


  • Considered Harmful

    @masonwheeler to you.


  • Impossible Mission - B

    @pie_flavor Not just to me. I'll say this much: I'm not the one who invented the term colon::cancer. (Don't remember where I first heard it, but it's been around for a while...)


  • Banned

    @masonwheeler I like my turbofish.


Log in to reply