-1
B8 00 B8 8E E8 B4 00 CD 16 65 88 00 EF F2

该程序最初有 16 个字节,但我决定牺牲 2 个字节来支持不稳定的输入位置。这是以前的版本(0 0 位置):

65 88 06 00 00

那么可能的候选人是:

EF F2 -> 
C3 ->
CF..CB..CC..CE

那些单字节的人也不是帮手。我的微弱想法是改变(不使用)段组件。删除 65 并使用默认数据段。不幸的是,它似乎不起作用。

我做错了什么?昨天我将模块减小到 13 字节大小,尽管到目前为止它还不稳定,以至于每个符号都出现在单独的屏幕位置。

4

1 回答 1

0

好吧,它显然是 16 位实模式 x86 代码、用于 DOS 或其他平面二进制文件的 .com 文件。

$echo 'B8 00 B8 8E E8 B4 00 CD 16 65 88 00 C3' | udcli -x -16

0000000000000000 b800b8           mov ax, 0xb800          
0000000000000003 8ee8             mov gs, ax              
0000000000000005 b400             mov ah, 0x0             
0000000000000007 cd16             int 0x16                
0000000000000009 658800           mov [gs:bx+si], al      
000000000000000c c3               ret

它假定bx并且si具有一些可接受的值,因此0xb800:bx+si指向当前文本视频模式使用的视频内存区域。嗯,这是可能的,但我不会推荐它。

无论如何,如果仍然允许对寄存器值的假设,它可以缩短至少 4 个字节。如果可以假设它bx具有si有用的值(见上文),那么它di也可能0xb800:di指向当前文本视频模式使用的视频内存区域。

00000000  B800B8            mov ax,0xb800
00000003  8EC0              mov es,ax
00000005  98                cbw
00000006  CD16              int 0x16
00000008  AA                stosb
00000009  C3                ret

首先设置并存储到ax(几种BIOS文本视频模式的段地址)。0xb800es

然后将字节al(0) 转换为 word ax,将 的符号位扩展alax,结果ax= 0。

int 16h然后使用 BIOS 键盘中断( ah= 0)从键盘读取输入(并等待输入,如有必要)。ASCII码输入al,扫描码输入ah

最后将 ASCII 代码存储到视频内存(到[es:di])以stosb在屏幕上打印字符,然后返回到 DOS(或任何操作系统)ret

编辑:实际上可以将大小降低到 12 个字节,并且仍然有一个稳定的输出地址,如下所示:

00000000  6800B8            push word 0xb800
00000003  1F                pop ds
00000004  31C0              xor ax,ax
00000006  CD16              int 0x16
00000008  A20000            mov [0x0],al
0000000B  C3                ret

希望这可以帮助。

于 2013-01-09T19:56:15.270 回答