6 ms·
I really like C as well, it's the smallest language I know. From bare metal you can bootstrap a basic C runtime in like 10 lines of ASM (zero the BSS, setup the
by simias 6y ago
I really like C as well, it's the smallest language I know. From bare metal you can bootstrap a basic C runtime in like 10 lines of ASM (zero the BSS, setup the stack, jump main). I really love Rust these days, but there's no denying that it's a much more complex language.
Segfaults are not something C is aware of, it's usually the consequence of triggering an undefined behaviour. But UB being... undefined, all sort of things can and do happen, for instance a buffer overflow can segfault, but it can also overwrite some other variable, or the return address of the function, or do nothing at all.
That's really the problem with C. If UB meant segfault, then it wouldn't be so bad because at least you'd immediately know that something went wrong. Instead it's very easy to have small issues go unnoticed for a long time, until your application finally crashes in a seemingly unrelated location or, worse, some clever guy or gal manages to exploit the flaw for fun and profits.
- bogomipz 6y ago>"From bare metal you can bootstrap a basic C runtime in like 10 lines of ASM (zero the BSS, setup the stack, jump main)." Might you or someone else have a resource on learning how to do this?
- kahlonel 6y agoI don’t self-promote usually, but I asked some people on Reddit[1] if they would like an educational stream on embedded systems, and a lot of people said yes. I’m doing one on Sunday most probably. Feel free to join in because that’s one of the things I will be talking about. [1] - https://old.reddit.com/r/embedded/comments/ilgyun/would_you_be_interested_in_an_educational_stream/ https://old.reddit.com/r/embedded/comments/ilgyun/would_you_...
- djeiasbsbo 6y agoHey kahlonel! Just wanted to tell you that I watched your stream and it was really good, I learned a lot. I don't have a twitch account so I couldn't use the chat when you were waiting for someone to show up. So I just wanted to tell you here that everything was great from sound quality to the content you provided! :)
- gumby 6y agoJust read the source to crt0 which contains the entry point called by the kernel (a symbol called _start or __start) and which finishes up by calling main(). It should be in the source of your c runtime library (just look at any of the open source ones) with different versions for each architecture and with slight variations for the os.
- simias 6y agoWell it's pretty platform dependent, but basically all you need is to do is make sure that you're in a consistent state with regards to IRQs and other low level configuration, then clear the BSS, then setup the stack pointer, then you can jump to C. Here's a random bootloader init code I wrote a while ago for an ARM SoC (probably heavily inspired by uboot): https://gist.github.com/simias/c31ae83127c77519621edfb76d5994d5 https://gist.github.com/simias/c31ae83127c77519621edfb76d599... The vectors are a table that must be placed in a specific location in memory and are used by the CPU to know what code to execute when certain events occur. Here I only fill the "reset" entry to call my init code when the CPU boots up. Everything in my "reset" function up to line 93 is low level ARM things: making sure the CPU is in a well defined mode, disable IRQs, initialize the cache (optional, but good for perfs) etc... All that stuff is usually described in the docs for the CPU/SoC/Controller. Note that this SoC is fairly complex, if you used a smaller microcontroller it's usually much more straightforward. Then after that you have a loop to clear the BSS (the _bss_start and _bss_end are generated automatically by the linker script, normally when you load an executable the operating system clears those regions for you, but obviously here we're on our own). Then I set the stack pointer register SP to _stack_base which is also defined in the linker script to point at some memory location (typically the top of the RAM). And then we're good to go, we can do the rest in C with only small bits of ASM here and there for special instructions. I think the best way to learn that stuff is by doing, get some ARM chip with an u-boot loader and dig into it, break it, see what code does etc... Obviously you need a good knowledge of C to begin with, and at least a basic understanding of assembly, so start with that if you're not there yet.
- odc 6y agoEasy: https://en.wikipedia.org/wiki/Crt0 https://en.wikipedia.org/wiki/Crt0
- fao_ 6y agoOS dev[1] has a full page on how to do this and more, as well as links to sample code, etc. Unfortunately it's down right now, so here's a webarchive link from 1st Sept[1.5] A resource you'll find immensely useful is ctyme's interrupt jump table[2][3], which is easier than reading Ralf Brown's ASCII formatted notes[4]. Of course there are easier ways to do it, but printf() debugging (or the assembly equivalent) is still by far the easiest to set up. If you want to go write code for modern systems -- UEFI code, you can find a tutorial here[5] (I didn't write this, however, so I don't know how good it is, I can't find the resources I used :c), and the EFI spec here[6] [1]: https://wiki.osdev.org/Main_Page https://wiki.osdev.org/Main_Page [1.5]: https://web.archive.org/web/20200901014356/https://wiki.osdev.org/Main_Page https://web.archive.org/web/20200901014356/https://wiki.osde... [2]: http://www.ctyme.com/intr/int.htm http://www.ctyme.com/intr/int.htm [3]: http://www.ctyme.com/rbrown.htm http://www.ctyme.com/rbrown.htm [4]: http://www.cs.cmu.edu/~ralf/files.html http://www.cs.cmu.edu/~ralf/files.html [5]: https://github.com/safayetahmedatge/efitutorial https://github.com/safayetahmedatge/efitutorial [6]: https://uefi.org/sites/default/files/resources/UEFI%20Spec%202_6.pdf https://uefi.org/sites/default/files/resources/UEFI%20Spec%2...
- lebuffon 6y agoUmmm.. Is that the language? Sounds like the preamble in the code generator. The equivalent Forth VM is just a handful of instructions also but one would not say that's the language.
- deleted 6y ago[deleted]
- saagarjha 6y agoThe C startup routines are not part of the language, but you can think of them as the bridge between your actual machine and a state that matches the C abstract machine. (For a virtual machine this might be two memsets-one to the registers and one to memory.)
- brandmeyer 6y ago> (zero the BSS, setup the stack, jump main) Also: run global initializers. Getting kinda fuzzy on the boundaries, but I'd also add in the process to copy the initial contents of the .data segment from read-only to read-write storage.
- deleted 6y ago[deleted]
- tomjakubowski 6y agoIn standard C only constant values can initialize globals, so the value can be baked into the binary.
- brandmeyer 6y ago"baked into the binary" covers a lot of ground. You've got to get the initial contents of .data initialized somehow. In a typical microcontroller that's a copy from flash to ram.
- simias 6y agoThat's true, I forgot about that because the last controller I used had a bootrom that copied the booloader straight to RAM, so .data was already read-write and there was nothing to do.