HackerURLs

一次又一次被重新发现的经典。

同一个链接,相隔一年以上,一次又一次被人重新发现、再次冲上 Hacker News 首页。能经受住这种时间检验的,大多是值得一读再读的文章。每篇附中文标题,讨论最热的那些再加上中文导读和高赞评论翻译。

从名人堂开始
  • 4,700+篇经过时间检验的经典

Hall of fame

名人堂

在经典库里看全部精选

上首页次数最多、而且有中文导读的 30 篇。时间轴上每个黑点是一次上首页,空心点是一次没冲上去的投稿。

  1. 正在载入经典…

Archive

经典库

按第一次上首页的年份分布,点柱子筛选。

排序

    About

    这些经典是怎么挑出来的

    1. 01

      合并同一个链接

      读取 Hacker News 自 2006 年以来的全部链接投稿,把 http/https、www、跟踪参数等写法不同的同一篇文章合并成一条。

    2. 02

      只留经得起时间的

      同一链接至少两次拿到 50 分以上(约等于上首页),而且两次相隔一年以上;再由 AI 剔除状态页、产品首页和新闻事件。

    3. 03

      写导读、译评论

      上首页次数最多的 2,000 篇配上中文导读、"为什么经久不衰",并精选翻译 HN 高赞评论。导读由 AI 生成,可能有误。

    编程与软件工程jroweboy.github.io

    main 通常是一个函数——但何时不是?

    Main is usually a function – when is it not?

    3次上首页
    6年跨度
    698累计得分
    188条评论

    2015 — 2021,它一次次回到首页

    黑点是上首页(≥ 50 分)的那次投稿,空心点是没冲上去的投稿,点越大分数越高。

    导读

    这篇博客通过反汇编和链接脚本,探索 C 程序中 main 到底是什么:作者展示了如何把 main 定义成数组甚至字符串,让链接器直接把数据当作机器码执行,最终实现一个没有真正函数入口的"Hello World"程序。文章层层深入,揭示了编译、链接和程序入口点背后的机制。

    为什么经久不衰:它把"main 是函数"这一人人默认的常识拆开,展示了 C/汇编/链接器底层的运作方式,这种对系统底层的好奇心和技术趣味跨越多年仍吸引读者。

    关键词 C语言汇编链接器程序入口点

    HN 评论精选

    认为文章没有正面回答标题问题,但欣赏这种把程序结构彻底拆解的探索精神

    不确定标题的问题最后是否被回答了,结尾他只是说"一直以来我们都忽略了 main 不是函数的警告 :)"。我记得 20 年前第一次写 C/C++ 内嵌汇编时的震撼——我完全掌控了这台机器!其实一旦开始拆这些线头,整个结构都会散架:源代码可以长成任何你想要的样子,这很酷。

    DanielBMarkham查看英文原文

    Not sure the title's question was answered. At the end he just said "And all this time we’ve been ignoring the warning message about main not being a function :)" I remember 20 years or ago writing my first C/C++ function where I popped out to inline ASM. I was like, wow! I'm in complete control of this box! (It was mostly copied code. My ASM-foo is weak) I really liked the fact that I could either code in these really abstract types -- or be concerned with what the stack looks like on entering a function. So I _think_ I know the answer to the question. Instead of ignoring the error, I was thinking that you could just mangle the link file and make the entry point whatever you want, right? I could have a program that consisted of "void x", then continue along the lines of the articles with the number list. Heck, once you start pulling the threads apart like this, the entire structure falls apart. Your source code could look like anything you want it to look like. And that's cool.

    指出这种手法早在 1984 年 IOCCC 获奖作品中就出现过

    第一届国际混淆 C 代码大赛(1984 年)的一个获奖作品就用过这种技术:short main[] = {...},直接把机器码以 short 数组的形式放在 main 里。

    _kst_查看英文原文

    One of the winners of the 1st International Obfuscated C Code Contest (1984) used this technique. https://www.ioccc.org/1984/mullender/mullender.c https://www.ioccc.org/1984/mullender/hint.text short main[] = { 277, 04735, -4129, 25, 0, 477, 1019, 0xbef, 0, 12800, -113, 21119, 0x52d7, -1006, -7151, 0, 0x4bc, 020004, 14880, 10541, 2056, 04010, 4548, 3044, -6716, 0x9, 4407, 6, 5568, 1, -30460, 0, 0x9, 5570, 512, -30419, 0x7e82, 0760, 6, 0, 4, 02400, 15, 0, 4, 1280, 4, 0, 4, 0, 0, 0, 0x8, 0, 4, 0, ',', 0, 12, 0, 4, 0, '#', 0, 020, 0, 4, 0, 30, 0, 026, 0, 0x6176, 120, 25712, 'p', 072163, 'r', 29303, 29801, 'e' };

    分享 call/pop 技巧获取内嵌数据地址,并提到这是老式恶意软件的常用手段

    获取数据地址并不难,在 32 位寻址下只需把数据内嵌在汇编里:call continue 后跟字符串,continue 处 pop eax——因为 call 相当于 push eip 再跳转,弹出后 eax 就是字符串地址。老式恶意软件常用这招实现地址无关代码并迷惑反汇编器。

    ipython查看英文原文

    It's not hard to get the address of data in 32-bit addressing. You just interleave the data inside your assembly, something like the following (pseudo code I haven't done this in a while): ... call continue .db "Hello World!\n\0" continue: pop eax ... Since 'call' just turns into a 'push eip; jmp target' (simplified, sorry), the address of the string is now pushed onto the stack. Popping off the top, now eax contains the address of the string "Hello World!\n\0". Since in 32-bit ABI most parameters are passed on the stack, many times you don't even need to 'pop' the address off the stack, it'll just be part of your arguments to the function. Old school malware used this a lot to 1) run regardless of the memory base address it was loaded at and 2) confuse some disassemblers (you can use silly conditionals that are always true or false to control whether you execute the 'call' instruction or not, forcing the disassembler to try and 'disassemble' the string into valid x86 opcodes)

    提出可以通过修改链接脚本自定义入口点,进一步突破 main 的限制

    与其忽略错误,不如直接改写链接文件,把入口点设成任何你想要的东西,对吧?我可以有一个只由 "void x" 组成的程序,然后按文章的思路继续下去。

    jpegqs查看英文原文

    Can be both, a string and a function: char main [/*x86*/] __attribute__ ((section(".text")) )="WTYH)9Zj8_j7H)9]R" "H)9^\350\0\0\0\0H)1^R" "H))Z8<2u\366j<)9Xj9" ")9j9VY)<$[S_H\xbd^[" "H$@\xcd\200-XP\xf" "\5XP_j<W\xeb\xe2]" "Hello World!\n"; /*Linux_Only!*/

    历次讨论

    同类还值得读

    1. 开源应用架构

      The Architecture of Open Source Applications

      《开源软件架构》(AOSA)是一本在线免费书,邀请知名开源项目的作者亲自剖析其内部设计,涵盖 SQLAlchemy、LLVM、Audacity、Apache、Bash 等系统。

      编程与软件工程上首页 9 次 · 2011–2024aosabook.org编辑精选
    2. 编程语言简史:简短、不完整且多半错误

      A Brief, Incomplete, and Mostly Wrong History of Programming Languages

      一篇以戏谑、故意不准确的方式回顾编程语言史的博客文章,用夸张轶事和讽刺定义串起 Lisp、C、C++、Java、JavaScript、PHP 等语言。

      编程与软件工程上首页 8 次 · 2009–2021james-iry.blogspot.com
    3. SQLite 是如何测试的

      How SQLite is tested

      SQLite 官方文档页,系统介绍 SQLite 的测试体系:多种测试方法(TCL 测试、模糊测试、回归测试、静态分析等)和海量测试用例,展示了这个小型开源项目如何靠极致测试获得…

      编程与软件工程上首页 8 次 · 2009–2025sqlite.org编辑精选
    4. 高级编程语言(2009)

      Advanced programming languages (2009)

      Matt Might 的经典文章,按用途推荐“高级编程语言”:如果追求就业就选主流语言,如果追求表达力、学术研究或创业,则推荐 Haskell、OCaml、Scala 等函数式语…

      编程与软件工程上首页 8 次 · 2009–2022matt.might.net
    5. 我的 Forth 与栈机器经历

      Yosefk - My history with Forth & stack machines

      作者以亲身经历回顾了使用 Forth 语言和栈式机器的历程:既赞叹其简洁优雅、代码量小、可自举的优点,也坦率指出栈操作在实际编程中的痛苦,以及 Forth 社区文化中的问题。

      编程与软件工程上首页 8 次 · 2010–2024yosefk.com编辑精选

    打赏支持

    打赏二维码

    觉得有用,请作者喝杯咖啡。

    WeChat

    关注向阳乔木

    微信公众号「向阳乔木推荐看」

    微信公众号「向阳乔木推荐看」二维码

    微信扫一扫;在微信里打开本页时,长按二维码识别。