追溯到根源:我们直接从MBR驱动计算机

我再次将Linux映像部署到USB驱动器(由于某种原因,结果证明是Manjaro,但这是一个完全不同的故事),奇怪的想法浮现在脑海:BIOS看到了USB闪存驱动器,然后呢?好吧,是的,这里有一个MBR,很可能是GRUB,并且……并且,一旦在MBR中弹出了其他人的自定义代码,这意味着一个来自Adygea的简单人可以在“大型”计算机上但在操作系统之外进行编程。


而且由于使用高级语言进行此类操作实在太大胆了,而且我们不了解汇编程序,因此我们将直接针对8086的操作码进行维护。



介绍


计划:


  1. 退出 #
  2. 退出 Hello, Habrauser!
  3. 显示输入字符(您已经可以娱乐孩子了)。

免责声明和免责声明


为了不打扰人声,我们将训练 QEMU. , , dd x86- . .


MBR, - (?) (?) — , Enter. .


— , ( !) - . ( .) ! .


MBR


:


  • , Bootstrap Area .
  • , ( ) 0x7c00 ( Compaq).
  • , , ( , --). : 640KB, . ( , .)


, — , .


, , , , (sic!) . , ( - ), , .


, - «» 80- «-» 90-, : «» «». «», Lode Runner, «».


«» +


!



-, , , , , — errata.


, , , .


:


  • , MOV, INT, ADD, DIV — , , , . , , , .
  • , , , : imm8, r16, r/m32, rel8. , , (, ) , , DIV BL F6 F3 (DIV r/m8, , , — .) F6DIV, NEG, ( opcode extension — .)


, , dd, , , , , — , , -. -, … , POSIX , !


➜  $ echo "48 65 6c 6c 6f 2c 20 48 61 62 72 21" | xxd -r -p 
Hello, Habr!%    

:


➜  $ echo -e "# Comment\n48 65 6c 6c 6f 2c 20  # First line\n48 61 62 72 21        # Last line" | sed 's/#.*$//g' | xxd -r -p
Hello, Habr!%  

( sed-, xxd , hex-dump. ?)


, , .


, sh-
#!/bin/sh

IN="${1:-/dev/stdin}"
OUT="${2:-/dev/stdout}"

> $OUT

while read line
do
    echo "$line" | sed 's/#.*$//' | xxd -r -p >> $OUT
done < $IN


: LF (aka \n), . , , , , - , — .

— , !


➜  $ ./build loader.mbr loader.img && stat -f %z loader.img
512

512 — , . , .




, bin- 512B, . « dd /dev/zero, !» — . , c ( , ipython) !


,
# 0x0000:0x007F (0-127)
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00

# 0x0080:0x00FF (128-255)
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00

# 0x0100:0x017F (256-383)
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00

# 0x0180:0x0200 (384-512)
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00


, , , QEMU, Exception'.



, , ( ), MBR.


,
...

# 0x0180:0x0200 (384-445)
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00

# Partition 1     0x01BE:0x01CD (446-461) 
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00

# Partition 2     0x01CE:0x01DD (462-477)
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00

# Partition 3     0x01DE:0x01ED (478-493)
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00

# Partition 4     0x01EE:0x01FD (494-509)
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00

# MBR Signature   0x1FE:0x1FF (510-511)
00 00


, :


# MBR Signature   0x1FE:0x1FF (510-511)
55 AA


:


$ qemu-system-i386 -nic none loader.img

-nic none , PXE, — .


, BIOS , ! , !



, !


, . :


# 0x0000:0x007F (0-127)
B4 0E                      # Set a console output mode
B0 23                      # Set an octothorp sign
CD 10                      # Call a print function

00 00
00 00 00 00 00 00 00 00


( , 512).


, QEMU !



, , , , :


  • B4 0EAH 0E ( mov ah, 0e), BIOS ( ), , .
  • B0 23 — : AL #. ? «»? — ASCII- man ascii!
  • CD 10 — : BIOS-, . , AL AH, , : .

, AL :


  • $ (B0 24)
  • % (B0 25)
  • á (B0 A0, )


, , . .


- . — printf('Hell of word') .


, , :


,
# 0x0000:0x007F (0-127)
B4 0E    # Set a console output mode

B0 0A    # LF
CD 10

B0 48    # H
CD 10    # print 

B0 65    # e
CD 10

B0 6C    # l
CD 10

B0 6C
CD 10

B0 6F    # o
CD 10

B0 2C    # ,
CD 10

B0 20    # SPC
CD 10

B0 48    # H
CD 10

B0 61    # a
CD 10

B0 62    # b
CD 10

B0 72    # r
CD 10

B0 61    # a
CD 10

B0 75    # u
CD 10

B0 73    # s
CD 10

B0 65    # e
CD 10

B0 72    # r
CD 10

B0 21    # !
CD 10

00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00

,


, , :



:


  • ,
  • , ,
  • , BIOS' — - , Booting from Hard Disk....

, :


# 0x0000:0x007F (0-127)
B8 00 06          # Clear screen
CD 10

B4 0E             # Set a console output mode
BE 80 7C          # Place 0x0080 + 0x7c00 = 0x7c80 into SI
AC                # Load a byte at address SI into AL, increment SI
3C 00             # AL == 00?
74 06             # If yes, go to +6 bytes (to zeroes)
CD 10             # Print a char in AL
EB F7             # Go to -7 bytes (to AC opcode)

00 00 00 00 00
00 00 00 00 00 00 00 00

...

# 0x0080:0x00FF (128-255)
48 65 6C 6C 6F 2C 20 48   # Hello, H
61 62 72 61 75 73 65 72   # abrauser
21                        # !

00 00 00 00 00 00 00
00 00 00 00 00 00 00 00

:


  • : , 0x7c00, . ? data- ( ), ( !), SI — .
  • SI AC ( LODS). , SI AL, SI! , !
  • . , . , , ?
  • AL, , — ( , 6 ), 00 .
  • AL - , BIOS-...
  • … 7 — LODS!

, . , .


, - . : BIOS- . … . — ( , — ).


, . printer.mbr typewriter.mbr.

, :


# 0x0000:0x007F (0-127)
B4 07   # Clear screen
B0 00   #
CD 10   #

B4 00   # Set Get keystroke mode
CD 16   # Read a char -> AL

3C 0D   # AL == 0D? (CR, Return pressed)
75 06   # If no, go to +6 bytes

B4 0E   # Print CR
CD 10   #
B0 0A   # Then print NL

B4 0E   # Print a char
CD 10   # 

EB EC   # Go to -20 bytes

1


:


  • ( QEMU) .
  • AH = 00h 16h, , , AL.
  • , : OD (aka CR aka ), Return/Enter, , ( -), .
  • CR CR, LF, , Enter.
  • AL OD, , .
  • : -- , ! 20 .

, :



, :


  • , «» ,
  • , ,
  • «»: Backspace , .

. emacs- .



, .



, - :



, . , :


# 0x0000:0x007F (0-127)
B8 12 00          # Set VGA mode 640x480x16
CD 10

B4 0E             # Set a console output mode
B3 00             # Set FG color to black
FE C3             # Color++

BE 80 7C          # Place 0x0080 + 0x7c00 = 0x7c80 into SI
AC                # Load a byte at address SI into AL, increment SI
3C 00             # AL == 00?
74 F6             # If yes, go to -10 bytes (to FE C3)

CD 10             # Print a char in AL
EB F7             # Go to -9 bytes (to AC)

00
00 00 00 00 00 00 00 00

...

# 0x0080:0x00FF (128-255)
48 65 6C 6C 6F 2C 20 48   # Hello, H
61 62 72 61 68 61 62 72   # abrahabr
21 20                     # ! 

00 00 00 00 00 00
00 00 00 00 00 00 00 00

color-printer.mbr


  • (? ? BIOS?) , ,
  • BL (. , .)
  • FE BL
  • : , , , .

.



, .






, :
— !
— .
, Sublime Text :
— --, ! !
.


- .




UPD: eisaev, Andrew_Pinkerton, MrSmith33, Anthony1025 , , .


All Articles