你见过或做过的最酷的黑客是什么?

时间:2008-10-10 18:02:54

标签: hardware

作为程序员,我们都将一个非常酷的程序组合在一起,或者以一种有趣的方式将一些硬件拼凑在一起来解决问题。今天我在考虑那些黑客以及它们中的一些是如何被现代技术弃用的(例如,你不再需要破解你的Tivo添加网络端口)。在软件世界中,我们现在将在网页上拖放的内容视为理所当然,但不久之前,这也是一个非常令人兴奋的黑客攻击。

我见过的最糟糕的硬件攻击之一是几年前一家电信公司的前同事完成的。他的办公室里有一台小型便携式电视机,他一整天都在工作时看着它。为了逃脱它,他将一个开关连接到通过他的桌子下面的脚激活的开/关。

您个人见过或做过的最酷的硬件或软件是什么?你现在正在做什么工作?

43 个答案:

答案 0 :(得分:54)

答案 1 :(得分:49)

我记得这个黑客是由Bob Smith编写的,他曾做过旧的DOS时代内存管理器,名为386MAX(或“386 to the Max”)。它不是产品的一部分,它是一个小小的实用程序,他掀起并张贴在某个地方。但是,在网络上我唯一可以找到的这种技术的参考文献是罗伯特柯林斯的DDJ Undocumented Corner November 1996列。

问题

在英特尔推出CPUID instruction之前,很难检查系统上CPU的确切类型和修订级别。事实证明,在386及更高版本的大多数版本中,实际上有一个CPU ID,但它只在一个特定时间可见:在EDX寄存器中重置处理器之后。 (假设计算机的BIOS是唯一对此有合法兴趣的软件。)

问题:如果我们不是BIOS,普通程序如何检索此寄存器值?

背景材料

这个hack依赖于IBM PC兼容计算机的六种不同特性。他们如下:

  1. 从IBM AT及更高版本开始,有一种方法可以在总线上independently disable the A20 address line
  2. 大多数计算机没有在BIOS ROM下方的高内存地址中安装RAM。
  3. 当您读取没有安装内存的内存位置时,大多数IBM PC总线计算机都会返回0xFF。
  4. 0xFF 0xFF 0xFF等是Intel CPU上的非法操作码。
  5. 如果你在内存中安装了一个异常处理程序,它将在这个时代(386到486)的大多数CPU上进行软重启后继续存在。
  6. 在软复位或硬复位时,英特尔处理器会跳转到可寻址存储器顶部的地址,减去16个字节,这就是放置BIOS ROM的原因。
  7. 该计划结合了所有这些琐事的知识,以实现目标。

    The Hack

    结果是DOS命令行程序,它执行以下操作:

    • 安装了非法操作码异常处理程序
    • 关闭总线上的A20地址线
    • 软重启CPU(我认为这是通过BIOS调用)

    当软重启发生时,处理器会尝试跳转到内存顶部减去16个字节,这是ROM启动代码所在的位置。但是,由于A20关闭,它实际上会跳到内存的顶部减去16个字节减去1兆字节。在大多数PC上,那里没有RAM。因此它将从这个不存在的RAM中获取一系列0xFF字节,并尝试执行它。这会产生非法的操作码异常。

    然后,他的异常处理程序将获取EDX(CPUID)的值,并将其存放在他可以找到的地方。然后它会清理混乱(重新打开A20,从保护模式转回到DOS的实模式)并将控制权返回到原始代码。

    当它奏效时,它是天才。 Voila,这是一个简单的命令行DOS程序,可以为您提供CPUID值。

    当然,那里不可避免地存在一些“不太兼容”的PC,当你运行它时会崩溃。好吧。

答案 2 :(得分:40)

嗯,这不是最酷的,但对程序员来说肯定很有趣。

我们为简历数据库项目构建了一个即席查询构建器。它有一些ajaxy部分,基本的想法是,如果你在页面上更改任何,搜索会自动重新运行。 (它是由所有UI小部件的onBlur事件触发的)

所以我们没有真正使用“搜索”或“运行查询”按钮。这使用户感到困惑。所以我们添加了一个什么都没做的搜索按钮。它只是坐在那里。

之所以有效,是因为每次点击搜索按钮时,您刚刚开启的字段中的onBlur事件都会触发。

这使我们的用户群非常高兴。简单的事情。

答案 3 :(得分:32)

这不是我做过的黑客攻击,而是我很久以前工作过的人告诉我的事情(他实际上做了黑客攻击)。

似乎他为盲人和需要阅读文本文件的人工作。所以他想出了如何将文本文件翻译成盲文并使用各种字符打印出来。并且:

当时的打印机是冲击式打印机,因此当打印字符时,打印机构足以打印纸张,留下可以感觉到的印象。由于纸张背面形成的印象,他不得不打印倒置的盲文盲文,这样当纸张翻转时就是正确的。

当然,阅读行为消除了萧条,因此它是一次性读取机制,但我一直认为这是一个非常酷的黑客。

答案 4 :(得分:24)

在进行iPhone的逆向工程工作时,我发现基带中的一个漏洞(处理电话和载波锁的芯片)可以让你随意写零。虽然这起初看起来毫无用处,但很快就会发现这可能比我原先想象的要多得多。通过ARM的工作方式,可以通过在目标中写入单个零来使某些跳转无效,从而使执行路径始终继续向前。这使得软件能够解锁,但很快就被更强大的黑客所取代,这使得你可以完全重新刷新基带。

仍然为这个黑客感到骄傲,不管它现在无用。

答案 5 :(得分:16)

我在大学里用气动阀门做了一个8分频计数器,以便免除其余的气动课程。

答案 6 :(得分:15)

这是一件微不足道的事情,但是当我第一次看到这段代码时(由我的同事开发)我感到震惊,因为这是我从未想到的东西(我添加了评论) :

cglobal x264_sub8x8_dct_sse2, 3,3  ;3,3 means 3 arguments and 3 registers used
.skip_prologue:
    call .8x4
    add  r0, 64                    ;increment pointers
    add  r1, 4*FENC_STRIDE
    add  r2, 4*FDEC_STRIDE
.8x4:
    SUB_DCT4 2x4x4W                ;this macro does the actual transform
    movhps [r0+32], m0             ;store second half of output data
    movhps [r0+40], m1             ;the rest is done in the macro
    movhps [r0+48], m2
    movhps [r0+56], m3
    ret

它通过一次做8x4组来完成4个8x8块变换。但它不会粘贴代码两次(这会浪费代码大小),也不会有8x4函数并调用它两次。也没有循环。相反,它调用“函数”,然后递增指针,然后“直接”进入它并再次执行。

它得到了两全其美:没有函数调用超出原始的开销(因为指针r0,r1和r2在SUB_DCT4中没有递增)没有代码重复,并且没有循环开销。

答案 7 :(得分:14)

今年夏天,我写了一款名为SatelliteRush的游戏。这是一款适用于带有Java和GPS的手机的突围游戏。它可以以两种模式播放:“无聊模式”和“卫星模式”。在无聊模式下,您可以像往常一样使用按钮移动球拍,但在卫星模式下,它使用手机的GPS接收器。你来回奔跑,桨随你移动。

我只在索尼爱立信W760i上进行了测试,并且考虑到GPS位置更新速度相当缓慢且不准确,因此效果相当不错。

到目前为止,我已经制作了这款游戏的“技术测试版”,因此它不是很好看或易于使用。但如果您有带Java的GPS手机,可以在此处下载: http://www.lysator.liu.se/~padrone/temporary/SatelliteRushTest/

修改

现已在Android电子市场上作为免费应用推出Android: https://market.android.com/details?id=se.nekotronic.satelliterush

答案 8 :(得分:11)

Duff's Device。这算数了吗? :)

答案 9 :(得分:10)

Duffs Device,针对上述问题。

The Story of Mel。铁杆黑客。

答案 10 :(得分:10)

我有一台早期的Commodore 64计算机,需要为它编写汇编代码。

问题是,C64没有汇编程序(不管是那个,还是我买不起)。

所以我通过查阅书中的6502操作码并用原始字节创建程序来编写汇编程序。

在某些时候,它能够将汇编代码作为输入,并汇编成一个程序。

我的一位朋友在BASIC为他的PET写了一个反汇编程序。我使用这个程序来反汇编我的汇编程序,然后能够使用我的汇编程序来组装它自己的更新版本。

哦,过去我们不得不跳过的篮球:)

答案 11 :(得分:9)

最酷的黑客(它真的不是真正意义上的黑客,但它和上面的一些答案一样)我曾创造过的是我的Apple // e。

参考手册中有一行表示$ C010是'任意按键'标志。

事实证明这是真的。尽管有内置的密钥重复硬件,但$ C010软开关的高位会告诉您密钥是否已关闭。

他们没有告诉你什么,每个人都发现困难的方法是没有可靠的方法来找出按键是什么。

如果你写了一个小装配程序......(原谅我的错误,我的6502装配很生锈)

  :1
  lda $C010
  cmp #$80
  bcc :1  ; branch if less than? I forget how to do that.
  lda $C000
  jsr $FDF0   ;output the accumulator value to the screen

所以它会循环,直到你按下一个键并通过从$ C000键盘读取开关加载来输出密钥。

但是,如果你运行该程序,它就不会正常工作。

当你拿着一把钥匙的时候肯定会打印出来的东西,当你没有按下时什么都没有,但是公共汽车上有一点延迟(我想,我不是硬件人)所以如果你按了' f'你会得到很多f。但如果你停下来,然后按'g',你会在切换到'g'之前得到一堆'f'。

你可以在苹果中看到这个问题的证据] [Gauntlet的版本,你向一个方向移动,如果你试图向第二个方向移动,你会向原来的方向移动一点,直到你通过了滞后。

它没有任何意义,因为读取$ C000始终是100%准确的,除非你首先扣除$ C010。

我发现这个问题引人入胜,经过数周的演奏后,我终于找到了我仍然认为是我写过的最酷的节目。

程序本身没有任何意义,它做了一些无用的ORA,但由于某种原因它起作用,并且在查询$ C010后它从$ C000产生了正确的值。

这很酷,我写了一篇关于nibble杂志的文章,他们接受了这篇文章,但从未发表过(因为他们已经停业或者因为这篇文章读起来像是15岁的人写的,这是我在哪里)写了一个替换键盘输入程序并将其挂钩到每个人调用以获得键盘输入的零页面位置,并且我能够以编程方式更改键盘重复延迟和重复率,这是因为它连接到硬件中是不可能的。 当然,Apple // e当时正在走出困境,但至今仍是我最酷的黑客。

2010年3月2日更新:通过一些旧文章,我找到了我的小装配程序的打印输出。我在这里张贴它,看看是否有人能弄清楚它为什么会起作用,所以它将永远以数字形式存在于某个地方......

$0300  AD 10 C0  LDA $C010  ; load accumulator with any-key-down flag
$0303  29 80     AND #$80   ; keep only high bit flag
$0305  0D 00 C0  ORA $C000  ; OR accumulate with keyboard soft switch
$0308  10 F9     BPL $0303  ; erm, I forget exactly which branch this is
$030A  09 80     ORA #$80   ; turn the high bit on 
$030C  20 ED FD  JSR $FDED  ; print char in accumulator
$030F  4C 00 30  JMP $0300  ; start again.

没有理由为什么这应该有用,但确实如此。或者做到了。 25年前。

答案 12 :(得分:8)

我的一位朋友正在用更新,更快的OEM主板更换戴尔的主板。然而,他无法使用电源按钮和其他前面板工作 - 连接器尺寸不同,引脚布局不同。我拿了一堆备用跳线和备用电线,然后逐个连接正确的引脚。无需焊接:)

代码方面,我不断留下深刻的印象。我一直认为没有一种优雅的方法来确定fork ed孩子是否成功exec编辑,但actually is

子:

execvp(argv[0], argv);
errval = errno;
write(data->fd, &errval, sizeof(errval));

父:

socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
flag = fcntl(fds[1], F_GETFD) | FD_CLOEXEC;
fcntl(fds[1], F_SETFD, flag);
pid = clone(child, NULL, SIGCHLD, NULL);
if(pid < 0){
        ...
}
close(fds[1]);
/* Read the errno value from the child, if the exec failed, or get 0 if
 * the exec succeeded because the pipe fd was set as close-on-exec.
 */
n = read(fds[0], &ret, sizeof(ret));
if (n < 0) {
        ...
} else if(n != 0){
        /* exec failed */
} else {
        /* exec succeeded */
}

答案 13 :(得分:8)

Steve Wozniak的disk controller

答案 14 :(得分:8)

特斯拉的装置set the record for man-made lightning(42米或130英尺)和科罗拉多斯普林斯的所有灯都熄灭了。

答案 15 :(得分:8)

快速反向平方根 - 一个奇怪的小程序,以某种方式设法计算某事物的平方根,但你从来没有猜到这一点。

http://betterexplained.com/articles/understanding-quakes-fast-inverse-square-root/

答案 16 :(得分:8)

答案 17 :(得分:8)

我们在一些据称是俄罗斯黑客的小公司受到了损害。我自己和其他一些开发人员想看看如何,所以我从我们的服务器上下载了我见过的最优雅的PHP脚本,并立即从我们的实时机器中删除它。

这是一种名为c99shell的特洛伊木马,它做得如此之少,以至于同时它既可怕又美丽。这个东西有一个嵌入式GUI,图像使用base64从PHP输出,所以一切都是自包含的。功能列表生病了!这个东西可以启动shell,扫描连接字符串,锁定自己以及攻击者的其他一些有用的事物。

很漂亮。

办公室里的每个人都认为我很疯狂,但实际上,这段代码确实有很多想法。他们保持文件大小较小,以便偷偷摸摸那些讨厌的上传限制,甚至还有一个base64编码的电子邮件通知,收集了攻击者的所有信息。

答案 18 :(得分:7)

我会告诉你,但如果我承认,他们可能会要求我的高中毕业证书;)

答案 19 :(得分:6)

回到DOS的时代,我写了一个脚本程序来演示我公司的软件。此脚本程序将启动应用程序,然后在应用程序顶部弹出窗口,使用动画类型描述其某些功能,然后关闭窗口,向应用程序提供按键,等待应用程序显示正确的屏幕,然后弹出更多的窗户。它有自己的脚本语言甚至脚本编辑器,因此我可以中断脚本,编辑它,然后继续运行它。最好的部分是它运行在我们的应用程序的未修改版本之上。

整个演示应用程序是用C语言和汇编语言编写的。它挂钩了计时器和键盘中断,以便与应用程序进行交互。我写了一切,包括窗口库。

答案 20 :(得分:5)

我曾经在大学演讲期间为psion 3a编写了一个简单的dos式命令行。它只能做基本的目录列表,浏览,复制和移动,但它看起来是部分 - 全屏小字体。

哦,我为68008编程pong,输入电位器和输出示波器。使用开发板并不是那么难,但是在osc上播放它有一些很酷的东西。

答案 21 :(得分:5)

当然不是我做的,但最近我遇到它并且看起来很酷:

Self-printing Game of Life in C#

几十年来,康威的生命游戏让计算机科学家着迷。虽然它的规则非常简单,但康威的宇宙产生了各种各样的滑翔机,宇宙飞船,振荡器,滑翔机和其他形式的“生命”。印刷程序同样很奇怪,而且 - 相当令人惊讶 - 在计算理论中占有重要地位。

将两者合并后会发生什么?你即将发现,但有一件事是肯定的:极客因素应该很高。

我写了一个包含生命游戏网格的C#程序。程序将游戏网格推进到下一代并打印出自己的副本,并更新网格。您可以获取输出,使用C#编译器进行编译,运行它,然后您将获得下一代游戏。您可以迭代该过程,或手动更改初始网格状态。 “

按照上面的链接获取源代码。

答案 22 :(得分:5)

我写了一个简单的Windows批处理文件,让我在一台速度很慢的机器上快速播放与我的音乐库(f:驱动器)上的某些模式匹配的曲目(在这台机器上打开iTunes大约需要3分钟!)。它通过findstr命令支持正则表达式,并使用mplayer播放曲目。我所要做的就是按Windows + R并键入:

play u2

或:

play "neighbo.+rhood"

或:

play "blink[0-9][0-9][0-9]"

批处理文件在play.bat中就是这样。

cd /d f:
findstr /I /R %1 dirlist.txt > playlist.txt
mplayer -playlist playlist.txt

mplayer和play.bat都应添加到您的路径中。

答案 23 :(得分:4)

我用Excel和Visual Basic为一个小型虚拟机(UDVM)编写了一个汇编程序。您在Excel单元格中编写汇编代码,在另一个工作表中编写内存布局,然后在底部计算机器代码二进制字符串。想象一下每次更改汇编代码时都会对手装配的恐惧。

答案 24 :(得分:4)

C#中的自打印程序('quine'),长度为149个字符:

C# Quine

class P{static void Main(){var S=“class P{{static void Main(){{var S={1}{0}{1};System.Console.Write(S,S,’{1}’);}}}}”;System.Console.Write(S,S,‘”‘);}}

答案 25 :(得分:4)

几年前,我正在开发一个Web界面,并使用一些全新的JS库来实现AJAX功能。 lib只评估了html doc头文件中的JS,但返回的数据太多,不适合头文件。怎么办?

有些讨论显示头文件中的JS可以访问html doc的主体,所以我写了一个通用的'eval the body'函数,它在头文件中返回。在当时非常有用,特别是b / c一个不同的JS库,我们只评估来自正文的eval'd JS,因此这兼容了两个JS库并避免了标题中的任何大小限制!

是的,很简单,但在弄清楚这一点之后整整一个月我觉得非常棒:)

答案 26 :(得分:4)

经过几天的调试拨号服务器经历了无法接受的掉线次数后,我将问题追溯到一个本地认证机制,该机制依赖于正在运行的getty的文本表示。 PID。 getty会产生错误并在其PID包含偶数后跟9时中止,导致调用丢弃,getty重新生成新PID。

发现问题后,我被取消了项目,后来发现“修复”是从

更改数字到文本的转换
sprintf(strval, "%d", pid);

sprintf(strval, "%o", pid);

有人选择将PID转换为 octal ,而不是对身份验证例程进行故障排除,因此无法包含9!

答案 27 :(得分:3)

如果你想要很多具有令人难以置信的黑客攻击的C代码,请尝试International Obfuscated C Code Contest。它们通常不是你想要被捕的东西,但无论如何它们都令人印象深刻。

答案 28 :(得分:3)

不是我:

#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]){
  int i;

  printf("((((");
  for(i=1;i!=argc;i++){
    if(     strcmp(argv[i], "^")==0) printf(")^(");
    else if(strcmp(argv[i], "*")==0) printf("))*((");
    else if(strcmp(argv[i], "/")==0) printf("))/((");
    else if(strcmp(argv[i], "+")==0) printf(")))+(((");
    else if(strcmp(argv[i], "-")==0) printf(")))-(((");
    else                             printf("%s", argv[i]);
  }
  printf("))))\n");
  return 0;
}

答案 29 :(得分:3)

看到我的前同事在三周内从汇编程序中重写一个游戏机一个3d引擎。旧的是慢,我们没有时间改变图形资产了。他在截止日期前两个月开始重写。

同一个人(以及其他一些家伙 - 这是团队合作的行为)做了一个惊人的工作,将10分钟的图形和声音填充到一个64kb的可执行文件中。

http://pouet.net/prod.php?which=1221

答案 30 :(得分:3)

在查看如何在4D中使用TCP时,我在文档中遇到了Duff设备的这种变体:

$SentOK:=False  //A flag to indicate if we made it through all of the calls
Case of 
   : (SMTP_New ($smtp_id)!=0)
   : (SMTP_Host ($smtp_id;<>pref_Server)!=0)
   : (SMTP_From ($smtp_id;vFrom)!=0)
   : (SMTP_To ($smtp_id;vTo)!=0)
   : (SMTP_Subject ($smtp_id;vSubject)!=0)
   : (SMTP_Body ($smtp_id;vMessage)!=0)
   : (SMTP_Send ($smtp_id)!=0)
Else 
   $SentOK:=True  //message was composed and mailed successfully
End case 
If ($smtp_id!=0)  //If a Message Envelope was created we should clear it now
   $OK:=SMTP_Clear ($smtp_id)
End if 

我看着它,并认为它非常聪明(我仍然这样做)。不幸的是,这不是我需要的,我从来没有机会使用它。

答案 31 :(得分:2)

回到高中时,我很自豪能在我的ti-83上写一个3D绘图程序,因为我的父母不会给我买89.

答案 32 :(得分:2)

将扫描仪从打印头中取出。现代版本包括Canon's,但这个技巧实际上已经很老了。

答案 33 :(得分:2)

这是一个老人,但对我来说这是Duff的设备:

http://en.wikipedia.org/wiki/Duff's_device

(出于某种原因,我无法将markdown显示为URL作为链接)


strcpy(to, from, count)
char *to, *from;
int count;
{
    int n = (count + 7) / 8;
    switch (count % 8) {
    case 0: do { *to = *from++;
    case 7:      *to = *from++;
    case 6:      *to = *from++;
    case 5:      *to = *from++;
    case 4:      *to = *from++;
    case 3:      *to = *from++;
    case 2:      *to = *from++;
    case 1:      *to = *from++;
               } while (--n > 0);
    }
}

答案 34 :(得分:2)

使用.ToString()转换字符串始终是我找到的WTF。

答案 35 :(得分:2)

我第一次尝试理解和修改以功能样式编写的代码。我花了一个小时试图了解发生了什么,然后发现所有的工作都是在一行看起来像这样:

for my $row (@data) {
  push @formatted, join ",", map $format[$_]->($data->[$_]), 0..$#$data;
}

我找到了作者,并惊呼道,“你为什么不评论那个?”他的回答是,“评论会有什么帮助?”我试着想到一个,然后失败了。

这段代码告诉我一项我今天发现非常有用的技术。但是我已经了解到这是一种应该经常使用或从不使用的技术,但它介于两者之间。因为,实际上,没有评论会有所帮助。要么你了解那里有一条线,它做了什么,你不需要担心它,否则你将无法理解该代码。

同一个程序员经常做其他令人印象深刻的事情。例如,在之前的工作中,他修改了C库,这样当C程序转储核心时,它不仅仅是转储核心。相反,它会创建一个coredump,然后通过堆栈回溯和附加的coredump向开发团队发送电子邮件。这使他们能够注意到并修复了有问题的cron作业中的错误。

答案 36 :(得分:2)

David Carlisle的TeX诗:

\let~\catcode~`76~`A13~`F1~`j00~`P2jdefA71F~`7113jdefPALLF
PA''FwPA;;FPAZZFLaLPA//71F71iPAHHFLPAzzFenPASSFthP;A$$FevP
A@@FfPARR717273F737271P;ADDFRgniPAWW71FPATTFvePA**FstRsamP
AGGFRruoPAqq71.72.F717271PAYY7172F727171PA??Fi*LmPA&&71jfi
Fjfi71PAVVFjbigskipRPWGAUU71727374 75,76Fjpar71727375Djifx
:76jelse&U76jfiPLAKK7172F71l7271PAXX71FVLnOSeL71SLRyadR@oL
RrhC?yLRurtKFeLPFovPgaTLtReRomL;PABB71 72,73:Fjif.73.jelse
B73:jfiXF71PU71 72,73:PWs;AMM71F71diPAJJFRdriPAQQFRsreLPAI
I71Fo71dPA!!FRgiePBt'el@ lTLqdrYmu.Q.,Ke;vz vzLqpip.Q.,tz;
;Lql.IrsZ.eap,qn.i. i.eLlMaesLdRcna,;!;h htLqm.MRasZ.ilk,%
s$;z zLqs'.ansZ.Ymi,/sx ;LYegseZRyal,@i;@ TLRlogdLrDsW,@;G
LcYlaDLbJsW,SWXJW ree @rzchLhzsW,;WERcesInW qt.'oL.Rtrul;e
doTsW,Wk;Rri@stW aHAHHFndZPqpa.rtMRrgeLinZ.irLtYer.W,:jbye

在此文件上运行pdftex并感到惊讶。

答案 37 :(得分:1)

http://pida.co.uk/黑客会结束Vim / Emacs的火焰大战! (!! 11eleven)

答案 38 :(得分:1)

有一个开关嵌套在循环中,用于循环展开,称为Duff device

dsend(to, from, count)
char *to, *from;
int count;
{
    int n = (count + 7) / 8;
    switch (count % 8) {
    case 0: do { *to = *from++;
    case 7:      *to = *from++;
    case 6:      *to = *from++;
    case 5:      *to = *from++;
    case 4:      *to = *from++;
    case 3:      *to = *from++;
    case 2:      *to = *from++;
    case 1:      *to = *from++;
               } while (--n > 0);
    }
}

它不是那么强大但是它很好地滥用了C语法

答案 39 :(得分:1)

不支持引导加载程序的CPU的引导加载程序。

CPU是rockwell CPU系列成员的衍生产品,它运行它给出的代码。 工具链生成RAM映像(您可以JTAG并运行以进行调试) 或者它产生ROM图像。

有一个链接引导程序。但它只是链条。你必须运行,它只适用于RAM。

万一我觉得很有创意,CPU没有JMP指令。 (我不是在开玩笑。)也没有RST指令。

所以我们需要从文件系统加载程序并运行它,这个CPU非常明确地嵌入并且不想这样做。

文件系统位于Flash ROM中,只能在写入的地址运行。 (它不可重新定位)

因此我使用引导加载程序加载ROM,该引导加载程序将引导加载程序加载到RAM的底部。 CPU写入门阵列,即

1)断言重置。 2)交换芯片选择RAM和ROM 3)释放重置。

CPU最终从RAM运行,准备将文件系统中的代码读入RAM。

它确实有效。 IBM PC-AT让286芯片脱离保护模式的方式让我“受到启发”。

答案 40 :(得分:0)

简单的一个。我的一位早期导师和他的家人一起暑假去了。当他回来时,他立即坐在终点站并键入GMAP例程,编译(清理)并将其推出。我问我是否可以帮助测试,他说他可以“测试”它。咦?显然他在沙滩上很无聊,所以发现了一块平坦的沙子,编码并检查了它 - “沙子检查”。 太棒了。

答案 41 :(得分:0)

多年前,我编写了一个用大块字母显示文本的程序,以便将它们放在我的源文件的标题中,这样我就可以用非常小的字体打印多页。我用一个5x5方形的像素信息构建了一个小表来打印字符。它只有大写字母和数字。所以pa会变成......

####    #
#   #  # #
####  #   #
#     #####
#     #   #

一段时间后,我在IBM PC Technigal Reference附带的原始IBM PC BIOS列表中发现它有一个8x8字符生成器。所以我找到它并从内存转储中提取它。所以我能够生成完整的字符集,所以我可以使用小写字母......

## ###   ####
 ##  ##     ##
 ##  ##  #####
 #####  ##  ##
 ##      ### ##
####

答案 42 :(得分:0)

我曾经在FoxPro(windows)中使用按钮在我编写的第一个程序中生成条形图。这对我来说真的很酷。