では、私が質問する番です。「私のコードの何が問題なのですか?」これは、Nasm で記述された dos .com ファイル (x86) であり、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
-しかし、これらのことは「以前は機能していました」...そしてデバッガーで機能するようです。マシンがハングアップする (出力がまったくない) 原因は何ですか?
アミット、もしよろしければ、これが DosBox で何をするのか教えてください。他の誰でも、助けてくれてありがとう!
編集:わかりました...「修正」しました。方法がわからない!「まったく無意味な割り込み」で、動作します。それがなければ、前と同じ結果 - 出力なしでハングします。int 13h
どうやら、FreeDos は最初の割り込み (?) として気に入らないようです。理由はわかりません。私はこれまでにこのようなものを見た記憶がありません。このバージョンには、わずかに優れた 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
;--------------------
...そして今はそれで十分です...