2

好了,轮到我提问了。“我的代码有什么问题?” 它是一个 dos .com 文件 (x86),用 Nasm 编写,并在 FreeDos(不是 DosBox)的引导下运行。

; nasm -f bin -o readmbr.com readmbr.asm

org 100h ; offset where dos will load us

section .text

mov si, 5 ; retry count
read:
mov dx, 80h ; drive
mov cx, 1 ; segment
mov bx, buffer
mov ax, 201h ; read 1 sector
int 13h
jnc goodread

mov ah, 0 ; reset drive
int 13h
dec si
jnz read
jmp exit

goodread:
mov si, buffer
mov cx, 512
top:
lodsb
aam 16
xchg al, ah
call printhex
xchg al, ah
call printhex
mov al, ' '
int 29h
loop top

exit:
int 20h
;mov ah, 4Ch
;int 21h
; ret
printhex:
cmp al, 9
jbe not_alpha
add al, 7
not_alpha:
add al, '0'
int 29h ; print the character in al
ret

section .bss
buffer resb 512

当我在调试器(FreeDos'DEBUG)中逐步执行此操作时,我得到了预期的输出(或多或少),但不是“程序正常终止”,而是“意外的单步断点”(或类似的),并且ip表示我“在树林里”。当我尝试“以速度”运行它时,它会挂起机器,根本没有输出!这些天Dos启动得很快,但一段时间后它仍然会变老。我想是时候换个角度看这个了!

我意识到我已经做了一些“记录较少”的事情 -aam 16例如int 29h- 但这些事情“曾经对我有用”......并且似乎在调试器中工作。我在做什么使机器挂起(根本没有输出)?

Amit,如果您愿意,请告诉我这在 DosBox 中的作用。其他人,感谢您的帮助!

编辑:好的......我“修复”了它。我不知道怎么办!使用“完全无意义的中断”,它可以工作。没有它,结果与以前相同 - 挂起,没有输出。显然,FreeDos 不喜欢int 13h作为第一个中断(?)。不知道为什么。我不记得以前见过这样的事情。这个版本有一个稍微好一点的 hexdump - 也包括 ascii,这应该可以更容易地判断你是否正在查看一个真正的引导扇区。我有一个想法,它不会在 DosBox 中工作......这使得整个练习变得毫无意义......

; nasm f-bin -o readmbr.com readmbr.asm

org 100h

section .bss
    buffer resb 512

section .text

; completely meaningless interrupt!
    mov dl, 13
    mov ah, 2
    int 21h

    mov dx, 80h ; drive
    mov cx, 1 ; sector (not "segment", idiot)
    mov bx, buffer
    mov ax, 201h ; read one sector
    int 13h
    jc exit

; dump 512 bytes as hex, and ascii (if printable), 16 at a time
    mov si, buffer
    mov di, 32 ; loop counter
dumpem:
    call dump16
    dec di
    jnz dumpem

exit:
    ret
;------------------

;--------------------
; print character in al to stdout
; returns: nothing useful
printchar:
    push ax
    push dx
    mov dl, al
    mov ah, 2
    int 21h
    pop dx
    pop ax
    ret
;------------------

;--------------------
dump16:
; prints 16 bytes pointed to by si, as hex and as ascii (if printable)
; returns: si pointed to next byte. ax, cx trashed.

    mov cx, 16
    push si ; save it for the ascii part
top:
    lodsb ; al <- [si], inc si
    aam 16 ; split al into ah and al - four bits per
    xchg al, ah ; we want the high one first
    cmp al, 9
    jbe not_alpha
    add al, 7 ; bump 10 - 15 up to 'A' - 'F'
not_alpha:
    add al, '0'
    call printchar
    xchg al, ah ; swap 'em back and print low nibble
    cmp al, 9
    jbe not_alpha2
    add al, 7
not_alpha2:
    add al, '0'
    call printchar
    mov al, ' '
    call printchar
    loop top

    mov al, '|'
    call printchar
    mov al, ' '
    call printchar

    pop si ; get back pointer to 16 bytes
    mov cx, 16
asciitop:
    lodsb
    cmp al, 20h ; we don't want to print control characters!
    jae printable
    mov al, '.'
printable:
    call printchar
    loop asciitop
; and throw a CR/LF
    mov al, 13
    call printchar
    mov al, 10
    call printchar
    ret
;--------------------

想要 Linux 版本吗?为什么不?可能更有用...

; nasm -f elf32 myprog.asm
; ld -o myprog myprog.o -melf_i386
;
; since only root is going to have access to the MBR,
; run it as root... or if you wish a user to be able to run it...
; as root:
; chown root:root myprog
; chmod +s myprog

global _start

section .data

; on my valuable antique system, this is the first hard drive
; (not necessarily the one I booted from)
; on a more modern system, probably "sda" or so...?

    filename db "/dev/hda", 0

section .bss
    buffer resb 512
    file_desc resd 1

section .text
_start:
    nop

; open the file
    ; don't care about edx, since we're not creating the file
    mov ecx, 0 ; readonly
    mov ebx, filename
    mov eax, 5 ; sys_open
    int 80h

    test eax, eax ; fancy error handler :)
    js exit
    mov [file_desc], eax

; read all 512 bytes
    mov edx, 512
    mov ecx, buffer
    mov ebx, [file_desc]
    mov eax, 3 ; sys_read
    int 80h
    test eax, eax
    js exit

; dump 512 bytes as hex, and ascii (if printable), 16 at a time
    mov esi, buffer
    mov edi, 32
dumpem:
    call dump16
    dec edi
    jnz dumpem

; the exit would close the file, but we'll be nice and close it
    mov ebx, [file_desc]
    mov eax, 6 ; sys_close
    int 80h
    test eax, eax
    js exit

; if we get here, pretend there was no error

    xor eax, eax

exit:

; if there was an error, return it as an exit-code,
; negated for easy readability.
; view it with "echo $?".

    mov ebx, eax
    neg ebx
    mov eax, 1 ; sys_exit
    int 80h
;------------------

;--------------------
; print character in al to stdout
; returns: nothing useful
printchar:
    push edx ; save these, by preference
    push ecx
    push ebx ; C would expect ebx to be preserved
    push eax ; has to be last - it serves as our buffer

    mov ecx, esp ; buffer's on the stack
    mov edx, 1 ; one only please
    mov ebx, 1 ; stdout
    mov eax, 4 ; sys_write
    int 80h

    pop eax
    pop ebx
    pop ecx
    pop edx
    ret
;------------------

;--------------------
dump16:
; prints 16 bytes pointed to by esi, as hex and as ascii (if printable)
; returns: esi pointed to next byte. eax, ecx trashed.

    mov ecx, 16
    push esi ; save it for the ascii part
top:
    lodsb ; al <- [esi], inc esi
    aam 16 ; split al into ah and al - four bits per
    xchg al, ah ; we want the high one first
    cmp al, 9
    jbe not_alpha
    add al, 7 ; bump 10 - 15 up to 'A' - 'F'
not_alpha:
    add al, '0'
    call printchar
    xchg al, ah ; swap 'em back and print low nibble
    cmp al, 9
    jbe not_alpha2
    add al, 7
 not_alpha2:
    add al, '0'
    call printchar
    mov al, ' '
    call printchar
    loop top

    mov al, '|'
    call printchar
    mov al, ' '
    call printchar

    pop esi ; get back pointer to 16 bytes
    mov ecx, 16
asciitop:
    lodsb
    cmp al, 20h ; we don't want to print control characters!
    jae printable
    mov al, '.'
printable:
    call printchar
    loop asciitop
; and throw a linefeed...
    mov al, 10
    call printchar
    ret
;--------------------

...现在就足够了...

4

2 回答 2

1

好的。这是 Linux 版本的输出(比重新启动更容易)。它可怕地“包裹”,但你可以看到它是“LILO”。

FA EB 21 01 B2 01 4C 49 4C 4F 16 07 80 60 FC 47 | úë!.².LILO..`üG
00 00 00 00 FA 9A FA 47 40 F6 3F 30 81 00 80 60 | ....úúG@ö?0.`
16 2B F3 01 B8 C0 07 8E D0 BC 00 08 FB 52 53 06 | .+ó.¸À.м..ûRS.
56 FC 8E D8 31 ED 60 B8 00 12 B3 36 CD 10 61 B0 | VüØ1í`¸..³6Í.a°
0D E8 64 01 B0 0A E8 5F 01 B0 4C E8 5A 01 60 1E | .èd.°.è_.°LèZ.`.
07 80 FA FE 75 02 88 F2 BB 00 02 8A 76 1E 89 D0 | .úþu.ò»..v.Ð
80 E4 80 30 E0 78 0A 3C 10 73 06 F6 46 1C 40 75 | ä0àx.<.s.öF.@u
2E 88 F2 66 8B 76 18 66 09 F6 74 23 52 B4 08 B2 | .òfv.f.öt#R´.²
80 53 CD 13 5B 72 57 0F B6 CA BA 7F 00 42 66 31 | SÍ.[rW.¶Êº.Bf1
C0 40 E8 60 00 66 3B B7 B8 01 74 03 E2 EF 5A 53 | À@è`.f;·¸.t.âïZS
8A 76 1F BE 20 00 E8 DD 00 B4 99 66 81 7F FC 4C | v.¾ .èÝ.´füL
49 4C 4F 75 29 5E 68 80 08 07 31 DB E8 C7 00 75 | ILOu)^h..1ÛèÇ.u
FB BE 06 00 89 F7 B9 0A 00 B4 9A F3 A6 75 0F B0 | û¾..÷¹..´ó¦u.°
02 AE 75 0A 06 55 B0 49 E8 CD 00 CB B4 40 B0 20 | .®u..U°IèÍ.Ë´@° 
E8 C5 00 E8 B2 00 FE 4E 00 74 07 BC E8 07 61 E9 | èÅ.è².þN.t.¼è.aé
5C FF F4 EB FD 60 55 55 66 50 06 53 6A 01 6A 10 | \ÿôëý`UUfP.Sj.j.
89 E6 53 F6 C6 60 74 6E F6 C6 20 74 14 BB AA 55 | æSöÆ`tnöÆ t.»ªU
B4 41 CD 13 72 0B 81 FB 55 AA 75 05 F6 C1 01 75 | ´AÍ.r.ûUªu.öÁ.u
3F 52 06 B4 08 CD 13 07 72 B4 51 C0 E9 06 86 E9 | ?R.´.Í..r´QÀé.é
89 CF 59 C1 EA 08 92 40 83 E1 3F F7 E1 93 8B 44 | ÏYÁê.@á?÷áD
08 8B 54 0A 39 DA 73 94 F7 F3 39 F8 77 8E C0 E4 | .T.9Ús÷ó9øwÀä
06 86 E0 92 F6 F1 08 E2 89 D1 41 5A 88 C6 EB 1C | .àöñ.âÑAZÆë.
B4 42 5B BD 05 00 60 CD 13 73 16 4D 74 BA 31 C0 | ´B[½..`Í.s.Mtº1À
CD 13 61 4D EB F0 66 50 59 58 88 E6 B8 01 02 EB | Í.aMëðfPYXæ¸..ë
E1 8D 64 10 61 C3 66 AD 66 09 C0 74 0A 66 03 46 | ád.aÃf­f.Àt.f.F
10 E8 61 FF 80 C7 02 C3 C1 C0 04 E8 03 00 C1 C0 | .èaÿÇ.ÃÁÀ.è..ÁÀ
04 24 0F 27 04 F0 14 40 60 BB 07 00 B4 0E CD 10 | .$.'.ð.@`»..´.Í.
61 C3 00 00 00 00 44 63 40 F6 3F 30 73 20 80 01 | aÃ....Dc@ö?0s .
01 00 83 EF FF FF 3F 00 00 00 41 45 31 09 00 EF | ..ïÿÿ?...AE1..ï
FF FF 82 EF FF FF 80 45 31 09 D0 87 20 00 00 00 | ÿÿïÿÿE1.Ð ...
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA | ..............Uª
于 2013-07-21T12:37:56.647 回答
0

在此处输入图像描述

查找在 dosbox 环境中运行的代码的附加输出。我想在这里提出一个有趣的观点,当我将 int29h 替换为 int 10h/ah=0x0e 时,输出不同,十六进制值发生了变化。

在此处输入图像描述

于 2013-07-18T17:59:17.433 回答