[HN Gopher] Hello World
___________________________________________________________________
Hello World
Author : fbrusch
Score : 173 points
Date : 2024-04-08 09:07 UTC (13 hours ago)
(HTM) web link (thecoder08.github.io)
(TXT) w3m dump (thecoder08.github.io)
| ben_w wrote:
| I've been thinking recently, we might have too many layers of
| abstraction in our systems.
|
| And I didn't even know about most of the ones in this post.
| mttpgn wrote:
| Just because the number of abstraction layers can be reduced
| doesn't mean they need to be. You might gain back some CPU
| cycles, some milliseconds of execution time. But the tradeoffs
| of maintainability, legibility, and developer quality-of-life
| may, in the long run, reintroduce abstraction layers of some
| other type back into the overall SDLC.
| ben_w wrote:
| > But the tradeoffs of maintainability, legibility, and
| developer quality-of-life
|
| Are in fact the things I think have become _worse_ from the
| abstractions.
|
| Well, the _recent_ abstractions. I like the ones that were
| widespread until about 2018 or so.
| richardwhiuk wrote:
| None of the abstractions above are new in the last 5 years.
| bitterblotter wrote:
| Im curious. Can you expand / give examples?
| nomel wrote:
| > And I didn't even know about most of the ones in this post.
|
| I think that's the answer to the question of "why do we have so
| many". It's a great thing you don't have to know about them. Go
| down a layer, and the people working there will think it's a
| great thing they don't have to worry about the abstraction
| below. Software development is, currently, a human task, so the
| human needs necessarily structure it.
|
| I can't comment on web development...
| freeone3000 wrote:
| Do some embedded work, even at the c-for-esp32 layer, and
| you'll start to see the benefits of having an OS.
| xandrius wrote:
| Yep, it seems common for people who haven't actually
| experienced something from the past to wish it was still like
| then, not understanding why people decided the trade was
| worth it.
|
| You might save some bytes but boy how annoying and
| complicated it can get.
| ctrw wrote:
| I can see the benefits of an os. I fail to see the benefits
| of a browser pretending to be another os on top of the os.
| MuffinFlavored wrote:
| I got bored the other day and tried to achieve something similar
| on MacOS with Rust: #![no_std]
| #![no_main] use core::panic::PanicInfo;
| #[panic_handler] fn panic_handler(_panic: &PanicInfo<'_>)
| -> ! { // TODO: write panic message to stderr
| write(2, "Panic occured\n".as_bytes()); // TODO: panic location +
| message unsafe { sc::syscall!(EXIT, 255 as u32) };
| loop {} } fn write(fd: usize, buf:
| &[u8]) { unsafe { sc::syscall!(WRITE,
| fd, buf.as_ptr(), buf.len()); } }
| #[no_mangle] pub extern "C" fn main() -> u32 {
| write(1, "Hello, world!\n".as_bytes()); return 0;
| }
|
| Then I inspected the ELF output in Ghidra. No matter what it was
| about ~16kb. I'm sure some code golf could be done to get it done
| (which has obviously been done + written about + documented
| before)
| 082349872349872 wrote:
| it's fun to golf, but how big are pages these days, anyway?
|
| (and if you're using a language with a stack, your executable
| probably ultimately loads as at least two pages: r/o and r/w)
| anyfoo wrote:
| 16kB on a Mac, so that was probably what they were running
| into. You effectively can't make a program whose code
| occupies less than 16kB.
| speed_spread wrote:
| Rust or not, 16kb is entirely satisfactory. I mean, it fits in
| a Commodore 64's memory!
| _the_inflator wrote:
| Compared to a Hello World program on C64 written in assembler
| probably not. ;)
|
| I need roughly 24 bytes. 16kb means 16.384 bytes. I can think
| of better usage of $4000 space in memory, FLI for example.
| delta_p_delta_x wrote:
| Sadly, like most 'hello world' deep dives, the author stops at
| the `write` syscall and glosses over the rest. Everything before
| the syscall essentially boils down to `printf` calling `puts`
| calling `write`--it's one function call after another forwarding
| the `char const*` through, with some book-keeping. In my opinion,
| not the most interesting.
|
| What comes _after_ the syscall is where everything gets very
| interesting and very _very_ complicated. Of course, it also
| becomes much harder to debug or reverse-engineer because things
| get _very_ close to the hardware.
|
| Here's a quick summary, roughly in order (I'm _still_ glossing
| over; each of these steps probably has an entire battalion of
| software and hardware engineers from tens of different companies
| working on it, but I daresay it 's still more detailed than other
| 'tours through 'hello world'): - The kernel
| performs some setup setup to pipe the `stdout` of the hello world
| process into some input (not necessarily `stdin`; could be a
| function call too) of the terminal emulator process. - The
| terminal emulator calls into some typeface rendering library and
| the GPU driver to set up a framebuffer for the new output.
| - The above-mentioned typeface rendering library also interfaces
| with the GPU driver to convert what was so far just a one-
| dimensional byte buffer into a full-fledged two-dimensional
| raster image: - the corresponding font outlines for each
| character byte is loaded from disk; - each outline is
| aligned into a viewport; - these outlines are resized,
| kerning and font metrics applied from the font files set by the
| terminal emulator; - the GPU rasterises and anti-aliases
| the viewport (there are entire papers and textbooks written on
| these two topics alone). Rasterisation of font outlines may be
| done directly in hardware without shaders because nearly all
| outlines are quadratic Bezier splines. - This is a new
| framebuffer for the terminal emulator's window, a 2D grid
| containing (usually) RGB bytes. - The windowing manager
| takes this framebuffer result and *composits* with the window
| frame (minimise/maximise/close buttons, window title, etc) and
| the rest of the desktop--all this is done usually on the GPU as
| well. - If the terminal emulator window in question has
| fancy transparency or 'frosted glass' effects, this composition
| applies those effects with shaders here. - The resultant
| framebuffer is now at the full resolution and colour depth of the
| monitor, which is then packetised into an HDMI or DisplayPort
| signal by the GPU's display-out hardware, depending on which is
| connected. - This is converted into an electrical signal by
| a DAC, and the result piped into the cable connecting the
| monitor/internal display, at the frequency specified by the
| monitor refresh rate. - This is muddied by adaptive sync,
| which has to signal the monitor for a refresh instead of blindly
| pumping signals down the wire - The monitor's input
| hardware has an ADC which re-converts the electrical signal from
| the cable into RGB bytes (or maybe not, and directly unwraps the
| HDMI/DP packets for processing into the pixel-addressing signal,
| I'm not a monitor hardware engineer). - The electrical
| signal representing the framebuffer is converted into signals for
| the pixel-addressing hardware, which differs depending on the
| exact display type--whether LCD, OLED, plasma, or even CRT. OLED
| might be the most complicated since each *subpixel* needs to be
| *individually* addressed--for a 3840 x 2400 WRGB OLED as seen on
| LG OLED TVs, this is 3840 x 2400 x 4 = 36 864 000 subpixels, i.e.
| nearly 37 million pixels. - The display hardware refreshes
| with the new signal (again, this refresh could be scan-line, like
| CRT, or whole-framebuffer, like LCDs, OLEDs, and plasmas), and
| you finally see the result.
|
| Note that all this happens _at most_ within the frame time of a
| monitor refresh, which is 16.67 ms for 60 Hz.
| rossant wrote:
| > The display hardware refreshes with the new signal (again,
| this refresh could be scan-line, like CRT, or whole-
| framebuffer, like LCDs, OLEDs, and plasmas), and you finally
| see the result.
|
| Nice explanation but you stopped at the human's visual system
| which is where everything gets very interesting and very _very_
| complicated. :)
|
| [1] https://en.wikipedia.org/wiki/Visual_system
| thedatamonger wrote:
| thank you for that. I startled the dog with that laugh :)
| wonnage wrote:
| Most of this stuff is irrelevant to the program itself, e.g you
| could've piped the output to /dev/null and none of this would
| happen.
| delta_p_delta_x wrote:
| Fair enough.
|
| However, the point of a hello world program is to introduce
| programming to beginners, and make a computer _do something
| one can visibly see_. I daresay this is made moot if you pipe
| it into /dev/null. I could then replace 'hello world' in the
| title with 'any program _x_ that logs to `stdout` ', and it
| wouldn't reach HN's front page.
|
| In the same vein is this idea of 'a trip of abstractions'--I
| don't know about you, but I always found most of them very
| unsatisfying as they _always_ stop at the system call,
| whether Linux or Windows. It really is afterwards where
| things get interesting, you can 't deny that.
| Syntaf wrote:
| This reminds me of one of my favorite CS assignments in college
| for a systems programming class: > Given a
| hello world C++ snippet, submit the smallest possible compiled
| binary
|
| I remember using tools like readelf and objdump to inspect the
| program and slowly rip away layers and compiler optimizations
| until I ended up with the smallest possible binary that still
| outputted "hello world". I googled around and of course found
| someone who did it likely much better than any of us students
| could have ever managed [1]
|
| [1]:
| https://www.muppetlabs.com/%7Ebreadbox/software/tiny/teensy....
| eddd-ddde wrote:
| Does it even matter that the snippet was c++? Couldn't you just
| get the smallest binary that prints hello world and argue that
| they are semantically equivalent?
|
| That should be like 10 x86 instructions tops, plus the string
| data.
| Syntaf wrote:
| Our curriculum was c++, so it was familiar territory for the
| students in terms of both the language and the compiler but
| yeah you can likely do this exercise with any compiled
| language.
| greenbandit wrote:
| I don't think the smallest binary was the goal but rather the
| smallest compiled binary. I assume they were restricted to a
| specific compiler as well.
| riazrizvi wrote:
| Seems like it would miss the point of the exercise, which was
| to learn what a C++ compiler puts into an executable. Though
| I do realize that if there was a magic wand to get a grade
| without doing the work, some of us would take it.
| Retr0id wrote:
| > All modern big and important programs that make a computer work
| are written this way [AoT-compiled to native code].
|
| This is the conventional wisdom, but it's increasingly not true.
| bkallus wrote:
| This almost entirely skips the role of the dynamic linker, which
| is arguably the true entry point of the program.
|
| If you are interested in that argument, see
| https://gist.github.com/kenballus/c7eff5db56aa8e4810d39021b2....
| norir wrote:
| > I'm sorry the ending maybe wasn't as satisfying as you hoped.
| I'm happy someone found this interesting. I'm not quite sure why
| I wrote this, but it's now after midnight so I should get some
| sleep.
|
| This was actually a perfect ending to this piece.
| cancerhacker wrote:
| I liked and appreciated this, two points I'd like to make: you
| should disable optimizations and whatever inlining caused printf
| to become puts (or, alternatively, write the hello world to use
| puts directly), second would be to break your compile step into
| the 4 real parts: preprocess, compile, assemble, link. Or add
| --save-temps to the cc line and describe the various files
| created. There's a lot less magic involved if you can see the
| pipeline.
| sohzm wrote:
| This reminded me of this video "Advanced Hello World in Zig -
| Loris Cro" https://youtu.be/iZFXAN8kpPo although not a equivalent
| comparison but still a intresting watch
| Bengalilol wrote:
| Just saying hi ! (and thanks for the read, got me back to the old
| days of ASM One and SEKA on Amiga, trying to clean up my memory
| dust pile)
| ctrw wrote:
| > So, modern software systems on today's hardware are so complex
| and intricate that it really makes no sense to try and fully
| understand one little thing that your computer did
|
| I was going to say that this looks like the type of dumb shit I
| said in undergrad while learning comouter basics.
|
| Then I saw the OP is 16. Continue being a dumb ass OP, no one was
| born knowing and being confidently wrong is the fastest way to
| grow.
| forrestthewoods wrote:
| Strangely harsh comment.
|
| I mean it's impossible for anyone to "fully understand". This
| post didn't even get to the hardware level!
|
| This ancient Google+ post is one of my all time-favorites:
| Dizzying but Invisible Depth.
| https://archive.is/100Wn#selection-693.0-693.28
|
| I do think it's critical for programmers to be curious and dig
| a few levels deep. This young programmer went about 7 levels
| deeper than almost anyone would. Kudos to him!
| stevefolta wrote:
| > Unlike python, however, you can't just call an interpreter to
| run this program.
|
| Sure you can: "tcc -run hello.c". Okay, technically that's an in-
| memory compiler rather than an interpreter.
|
| For extra geek points, have your program say "Hellorld" instead
| of "Hello world".
| qznc wrote:
| Another interesting fact: Write a Hello World program in C++, run
| the preprocessor on it (g++ -E), then count the lines of the
| output.
|
| I just tried and it shows me 33738 lines (744 lines for C btw).
|
| In a language like C++, even Hello World uses like half of all
| the language features.
| ColonelPhantom wrote:
| Arguably, most of that is probably dead code included from
| <iostream>. Most of it is likely never called for a simple
| Hello World.
|
| Similarly, in C, you can just give the definition of printf and
| omit the include of stdio.h, which also saves a ton of
| preprocessed lines.
| nsguy wrote:
| Don't include the standard headers and just put it the
| definition for the symbols you're using. With std::cout you
| might end up pulling your hair out to find everything but I
| can't imagine it'd be more than a few dozen lines... Not gonna
| try ;)
|
| With C you just need a definition for printf instead of
| including stdio. In the old days you'd get by without even
| defining it at all.
___________________________________________________________________
(page generated 2024-04-08 23:00 UTC)