Wikipedia:Reference desk/Archives/Computing/2020 November 23

From Wikipedia, the free encyclopedia
Computing desk
< November 22 << Oct | November | Dec >> Current desk >
Welcome to the Wikipedia Computing Reference Desk Archives
The page you are currently viewing is a transcluded archive page. While you can leave answers for any questions shown below, please ask new questions on one of the current reference desk pages.


November 23[edit]

Exact same program is much bigger on Linux than on AmigaOS[edit]

As a fun experiment, I compiled this exact same source code:

#include <stdio.h>
int main(void)
{
  printf("Hello world!\n");
}

with both dcc on the Amiga (emulated on FS-UAE) and gcc on Linux. The result: as expected, it does the exact same thing on both systems.

The Amiga binary is 6064 bytes in size. The Linux binary is 19432 bytes, over 3.2 times as much. Yet I figure gcc has had much more development. All the program has to do is load the string "Hello world!\n" and call a system call to print it to stdout. Why, then, is the Linux binary so much bigger? JIP | Talk 00:57, 23 November 2020 (UTC)[reply]

Much of the size of such a trivial program is the printf library, which perhaps has additional features in Linux, or is optimised for speed at the cost of size. There might also be more debug code and symbols for use by a debugger included by the Linux compiler. Try using 'strip' on the executable (or compiling with 'gcc -s') to see if that reduces the size.-gadfium 02:00, 23 November 2020 (UTC)[reply]
Gadfium, he could also try -O2 which would optimize and possibly reduce (or increase) code size. Elizium23 (talk) 02:07, 23 November 2020 (UTC)[reply]
JIP, did you link static or dynamic? Elizium23 (talk) 02:04, 23 November 2020 (UTC)[reply]
This discussion mentions that a dynamically-linked "Hello world!" on Arch is "only 124KiB" which is remarkably larger than yours. Elizium23 (talk) 02:06, 23 November 2020 (UTC)[reply]
All the program has to do is load the string "Hello world!\n" and call a system call to print it to stdout. printf is not a system call. It is a function in the stdio library and on many systems, calling it will link your program with at least part of the stdio library. On the other hand, you could try calling write(1, "Hello world!\n", 13); instead of printf, and since write() IS a system call, that may behave more like you are expecting. But in general, compiler/linkers are not optimized for trivial one-line programs, and some relatively small amount of per-program overhead is not considered problematic. CodeTalker (talk) 03:52, 23 November 2020 (UTC)[reply]
Right, the executable links against the libc used for compiling—glibc on the typical distro—for printf. --47.152.93.24 (talk) 05:12, 23 November 2020 (UTC)[reply]
The GNU/Linux executable is an ELF file. It includes ELF headers and symbols for dynamic linking. You can view these with binutils. If you want to see how tiny you can get, you can whip up something in assembly that calls Linux syscalls directly, and have the assembler make a legacy a.out executable, at the expense of portability. A Web search will pull up guides for this. --47.152.93.24 (talk) 05:08, 23 November 2020 (UTC)[reply]

I now tried compiling the same "hello world" program with native function calls on both Amiga and Linux, bypassing stdio. The difference in size grew even bigger. Here is the Amiga version:

#include <proto/dos.h>
int main(void)
{
  Printf("Hello World!\n");
  return RETURN_OK;
}

Here is the Linux version:

#include <unistd.h>
int main(void)
{
  write(1, "Hello world!\n", 13);
}

The native Amiga binary is 3004 bytes, the native Linux binary is 19440 bytes. So the Linux binary is now almost six and a half times as big. JIP | Talk 22:31, 23 November 2020 (UTC)[reply]

Running strip on the Linux binaries made them smaller, but not by much. Both of them (the one using stdio and the one using native Linux functions) are now the exact same size, 14976 bytes. So in comparison, for the versions using stdio, the Linux binary is now about two and a half times as big as the Amiga binary, whereas for the versions using native functions, the Linux binary is about five times as big as the Amiga binary. JIP | Talk 22:35, 23 November 2020 (UTC)[reply]

Comparing the sizes of loadable object modules tells you very little. If you want to know how bit the actual code compiled to (which means how much memory space it occupies when loaded into memory) you need to look at the size of the .text segment. For your example (https://godbolt.org/z/6qdhfx), the actual code compiles to about 60 bytes, with the full .text section being 389 (that's 0x185) bytes - the overhead being the CRTL startup. Unfortunately compiler explorer doesn't have an Amiga (or even a mc68k) compiler. -- Finlay McWalter··–·Talk 22:53, 23 November 2020 (UTC)[reply]
It appears, then, that the vast bulk of the Linux binary is taken up by the CRTL startup. But what is the CRTL startup in the first place? JIP | Talk 00:55, 24 November 2020 (UTC)[reply]
The CRTL (C runtime library) startup code is 329 bytes. Not very vast. -- Finlay McWalter··–·Talk 01:14, 24 November 2020 (UTC)[reply]
Really, stop worrying about this "The Linux binary is 19432 bytes" stuff. The ELF binary is the box the program comes in; the system loader (ld-linux.so) reads that and writes only the relevant segments into actual program memory. Your program is 389 bytes (plus some string storage and a few other trivial things); it's nothing like 19k. Think of it like buying an SD card from Amazon - the card is tiny, the box it comes in is vastly larger. But the size of the box is very unimportant. -- Finlay McWalter··–·Talk 01:20, 24 November 2020 (UTC)[reply]
As I originally wrote, this is a fun experiment. It does not affect my actual development in any way. The code I write as a hobby in AmigaOS or Linux C take up hundreds of lines, the code I write in C# at my job take up tens of thousands (but I'm obviously not the only coder there). I was just wondering about the internals of Amiga and Linux binary files. JIP | Talk 01:30, 24 November 2020 (UTC)[reply]
If you really want to learn more (and there's sooo much more) you can have the linker emit a map file (-Xlinker -Map=output.map), compare that to what the final executable reports from objdump or elfdump, and with what the memory layout after loading really is (cat /proc/PID/maps). I'm sure I understand 0.1% of any of that. -- Finlay McWalter··–·Talk 11:12, 24 November 2020 (UTC)[reply]
"Native function calls" here doesn't really mean what you think it does. You're still calling other C functions, which means your binary includes all the symbols in the header files you include. The write() you used is the POSIX write(2) function in your libc. It's not a syscall; rather, it's a C wrapper around the system write syscall. Here's a very educational page that takes you through writing a 45-byte ELF binary. Granted, the 45-byte binary runs roughshod over the ELF standard, but the Linux kernel still merrily executes it, or at least it did at time of writing. It also doesn't print anything, but just returns an exit code. You could build on this to write a teeny Hello, world! in assembler if you choose. Or just Web search for examples. Hint: you don't want to use any library functions. You want to call syscalls directly in assembler. This will show you how low-level syscalls are, and how much stuff compilers and libraries do for you behind the scenes. This kind of thing is called code golf, and it's a good learning experience. --47.152.93.24 (talk) 02:46, 24 November 2020 (UTC)[reply]

–== Why is Emergency Call Mode only a thing on CDMA cell phones? ==

When dialing 911 on CDMA cell phones, the phone enters “emergency call mode” or “emergency mode.” This does not happen on GSM phones, and I don’t think it happens on 4G LTE phones either. Just out of curiosity, why does this only happen on CDMA phones? PCHS-NJROTC (Messages)Have a blessed day. 16:16, 23 November 2020 (UTC)[reply]

It should happen if your dial 112_(emergency_telephone_number) on a GSM phone, the phone will dial the local emergency number if it isn't 112. Phones can also be factory programmed for other numbers, if these are set, it will dial 112 instead of the entered number. — Preceding unsigned comment added by 81.187.116.230 (talk) 17:52, 23 November 2020 (UTC)[reply]
See this page. Notice it says “With CDMA, iPhone enters emergency call back mode”. Why only on CDMA? Phones going all the way back to the Motorola TalkAbout had “emergency mode” on Alltel while AT&T and T-Mobile US phones don’t appear to do that. PCHS-NJROTC (Messages)Have a blessed day. 20:36, 23 November 2020 (UTC)[reply]
This would suggest that some CDMA networks are unable to implement busy line interrupt, which would allow the 911 operator to call the person back, even if they're phoning someone else ("mum, you'll never guess what happened"). But I'll confess I can't find reliable documentation of that (because non-consumer-facing phone features are a madhouse of standards committees and nonsense). -- Finlay McWalter··–·Talk 21:45, 23 November 2020 (UTC)[reply]
Suffice to say, there are a lot of "implementation-specific details" in the modern consumer telephone handset; and its interconnection with a global marketplace of private-sector telecommunication networks. It is no easy task to ensure correct behavior and compliance across a global set of local and national government regulators and emergency-service-providers.
I'm not sure our OP's assessment is correct or complete - only to say that "emergency behavior" of most modern telephones will differ for many reasons: handset model, locale (both general and specific details of the exact location of the call-origination), subscription or service-provisioning status, device status, and so on, and so on, and so on... the typical end-user needs to know how to use the emergency service mode, but they probably can't (and don't need to) understand how it really works. Law, sausage, and mobile-radio-telephony, as they say.
Here's Rappaport's Wireless Communications: Principles & Practice, (1996). After glossing over those 736 pages of theory and practice, your enthusiastic reader regrettably finds herself only a few decades behind the current state of theory and practice - but at least with a head-start!
Nimur (talk) 00:45, 24 November 2020 (UTC)[reply]
What is referred to as "CDMA" in North America is CDMA2000, the 3G CDMA-based standard. It uses circuit-switching for voice and SMS, which means you have the same problem that you have on POTS; the voice circuit is either in-use or not, and if it's already in-use when someone tries to call you, the call can't be connected. UMTS is the other 3G standard used in North America. That's "GSM", which is fully packet-switched, as is 4G LTE. With packet switching, there's no concept of a "busy" circuit. I presume there's some magic in those standards as well to give emergency calls priority. --47.152.93.24 (talk) 02:34, 24 November 2020 (UTC)[reply]
Sort of correcting myself: UMTS does apparently have circuit-switched components, but for the life of me I can't figure out whether these are used in "routine" 3G operation, or whether they're primarily used for 2G GSM interoperability. If anyone wants to dig into things like Network Switching Subsystem and General Packet Radio Service and figure it out, be my guest. --47.152.93.24 (talk) 03:43, 29 November 2020 (UTC)[reply]