好了,轮到我提问了。“我的代码有什么问题?” 它是一个 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
;--------------------
...现在就足够了...