I did a “lecture”/“workshop” about this at work today. 16-bit DOS, real mode. 💾 Pretty cool and the audience (devs and sysadmins) seemed quite interested. 🥳
- People used the Intel docs to figure out the instruction encodings.
- Then they wrote a little DOS program that exits with a return code and they used uhex in DOSBox to do that. Yes, we wrote a COM file manually, no Assembler involved. (Many of them had never used DOS before.)
- DEBUG from FreeDOS was used to single-step through the program, showing what it does.
- This gets tedious rather quickly, so we switched to SVED from SvarDOS for writing the rest of the program in Assembly language. nasm worked great for us.
- At the end, we switched to BIOS calls instead of DOS syscalls to demonstrate that the same binary COM file works on another OS. Also a good opportunity to talk about bootloaders a little bit.
- (I think they even understood the basics of segmentation in the end.)
The 8086 / 16-bit real-mode DOS is a great platform to explain a lot of the fundamentals without having to deal with OS semantics or executable file formats.
Now that was a lot of fun. 🥳 It’s very rare that we do something like this, sadly. I love doing this kind of low-level stuff.
On my blog: Short Fiction — Transgender Athlete Bans https://john.colagioia.net/blog/2025/06/22/title-ix-hope.html #fiction #freeculture #lgbtpridemonth #politics
On my blog: Free Culture Book Club — First Woman — Dream to Reality https://john.colagioia.net/blog/2025/06/21/first-woman-1.html #freeculture #bookclub
Okay, here’s a thing I like about Rust: Returning things as Option and error handling. (Or the more complex Result, but it’s easier to explain with Option.)
fn mydiv(num: f64, denom: f64) -> Option<f64> {
// (Let’s ignore precision issues for a second.)
if denom == 0.0 {
return None;
} else {
return Some(num / denom);
}
}
fn main() {
// Explicit, verbose version:
let num: f64 = 123.0;
let denom: f64 = 456.0;
let wrapped_res = mydiv(num, denom);
if wrapped_res.is_some() {
println!("Unwrapped result: {}", wrapped_res.unwrap());
}
// Shorter version using "if let":
if let Some(res) = mydiv(123.0, 456.0) {
println!("Here’s a result: {}", res);
}
if let Some(res) = mydiv(123.0, 0.0) {
println!("Huh, we divided by zero? This never happens. {}", res);
}
}
You can’t divide by zero, so the function returns an “error” in that case. (Option isn’t really used for errors, IIUC, but the basic idea is the same for Result.)
Option is an enum. It can have the value Some or None. In the case of Some, you can attach additional data to the enum. In this case, we are attaching a floating point value.
The caller then has to decide: Is the value None or Some? Did the function succeed or not? If it is Some, the caller can do .unwrap() on this enum to get the inner value (the floating point value). If you do .unwrap() on a None value, the program will panic and die.
The if let version using destructuring is much shorter and, once you got used to it, actually quite nice.
Now the trick is that you must somehow handle these two cases. You must either call something like .unwrap() or do destructuring or something, otherwise you can’t access the attached value at all. As I understand it, it is impossible to just completely ignore error cases. And the compiler enforces it.
(In case of Result, the compiler would warn you if you ignore the return value entirely. So something like doing write() and then ignoring the return value would be caught as well.)
On my blog: Toots 🦣 from 06/16 to 06/20 https://john.colagioia.net/blog/2025/06/20/week.html #linkdump #socialmedia #quotes #week
On my blog: Real Life in Star Trek, Gambit part 1 https://john.colagioia.net/blog/2025/06/19/gambit-part-1.html #scifi #startrek #closereading
@kat@yarn.girlonthemoon.xyz uh, i use yandex mail which uses HTML by default
https://threadreaderapp.com/thread/1935344122103308748.html Interesting article on how ChatGPT is rotting your brain 🤣
@kat@yarn.girlonthemoon.xyz Ooh, I’ve got to bookmark that page. 😃
@aelaraji@aelaraji.com I wish I had the luxury of not reading that junk. 😅 But instead, I have a Mutt hotkey that pipes an HTML mail through elinks … Bah.
@prologic@twtxt.net I’m trying to call some libc functions (because the Rust stdlib does not have an equivalent for getpeername(), for example, so I don’t have a choice), so I have to do some FFI stuff and deal with raw pointers and all that, which is very gnarly in Rust – because you’re not supposed to do this. Things like that are trivial in C or even Assembler, but I have not yet understood what Rust does under the hood. How and when does it allocate or free memory … is the pointer that I get even still valid by the time I do the libc call? Stuff like that.
I hope that I eventually learn this over time … but I get slapped in the face at every step. It’s very frustrating and I’m always this 🤏 close to giving up (only to try again a year later).
Oh, yeah, yeah, I guess I could “just” use some 3rd party library for this. socket2 gets mentioned a lot in this context. But I don’t want to. I literally need one getpeername() call during the lifetime of my program, I don’t even do the socket(), bind(), listen(), accept() dance, I already have a fully functional file descriptor. Using a library for that is total overkill and I’d rather do it myself. (And look at the version number: 0.5.10. The library is 6 years old but they’re still saying: “Nah, we’re not 1.0 yet, we reserve the right to make breaking changes with every new release.” So many Rust libs are still unstable …)
… and I could go on and on and on … 🤣
https://blog.garambrogne.net/kloset.html #kloset disséqué une histoire de #plakar un outil de sauvegarde qui utilise déduplication compression chiffrage et signature
On my blog: Developer Diary, Day of the African Child https://john.colagioia.net/blog/2025/06/16/african-child.html #programming #project #devjournal
orb v0.1.0 - tiny metasearch | https://nilfm.cc/orb.html
On my blog: Go Nowhere Fast https://john.colagioia.net/blog/2025/06/15/go-nowhere-fast.html #harm #rant #politics #harm
fn sub(foo: &String) {
println!("We got this string: [{}]", foo);
}
fn main() {
// "Hello", 0x00, 0x00, "!"
let buf: [u8; 8] = [0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x00, 0x00, 0x21];
// Create a string from the byte array above, interpret as UTF-8, ignore decoding errors.
let lossy_unicode = String::from_utf8_lossy(&buf).to_string();
sub(&lossy_unicode);
}
Create a string from a byte array, but the result isn’t a string, it’s a cow 🐮, so you need another to_string() to convert your “string” into a string.
- https://doc.rust-lang.org/std/string/struct.String.html#method.from_utf8_lossy
- https://doc.rust-lang.org/std/borrow/enum.Cow.html
I still have a lot to learn.
(into_owned() instead of to_string() also works and makes more sense to me, it’s just that the compiler suggested to_string() first, which led to this funny example.)
So I was using this function in Rust:
https://doc.rust-lang.org/std/path/struct.Path.html#method.display
Note the little 1.0.0 in the top right corner, which means that this function has been “stable since Rust version 1.0.0”. We’re at 1.87 now, so we’re good.
Then I compiled my program on OpenBSD with Rust 1.86, i.e. just one version behind, but well ahead of 1.0.0.
The compiler said that I was using an unstable library feature.
Turns out, that function internally uses this:
https://doc.rust-lang.org/std/ffi/struct.OsStr.html#method.display
And that is only available since Rust 1.87.
How was I supposed to know this? 🤨
On my blog: Free Culture Book Club — Tag Team https://john.colagioia.net/blog/2025/06/14/tag-team.html #freeculture #bookclub
On my blog: Toots 🦣 from 06/09 to 06/13 https://john.colagioia.net/blog/2025/06/13/week.html #linkdump #socialmedia #quotes #week
On my blog: Real Life in Star Trek, Interface https://john.colagioia.net/blog/2025/06/12/interface.html #scifi #startrek #closereading
Here’s all the new features coming to your Apple device
Apple’s latest developer conference covered a huge number of features coming soon to iPhone, iPad and other devices. ⌘ Read more
New oil and gas fields incompatible with Paris climate goals
Opening any new North Sea oil and gas fields is incompatible with achieving the Paris Climate Agreement goals of limiting warming to 1.5°C or holding warming to “well below 2°C” relative to preindustrial levels, finds a new report published by UCL academics. ⌘ Read more
Apple unveils software visual redesign, but no revamped Siri
This yea’rs software updates will bring a new visual design that Apple is calling Liquid Glass. ⌘ Read more
Radeon Software For Linux Dropping AMD’s Proprietary OpenGL/Vulkan Drivers
Direct link to upstream release notes.
On my blog: Generative AI Wish List https://john.colagioia.net/blog/2025/06/08/ai-wish-list.html #artificialintelligence #harm #rant
Having some fun with SIRDS this morning.

What you should see: 
And the tutorial I used for my C program: https://www.ime.usp.br/~otuyama/stereogram/basic/index.html
Current toy project: an image feed generated by mk(1). Still some edges to clean up but it’s nice: http://a.9srv.net/img/_readme.html
On my blog: Free Culture Book Club — The Pink and Black Album https://john.colagioia.net/blog/2025/06/07/pink-black.html #freeculture #bookclub
On my blog: Toots 🦣 from 06/02 to 06/06 https://john.colagioia.net/blog/2025/06/06/week.html #linkdump #socialmedia #quotes #week
SuSE Linux 6.4 and Arachne on DOS also work (with Windows 2000 as a call target):
This ring wants to help you live longer. I gave it a try
A new gadget has emerged recently that promises 24/7 tracking in the most subtle way possible. ⌘ Read more
お知らせ:JPCERT/CC Eyes「TSUBAMEレポート Overflow(2025年1~3月)」 ⌘ Read more
お知らせ:JPCERT/CC インターネット定点観測レポート[2025年1月1日~2025年3月31日] ⌘ Read more
On my blog: Real Life in Star Trek, Liaisons https://john.colagioia.net/blog/2025/06/05/liaisons.html #scifi #startrek #closereading
お知らせ:Weekly Report公開遅延のおわび ⌘ Read more